import os

import numpy as np
import pandas as pd
from igor2.binarywave import load as loadibw

import src.g5505_utils as utils


import h5py

ROOT_DIR = os.path.abspath(os.curdir)

def read_xps_ibw_file_as_dict(filename):

    """ Reads ibw files from multiphase chemistry group, which contain xps spectra and acquisition settings."""

    file_obj = loadibw(filename)

    required_keys = ['wData','data_units','dimension_units','note'] 
    if sum([item in required_keys for item in file_obj['wave'].keys()]) < len(required_keys):
        raise ValueError('This is not a valid xps ibw file. It does not satisfy minimum adimissibility criteria.')
    
    file_dict = {}
    path_tail, path_head = os.path.split(filename)

    # Group name and attributes
    file_dict['name'] = path_head
    file_dict['attributes_dict'] = {}
 
    # Convert notes of bytes class to string class and split string into a list of elements separated by '\r'. 
    notes_list = file_obj['wave']['note'].decode("utf-8").split('\r')
    exclude_list = ['Excitation Energy']
    for item in notes_list:
        if '=' in item:
            key, value = tuple(item.split('='))
            # TODO: check if value can be converted into a numeric type. Now all values are string type
            if not key in exclude_list:
                file_dict['attributes_dict'][key] = value

    # TODO: talk to Thorsten to see if there is an easier way to access the below attributes
    dimension_labels = file_obj['wave']['dimension_units'].decode("utf-8").split(']')
    file_dict['attributes_dict']['dimension_units'] = [item+']' for item in dimension_labels[0:len(dimension_labels)-1]]

    # Datasets and their attributes

    file_dict['datasets'] = []

    dataset = {}
    dataset['name'] = 'spectrum'
    dataset['data'] = file_obj['wave']['wData']
    dataset['data_units'] = file_obj['wave']['data_units']
    dataset['shape'] = dataset['data'].shape
    dataset['dtype'] = type(dataset['data'])   

    # TODO: include energy axis dataset

    file_dict['datasets'].append(dataset)
    

    return file_dict

def copy_file_in_group(source_file_path, dest_file_obj : h5py.File, dest_group_name):
    # Create copy of original file to avoid possible file corruption and work with it.

    tmp_file_path = utils.make_file_copy(source_file_path)

    # Open backup h5 file and copy complet filesystem directory onto a group in h5file
    with h5py.File(tmp_file_path,'r') as src_file:
        dest_file_obj.copy(source= src_file['/'], dest= dest_group_name)

    if 'tmp_files' in tmp_file_path:
        os.remove(tmp_file_path)


def read_txt_files_as_dict(filename : str ):


    #TODO: this may be prone to error if assumed folder structure is non compliant 
    file_encoding = 'utf-8'
    if 'RGA' in filename: #TODO: it does not work with separator as none :(. fix for RGA
        #end_of_header = 'Channel,  Mass(amu),     Name,                 Cal Factor,  Noise Floor, CEM Status',
        table_header = 'Time(s)      Channel#1   Channel#2   Channel#3   Channel#4   Channel#5   Channel#6   Channel#7   Channel#8'
        separator = None
    elif 'Pressure' in filename: 
        table_header = 'Date	Time	Vapore-Pressure 1 in 	Vapore-Pressure 2 in 	Baratron 1 in 	Baratron 2 in 	Baratron 3 in 	Baratron 4 in 	Temp. Ice-Sample in 	Temp. Heated-Sample in 	Temp. Cooler 1 in 	Temp. Cooler 2 in 	Flow  Gas 1 in 	Pressure Chamber in 	X in 	Y in 	Z in 	None in 	Temp. Sealing in 	Flow Ice-Sample in'      
        separator = '\t'
    #elif 'gas' in filename:
    #    end_of_header = 'Date_Time	HoribaNO	HoribaNOy	Thermo42C_NO	Thermo42C_NOx	APHA370 CH4'
    elif 'Humidity_Sensors' in filename:
        table_header = 'Date	Time	RH1[%]	RH2[%]	RH3[%]	RH4[%]	RH5[%]	RH6[%]	RH7[%]	RH8[%]	T1[°C]	T2[°C]	T3[°C]	T4[°C]	T5[°C]	T6[°C]	T7[°C]	T8[°C]	DP1[°C]	DP2[°C]	DP3[°C]	DP4[°C]	DP5[°C]	DP6[°C]	DP7[°C]	DP8[°C]'
        separator = '\t'
        file_encoding = 'latin-1'
    elif 'ICAD' in filename and 'HONO' in filename:
        table_header = 'Start Date/Time (UTC)	Duration (s)	NO2 (ppb)	NO2 Uncertainty (ppb)	H2O (ppb)	H2O Uncertainty (ppb)	CHOCHO (ppb)	CHOCHO Uncertainty (ppb)	File Number	Light Intensity	#ICEDOAS iter.	Cell Pressure	Ambient Pressure	Cell Temp	Spec Temp	Lat	Lon	Height	Speed	GPSQuality	0-Air Ref. Time	0-Air Ref. Duration	0-Air Ref. File Number	0-Air Ref. Intensity	0-Air Ref. Rel Intensity	0-Air Ref. Intensity valid	MeasMode	SampleSource'
        separator = '\t' 
        file_encoding = 'latin-1'       
    elif 'ICAD' in filename and 'NO2' in filename:
        table_header = 'Start Date/Time (UTC)	Duration (s)	NO2 (ppb)	NO2 Uncertainty (ppb)	H2O (ppb)	H2O Uncertainty (ppb)	CHOCHO (ppb)	CHOCHO Uncertainty (ppb)	File Number	Light Intensity	#ICEDOAS iter.	Cell Pressure	Ambient Pressure	Cell Temp	Spec Temp	Lat	Lon	Height	Speed	GPSQuality	0-Air Ref. Time	0-Air Ref. Duration	0-Air Ref. File Number	0-Air Ref. Intensity	0-Air Ref. Rel Intensity	0-Air Ref. Intensity valid	MeasMode	SampleSource'
        separator = '\t'
        file_encoding = 'latin-1'
    else:
        return {}
        #raise ValueError('intrument_folder must be set as a either "RGA" or "Pressure"')

    # Read header as a dictionary and detect where data table starts
    header_dict = {}
    data_start = False    
    # Work with copy of the file for safety
    tmp_filename = utils.make_file_copy(source_file_path=filename)

    #with open(tmp_filename,'rb',encoding=file_encoding,errors='ignore') as f:
    with open(tmp_filename,'rb') as f:
        table_preamble = []
        for line_number, line in enumerate(f):        
            
            if table_header in line.decode(file_encoding):   
                list_of_substrings = line.decode(file_encoding).split(separator)             
                data_start = True  
                column_names = []
                for i, name in enumerate(list_of_substrings):
                    column_names.append(str(i)+'_'+name) 

                #print(line_number, len(column_names ),'\n')
                break
            # Subdivide line into words, and join them by single space. 
            # I asumme this can produce a cleaner line that contains no weird separator characters \t \r or extra spaces and so on.
            list_of_substrings = line.decode(file_encoding).split()
            # TODO: ideally we should use a multilinear string but the yalm parser is not recognizing \n as special character
            #line = ' '.join(list_of_substrings+['\n'])
            #line = ' '.join(list_of_substrings)     
            table_preamble.append(' '.join(list_of_substrings))# += new_line  

        header_dict["table_preamble"] = table_preamble

   
    # TODO: it does not work with separator as none :(. fix for RGA
    try:
        df = pd.read_csv(tmp_filename, 
                        delimiter = separator, 
                        header=line_number, 
                        #encoding='latin-1',
                        encoding = file_encoding,
                        names=column_names,
                        skip_blank_lines=True)
   
        df_numerical_attrs = df.select_dtypes(include ='number')
        df_categorical_attrs = df.select_dtypes(exclude='number')
        numerical_variables = [item for item in df_numerical_attrs.columns]       

        # TODO: 
        if 'Pressure' in tmp_filename:
            df_categorical_attrs['timestamps'] = [ df_categorical_attrs.loc[i,'0_Date']+' '+df_categorical_attrs.loc[i,'1_Time'] for i in df.index]
            df_categorical_attrs = df_categorical_attrs.drop(columns=['0_Date','1_Time'])

        categorical_variables = [item for item in df_categorical_attrs.columns]
        ####
        #elif 'RGA' in filename:
        #    df_categorical_attrs = df_categorical_attrs.rename(columns={'0_Time(s)' : 'timestamps'})

        ###
        file_dict = {}
        path_tail, path_head = os.path.split(tmp_filename)

        file_dict['name'] = path_head
        # TODO: review this header dictionary, it may not be the best way to represent header data
        file_dict['attributes_dict'] = header_dict
        file_dict['datasets'] = []
        ####

        if numerical_variables:
            dataset = {}
            dataset['name'] = 'numerical_variables'
            dataset['data'] = df_numerical_attrs.to_numpy()
            dataset['shape'] = dataset['data'].shape
            dataset['dtype'] = type(dataset['data'])       
            #dataset['data_units'] = file_obj['wave']['data_units']
            file_dict['datasets'].append(dataset)
            rows,cols = dataset['shape']

            dataset = {}
            numerical_variables= [item.encode("utf-8") for item in numerical_variables]
            dataset['name'] = 'numerical_variable_names'
            dataset['data'] = np.array(numerical_variables).reshape((1,cols))
            dataset['shape'] = dataset['data'].shape
            dataset['dtype'] = type(dataset['data'])
            file_dict['datasets'].append(dataset)            
        
        #if 'timestamps' in categorical_variables:
        #    dataset = {}
        #    dataset['name'] = 'timestamps'
        #    dataset['data'] = df_categorical_attrs['timestamps'].to_numpy().reshape((rows,1))
        #    dataset['shape'] = dataset['data'].shape
        #    dataset['dtype'] = type(dataset['data'])
        #    file_dict['datasets'].append(dataset)            
        #    categorical_variables.remove('timestamps')

        if categorical_variables:
            dataset = {}
            dataset['name'] = 'categorical_variables'
            dataset['data'] = df_categorical_attrs.loc[:,categorical_variables].to_numpy()
            dataset['shape'] = dataset['data'].shape
            dataset['dtype'] = type(dataset['data'])
            file_dict['datasets'].append(dataset)    

            dataset = {}
            categorical_variables = [item.encode("utf-8") for item in categorical_variables]
            dataset['name'] = 'categorial_variable_names'
            dataset['data'] = np.array(categorical_variables).reshape((1,len(categorical_variables)))
            dataset['shape'] = dataset['data'].shape
            dataset['dtype'] = type(dataset['data'])
            file_dict['datasets'].append(dataset)    

    except:
        return {}

    return file_dict

def main():

    inputfile_dir = '\\\\fs101\\5505\\People\\Juan\\TypicalBeamTime'

    file_dict = read_xps_ibw_file_as_dict(inputfile_dir+'\\SES\\0069069_N1s_495eV.ibw')

    for key in file_dict.keys():
        print(key,file_dict[key])


if __name__ == '__main__':

    main()

    print(':)')