import sys
import os
import re

from util import IOOperations, SCurves, ChannelCounts, ReferenceValues, ExtremeValues, DetectDefects, Calculus

class Main:

    def __init__(self, pathToFolder:str, doExport:bool, specialCalculations = [])-> None:
        """Function to find all input files and calls the needed functions for the analysis

        Parameters
        ------
        pathToFolder : str
        Path to the folder with the txt files
        """

        self.io = IOOperations()
        self.scurve = SCurves()
        self.counts = ChannelCounts()
        self.reference = ReferenceValues()
        self.deviation = ExtremeValues()
        self.defects = DetectDefects()
        self.calc = Calculus()

        _files = [f for f in os.listdir(pathToFolder) if os.path.isfile(os.path.join(pathToFolder, f))]

        print("\nDetected defect channels\n")

        defective_channels_dict = dict()

        for f in _files:
            if re.search(r".txt$",f) is None:
                continue
            else:
                raw_data = self.io.readConnResults(os.path.join(pathToFolder, f))
                self.scurve.performAllAnalysis(raw_data)
                if "scurve" in specialCalculations:
                    if (doExport == "True") or (doExport == "1"):
                        self.io.exportSCurves(self.scurve.sCurve, raw_data.get("asic_nr"), pathToFolder)
                self.counts.performAllAnalysis(self.scurve.channel_array)
                if "avg_multi" in specialCalculations:
                    avg_multi_even = self.reference.calculateReferenceAverages(self.counts.counts[1])
                    avg_multi_odd = self.reference.calculateReferenceAverages(self.counts.counts[2])
                    if (doExport == "True") or (doExport == "1"):
                        self.io.exportCountComparison(avg_multi_even, True, raw_data.get("asic_nr"), pathToFolder, "AvgMulti_even_")
                        self.io.exportCountComparison(avg_multi_odd, False, raw_data.get("asic_nr"), pathToFolder, "AvgMulti_odd_")
                if "avg_dist" in specialCalculations:
                    self.avg_even = self.calc.calculateNAverageOnList(self.counts.counts[1], 9)
                    self.avg_odd = self.calc.calculateNAverageOnList(self.counts.counts[2], 9)
                    if (doExport == "True") or (doExport == "1"):
                        self.io.exportCountComparison([self.counts.counts[1], self.avg_even], True, raw_data.get("asic_nr"), pathToFolder, "Avg_even_")
                        self.io.exportCountComparison([self.counts.counts[2], self.avg_odd], False, raw_data.get("asic_nr"), pathToFolder, "Avg_odd_")
                if "dev" in specialCalculations:
                    self.dev_even = self.calc.calculateDeviationBetweenLists(self.counts.counts[1], self.avg_even)
                    self.dev_odd = self.calc.calculateDeviationBetweenLists(self.counts.counts[2], self.avg_odd)
                    if (doExport == "True") or (doExport == "1"):
                        self.io.exportCountComparison([self.counts.counts[1], self.avg_even, self.dev_eben], True, raw_data.get("asic_nr"), pathToFolder, "Avg_Dev_even_")
                        self.io.exportCountComparison([self.counts.counts[2], self.avg_odd, self.dev_odd], False, raw_data.get("asic_nr"), pathToFolder, "Avg_Dev_odd_")
                print("\nASIC %d\n"%(raw_data.get("asic_nr")))
                filtered_even = self.deviation.filterExtremeValues(self.counts.counts[1], 0.25)
                filtered_odd = self.deviation.filterExtremeValues(self.counts.counts[2], 0.25)
                if "filter_multi" in specialCalculations:
                    list_filtered_even = []
                    list_filtered_odd = []
                    for i in range(100):
                        filtered_even = self.deviation.filterExtremeValues(self.counts.counts[1], i*0.01)
                        list_filtered_even.append(self.deviation.calculateNumberOfFilteredValues(self.counts.counts[1], filtered_even))
                        filtered_odd = self.deviation.filterExtremeValues(self.counts.counts[2], i*0.01)
                        list_filtered_odd.append(self.deviation.calculateNumberOfFilteredValues(self.counts.counts[1], filtered_odd))
                    if (doExport == "True") or (doExport == "1"):
                        self.io.exportFilterThresholds(list_filtered_even, 0, 0.01, pathToFolder, raw_data.get("asic_nr"), "filterNumEven_")
                        self.io.exportFilterThresholds(list_filtered_odd, 0, 0.01, pathToFolder, raw_data.get("asic_nr"), "filterNumOdd_")

                if "avg_multi_filter" in specialCalculations:
                    avg_filter_multi_even = self.reference.calculateReferenceAverages(filtered_even)
                    avg_filter_multi_odd = self.reference.calculateReferenceAverages(filtered_odd)
                    if (doExport == "True") or (doExport == "1"):
                        self.io.exportCountComparison(avg_filter_multi_even, True, raw_data.get("asic_nr"), pathToFolder, "AvgFilterMulti_even_")
                        self.io.exportCountComparison(avg_filter_multi_odd, False, raw_data.get("asic_nr"), pathToFolder, "AvgFilterMulti_odd_")
                avg_filter_even = self.calc.calculateNAverageOnList(filtered_even, 9)
                avg_filter_odd = self.calc.calculateNAverageOnList(filtered_odd, 9)
                dev_filter_even = self.calc.calculateDeviationBetweenLists(self.counts.counts[1], avg_filter_even)
                dev_filter_odd = self.calc.calculateDeviationBetweenLists(self.counts.counts[2], avg_filter_odd)
                if (doExport == "True") or (doExport == "1"):
                    self.io.exportCountComparison([self.counts.counts[1], filtered_even, avg_filter_even, dev_filter_even], True, raw_data.get("asic_nr"), pathToFolder, "overall_even")
                    self.io.exportCountComparison([self.counts.counts[2], filtered_odd, avg_filter_odd, dev_filter_odd], False, raw_data.get("asic_nr"), pathToFolder, "overall_odd")


                defects_even = self.defects.findDefectiveChannels(dev_filter_even, raw_data.get("asic_nr"), True)
                defects_odd = self.defects.findDefectiveChannels(dev_filter_odd, raw_data.get("asic_nr"), False)
                defective_channels_dict[raw_data.get("asic_nr")] = {"even" : defects_even, "odd" : defects_odd}
                print("")
                if (doExport == "True") or (doExport == "1"):
                    pass
 
        self.io.exportDetectedDefects(defective_channels_dict, pathToFolder)
if __name__ == "__main__":
    if len(sys.argv) >= 3:
        main = Main(sys.argv[1], sys.argv[2], sys.argv[3])
    else:
        print("Please specify path to folder and if data should be exported!")