# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals, division
from eight import *

from .lca import LCA
from .utils import wrap_functional_unit
try:
    from bw2data import calculation_setups
except ImportError:
    calculation_setups = None
import numpy as np


class MultiLCA(object):
    """Wrapper class for performing LCA calculations with many functional units and LCIA methods.

    Needs to be passed a ``calculation_setup`` name.

    This class does not subclass the `LCA` class, and performs all calculations upon instantiation.

    Initialization creates `self.results`, which is a NumPy array of LCA scores, with rows of functional units and columns of LCIA methods. Ordering is the same as in the `calculation_setup`.

    """
    def __init__(self, cs_name, log_config=None):
        if calculation_setups is None:
            raise ImportError
        assert cs_name in calculation_setups
        try:
            cs = calculation_setups[cs_name]
        except KeyError:
            raise ValueError(
                "{} is not a known `calculation_setup`.".format(cs_name)
            )
        self.func_units = cs['inv']
        self.methods = cs['ia']
        self.lca = LCA(demand=self.all, method=self.methods[0], log_config=log_config)
        self.lca.logger.info({
            'message': 'Started MultiLCA calculation',
            'methods': list(self.methods),
            'functional units': [wrap_functional_unit(o) for o in self.func_units]
        })
        self.lca.lci(factorize=True)
        self.method_matrices = []
        self.results = np.zeros((len(self.func_units), len(self.methods)))
        for method in self.methods:
            self.lca.switch_method(method)
            self.method_matrices.append(self.lca.characterization_matrix)

        for row, func_unit in enumerate(self.func_units):
            self.lca.redo_lci(func_unit)
            for col, cf_matrix in enumerate(self.method_matrices):
                self.lca.characterization_matrix = cf_matrix
                self.lca.lcia_calculation()
                self.results[row, col] = self.lca.score

    @property
    def all(self):
        """Get all possible databases by merging all functional units"""
        return {key: 1 for func_unit in self.func_units for key in func_unit}
