import pandas as pd
import numpy as np

class DiagramParser:
    def __init__(self, system_config: dict):
        self.data = pd.DataFrame({})
        self.signals = [system_config["Closure_signal"],
                        system_config["Squeeze_signal"],
                        system_config["Welding_signal"],
                        system_config["Release_signal"],
                        system_config["Oncomming_signal"]]
        # TODO: Переменные в Python именуются в lowercase либо snake_case.
        self.boolDict = {}
        self.floatDict = {}
        self.timingsDict = {}
        self.theor_mode = False

    def setData(self, path):
        # TODO: Методы в Python именуются в lowercase либо snake_case.
        # TODO: Данный метод устанавливает какой-то режим, читает CSV, наполняет словари некими данными.
        #  Декомпозировать на разные методы, каждый из которых будет решать какую-то свою задачу.
        if not path:
            self.theor_mode = True
        else:
            self.data = pd.read_csv(path)

            # TODO: 2 цикла ниже: дублирование кода. Устранить.
            for signalName in self.data.columns:
                # TODO: if isinstance...
                if type (self.data[signalName].iloc[0]) == np.bool:
                    self.boolDict[signalName] = self._getBoolChanges(signalName)

            for signalName in self.data.columns:
                # TODO: if isinstance...
                if type (self.data[signalName].iloc[0]) == np.float64:
                    self.floatDict[signalName] = self._getFloatChanges(signalName)
            
            for key, items in self.boolDict.items():
                # TODO: Писать так условия - моветон. Как вариант, можно применить конструкцию match - case.
                if key == self.signals[0]: name = "closure"
                elif key == self.signals[1]: name =  "compression"
                elif key == self.signals[2]: name =  "welding"
                elif key == self.signals[3]: name =  "opening"
                elif key == self.signals[4]: name =  "oncomming"

                self.timingsDict[name] = []
                len_items = len(items)
                for i, item in enumerate(items):
                    if item[1] == 'high':
                        if i < len_items-1:
                            self.timingsDict[name].append([items[i][0], items[i+1][0]])
                        else:
                            self.timingsDict[name].append([items[i][0], items[i][0]+0.01])
        
    def getBoolDict (self) -> dict:
        # TODO: сделать через декоратор @property:
        #  @property
        #  def bool_dict(self) -> dict:
        #      return self._bool_dict
        # TODO: Методы в Python именуются в lowercase либо snake_case.
        return self.boolDict
    
    def getFloatDict (self) -> dict:
        # TODO: сделать через декоратор @property:
        # TODO: Методы в Python именуются в lowercase либо snake_case.
        return self.floatDict
    
    def getRealTimings(self) -> dict:
        # TODO: сделать через декоратор @property:
        # TODO: Методы в Python именуются в lowercase либо snake_case.
        return self.timingsDict
    
    def getMode(self) -> bool:
        # TODO: сделать через декоратор @property:
        # TODO: Методы в Python именуются в lowercase либо snake_case.
        return self.theor_mode
    
    def _getBoolChanges(self, signalName) -> list:
        # TODO: Методы в Python именуются в lowercase либо snake_case.
        timeCode = self.data['time']
        signal_values = self.data[signalName]
        changes = []
        # TODO: if len(signal_values)...
        if len(signal_values) > 0:
            changes.append([float(timeCode.iloc[0]), 'high' if bool(signal_values.iloc[0]) else 'low'])

            for i in range(1, len(signal_values)):
                if signal_values.iloc[i] != signal_values.iloc[i - 1]:
                    changes.append([float(timeCode.iloc[i]), 'high' if bool(signal_values.iloc[i]) else 'low'])
        
        return changes
    

    def _getFloatChanges(self, signalName) -> list:
        # TODO: Методы в Python именуются в lowercase либо snake_case.
        timeCode = self.data['time']
        signal_values = self.data[signalName]
        changes = []

        if len(signal_values) > 0:
            for i in range (len(signal_values)):
                changes.append([float(timeCode.iloc[i]), float(signal_values.iloc[i])])
        
        return changes


        
    