import pandas as pd
import sys
import platform

if sys.version_info[0] < 3:
    from StringIO import StringIO
else:
    from io import StringIO


def independant_newline():
    if platform.system() == 'Windows':
        return '\r\n'
    else:
        return '\n'


class Reader:
    def __init__(self):
        pass

    @classmethod
    def read_pa(cls, path):
        current_param = ''
        propper_file = []
        head_written = False
        with open(path, 'r') as file_str:
            for line in file_str:
                if 'PARAMETER' in line:
                    current_param = line.replace(' PARAMETER: ', '')
                    current_param = current_param.replace('\n', '')
                    current_param = current_param.replace('\r', '')
                    current_param = current_param.replace(' ', '')
                elif 'ITERATION' in line:
                    if not head_written:
                        tmp = line.replace('\r', '')
                        tmp = tmp.replace('\n', '')
                        propper_file.append(tmp)  # line.replace('\r\n', ''))
                        propper_file.append(' "Parameter"{}'.format(independant_newline()))
                        head_written = True
                    else:
                        continue
                else:
                    tmp = line.replace('\r', '')
                    tmp = tmp.replace('\n', '')
                    propper_file.append(tmp)  # line.replace('\r\n', ''))
                    propper_file.append(' "{}"{}'.format(current_param, independant_newline()))
                    # propper_file.append(' "' + current_param + '"' + independant_newline())
        out = ''.join(propper_file)
        file_str = StringIO(out)
        data = pd.read_csv(file_str, sep=r"\s+")
        return data

    @classmethod
    def read_scgrp(cls, path):
        """
        Able to read the horribly formatted _scgrp file
        Returns a pandas data frame
        -------
        """

        # get group names
        group_names = {}
        i = 0
        propper_file = []
        head_written = False
        with open(path, 'r') as searchfile:
            for line in searchfile:
                if 'GROUP NAME' in line:
                    split = line.rsplit(' ')
                    group_names[i] = split[3]
                    i += 1
                elif 'PARAMETER NAME' in line:
                    if not head_written:
                        tmp = line.replace('\n', '')
                        tmp = tmp.replace('\r', '')
                        propper_file.append(tmp)
                        propper_file.append(' "group"{}'.format(independant_newline()))
                        head_written = True
                    else:
                        continue
                else:
                    tmp = line.replace('\n', '')
                    tmp = tmp.replace('\r', '')
                    propper_file.append(tmp)
                    propper_file.append(group_names[i - 1] + independant_newline())

        file_str = StringIO(''.join(propper_file))
        data = pd.read_csv(file_str, sep=r"\s+")
        return data, group_names

    @classmethod
    def modify_data_sc(cls, data_frame):
        data_frame.sort_values(['COMPOSITE SCALED SENSITIVITY'], ascending=False, inplace=True)
        list_of_params = data_frame['PARAMETER NAME']
        values = data_frame['COMPOSITE SCALED SENSITIVITY']
        return list_of_params, values

    @classmethod
    def modify_data_so(cls, data_frame):
        data_frame.sort_values(['LEVERAGE'], ascending=False, inplace=True)
        list_of_params = data_frame['OBSERVATION or PRIOR NAME']
        values = data_frame['LEVERAGE']
        return list_of_params, values

    @classmethod
    def modify_data_w(cls, data_frame):
        data_frame.sort_values(['WEIGHTED RESIDUAL'], ascending=False, inplace=True)
        list_of_params = data_frame['OBSERVATION or PRIOR NAME']
        values = data_frame['WEIGHTED RESIDUAL']
        return list_of_params, values

    @classmethod
    def modify_data_r(cls, data_frame):
        data_frame.sort_values(['RESIDUAL'], ascending=False, inplace=True)
        list_of_params = data_frame['OBSERVATION or PRIOR NAME']
        values = data_frame['RESIDUAL']
        return list_of_params, values

    @classmethod
    def modify_data_sd(cls, data_frame, list_of_params):
        # get first slice = observation variables
        observations = data_frame.ix[:, 0]
        num_of_obs = len(data_frame.index)
        frames = []

        for i, column in enumerate(data_frame):
            if i == 0 or i == 1:
                continue
            # get current param from data
            parameter = data_frame[column]
            param_name = [column] * num_of_obs

            tmp = pd.DataFrame(columns=['Observation', 'ObservationIndex', 'Parameter', 'Data'])
            tmp['Observation'] = observations
            tmp['Parameter'] = pd.Series(param_name)
            tmp['ObservationIndex'] = observations.index
            tmp['Data'] = parameter
            frames.append(tmp)
        out = pd.concat(frames)

        if list_of_params:
            out = out[out.Parameter.isin(list_of_params)]

        # print("got following list")
        # print(listOfParams)

        # with pd.option_context('display.max_rows', 999, 'display.max_columns', 10):
        #    print out
        return out

    @classmethod
    def read_calibration(cls, path):
        return cls.__read_csv(path, ' ')

    @classmethod
    def read_calibration_without_first4(cls, path):
        data = cls.__read_csv(path, ' ', header=3)
        data = data.dropna()
        return data

    @classmethod
    def read_calibration_without_first_and_last(cls, path):
        data = cls.__read_csv(path, ' ', skiprows=1)
        data = data.dropna()
        return data

    @classmethod
    def __read_csv(cls, path, seperator, **kwargs):
        """

        Parameters
        ----------
        path: the path to the csv file
        seperator: seperator of the given csv file

        Returns: a pandas dataframe with the csv information
        -------

        """
        try:
            data = pd.read_csv(path, delim_whitespace=True, **kwargs)
            data.columns = pd.core.strings.str_strip(data.columns.values)
            return data
        except:
            return None
