"""
Created on 12 Apr 2014

@author: tessonec
"""


import pandas as pd
import spg.base as spgb
import spg.utils as spgu

# from spg.utils import newline_msg, evaluate_string, load_configuration


class DataFrameIterator:
    def __init__(self, df, filter=[]):
        self.data = df
        self.filter = filter

    def __iter__(self):
        if len(self.filter) > 0:
            df_coalesced = self.data.groupby(self.filter)

            for minimal_gr in sorted(df_coalesced.groups):
                minimal_idx = df_coalesced.groups[minimal_gr]
                minimal_df = self.data.loc[minimal_idx]

                yield minimal_df

        else:
            yield self.data


# from spg.plot import DataFrameIterator


class BaseDataLoader:
    def describe_variables(self):
        for v in self.variables:
            red_d = self.data[v].unique()
            print(
                "%-16s: %4s values || %s -- %s"
                % (v, len(red_d), min(red_d), max(red_d))
            )

    def describe_configuration(self):
        print("variables      : %s" % (", ".join(self.variables)))
        print("  + separated  : %s" % (self.separated_vars))
        print("  + coalesced  : %s" % (self.coalesced_vars))
        print("  + independent: %s" % (self.independent_var))
        print("output columns : %s " % (", ".join(self.output_columns)))

    def setup_output_columns(self, oc):
        self.output_columns = oc
        self.data = self.full_dataframe[self.variables + self.output_columns]

    #

    def get_separated_values(self):

        ret = []
        for outer_df in DataFrameIterator(self.data, self.separated_vars):
            ret.append([outer_df[v].unique()[0] for v in self.separated_vars])
        return ret

    def get_coalesced_values(self):

        ret = []
        for inner_df in DataFrameIterator(self.data, self.coalesced_vars):
            ret.append([inner_df[v].unique()[0] for v in self.coalesced_vars])

        return ret


class SPGDataLoader(BaseDataLoader):
    """
    A class that constructs the plots.
    It exposes
    self.parameter_file: spg file name
    self.base_name:
    self.datafile_name:

    self.simulation: the MultIterator that describes the simulation

    self.full_dataframe : ALl the data in the table
    self.variables
    self.constants
    """

    def __init__(self, simulation_filename):

        full_name, self.path, self.base_name, extension = spgu.translate_name(
            simulation_filename
        )
        self.simulation = spgb.MultIteratorParser(open(f"{self.base_name}.spg"))
        self.datafile_name = "%s.csv" % (self.base_name)

        self.full_dataframe = pd.read_csv(self.datafile_name)

        settings_output = self.simulation.stdout_configuration
        self.output_columns = list(settings_output.keys())

        self.constants = {}
        self.variables = []
        for vn in list(self.full_dataframe.keys()):
            if vn in self.output_columns:
                continue
            all_values = self.full_dataframe[vn].unique()
            if len(all_values) > 1:
                self.variables.append(vn)
            else:
                self.constants[vn] = self.full_dataframe[vn].unique()[0]

        self.settings = self.simulation.input_configuration

        self.settings.update(settings_output)

        self.data = self.full_dataframe[self.variables + self.output_columns]

        print("[__init__] constants: %s" % list(self.constants.keys()))
        print(
            "[__init__] independent variables:",
            self.separated_vars,
            self.coalesced_vars,
            self.independent_var,
        )
        print("[__init__] output columns: %s" % self.output_columns)

    def mean(self):
        self.data = (
            self.data.groupby(self.separated_vars + self.coalesced_vars + [self.x_axis])
            .mean()
            .reset_index()
        )

    def std(self):
        self.data = (
            self.df.groupby(self.separated_vars + self.coalesced_vars + [self.x_axis])
            .std()
            .reset_index()
        )
