#-------------------------------------------------------------------------------
# Name:          Output Manager
# Purpose:       Manages the output of the experimental results (product concentrations, ) in image, csv, json format
# Authors:       Eric N
#
# Last Version:  22.09.2022
# Copyright:     (c) Institute of Technical Biocatalysis TUHH
# Licence:       GNU GPL-v3 
#-------------------------------------------------------------------------------
import openpyxl
import os
import datetime
import pandas as pd
import json
import matplotlib.pyplot as plt

excelName = 'RunResults'

class OutputManager():
    def __init__(self,outputPath,PumpMode):
        
        self.PumpMode = PumpMode
        self.nExperiment = 1

        self.paths = {}
        self.CURRENT_DATE = str(datetime.date.today())
        path = '/'.join((outputPath,self.CURRENT_DATE,'Run_'))
        i = 1
        while os.path.isdir(path+str(i)):
            i +=1

        self.paths['Base'] = path+str(i)
        self.paths['Images'] = self.paths['Base'] + '/images'
        self.paths['Results'] = self.paths['Base'] + '/dataResults'

        if not os.path.isdir(self.paths['Base']):
            os.makedirs(self.paths['Base'])
            os.makedirs(self.paths['Images'])
            os.makedirs(self.paths['Results'])

        self.paths['excelFile'] = '/'.join((self.paths['Results'],excelName+'.xlsx'))

        self.createExcel()

    def createExcel(self):
        # creates the excel file with a header in row 1.
        header = ['Experiment-No.','c_in(NAD+) [mM]','c_in(Sodium F.) [mM]','Verweilzeit [s]','c_out(NADH) [mM]']
        wb = openpyxl.Workbook()
        page = wb.active
        page.title = 'Parameters & Results'
        page.append(header)
        wb.save(self.paths['excelFile'])

    def outputExperiment(self,experiment):
        self.outputExcel(experiment)
        self.outputJSON(experiment)
        self.outputCSV(experiment)
        self.outputFigures(experiment)
        self.nExperiment += 1

    def outputExcel(self,experiment):
        # takes the four parameters needed for the matlab code from the experiment
        s1 = experiment['TargetConcentrationS1']
        s2 = experiment['TargetConcentrationS3']
        tres = experiment['ResidenceTime']
        #print(s1)
        #print(s2)
        #print(tres)
        cNADH = experiment['average_final_cNADH']
        #print(cNADH)
        
        # appends the experiment number and the data to the excel file created in __init__.
        data = [self.nExperiment, s1, s2, tres, cNADH]
        wb = openpyxl.load_workbook(self.paths['excelFile'])
        page = wb.active
        page.append(data)
        wb.save(self.paths['excelFile'])

    def outputJSON(self,experiment):
        '''
        Helper function to output an experiment to the desired json file
        '''
        tempExperiment = experiment.copy()
        #del tempExperiment['FigureAbs']
        del tempExperiment['FigureCnv']
        filePath = '/'.join((self.paths['Results'],'Exp_%i_%s.json'%(self.nExperiment,experiment['GenFileName'])))

        with open(filePath,'w') as fp:
            json.dump(tempExperiment,fp,indent=4,sort_keys=True)

    def outputCSV(self,experiment):
        '''
        Helper function to output an experiment to the desired csv file
        '''

        filePath = '/'.join((self.paths['Results'],'Exp_%i_%s.csv'%(self.nExperiment,experiment['GenFileName'])))

        header = pd.DataFrame(columns=['idx','value'])
        header.loc[0] = ['Name:',experiment['Name']]
        header.loc[1] = ['Filename:',experiment['GenFileName']]
        header.loc[2] = ['ResTime:',experiment['ResidenceTime']]
        if self.PumpMode == 1:
            header.loc[3] = ['TotalFlowrate:',experiment['TotalFlowrate']]
        if self.PumpMode == 2 or self.PumpMode == 3:
            header.loc[3] = ['FlowrateS1:',experiment['FlowrateS1']]
            header.loc[4] = ['FlowrateS2:',experiment['FlowrateS2']]
        if self.PumpMode == 3:
            header.loc[5] = ['FlowrateS3:',experiment['FlowrateS3']]
            header.loc[6] = ['FlowrateS4:',experiment['FlowrateS4']]
        header.loc[7] = [' ',' ']
        header.to_csv(filePath,sep ='\t',index = False,header = False)
        
        column_names = ['Time [s]','Abs [-]','cNADH [mmol/l]','Flow [ul/min]','Temp [°C]','STY','Conv']
        out = pd.DataFrame(columns=column_names)
        #out = out.rename_axis(index='idx')
        out.loc[:,'Time [s]'] = experiment['times']
        out.loc[:,'Abs [-]'] = experiment['maxAb']
        out.loc[:,'cNADH [mmol/l]'] = experiment['cNADH']
        out.loc[:,'Flow [ul/min]'] = experiment['FlowRates']
        out.loc[:,'Temp [°C]'] = experiment['Temperatures']
        out.loc[:,'STY'] = experiment['STY']
        out.loc[:,'Conv'] = experiment['conversion']
        
        out.to_csv(filePath,sep ='\t',mode = 'a',float_format = '%.3f',index = False)
    
    def outputFigures(self,experiment):
        '''
        Helper function to create and output a figure
        '''
        filePath = '/'.join((self.paths['Images'],'Exp_%i_%s_AbVsWl.png'%(self.nExperiment,experiment['GenFileName'])))

        experiment['FigureAbs'],ax = plt.subplots()
        ax.plot(experiment['wavelengths'],experiment['Absorbances'][0])
        ax.set_xlabel('wavelengths')
        ax.set_ylabel('Absorbance')
        ax.grid(True)
        experiment['FigureAbs'].savefig(filePath)
        plt.close(experiment['FigureAbs'])

        filePath = '/'.join((self.paths['Images'],'Exp_%i_%s_ConVsT.png'%(self.nExperiment,experiment['GenFileName'])))

        experiment['FigureCnv'].savefig(filePath)

    def getPaths(self):
        return self.paths

if __name__ == '__main__':
    path = 'C:\\Users\\HiWi\\Desktop\\seabreeze-kinetic-enzyme-pj-master\\OverhaulEN'
    out = OutputManager(path)
    '''experiment = {}
    experiment['TargetConcentrationS1'] = 2
    experiment['TargetConcentrationS3'] = 3
    experiment['ResTimes'] = 7
    experiment['average_final_cNADH'] = 9

    out.add(experiment)
    out.add(experiment)'''
