import struct
import argparse
import csv
from glob import glob


def convert_file(fname): 
    with open(fname, 'rb') as f:
        begin = False
        keys = ['type','short_name','format','long_name','units','size']
        data_defs = []
        
        # GET HEADER
        while begin is False:
            fl = f.readline()
            
            tokens = fl.split()
            
            for idx, token in enumerate(tokens):
                tokens[idx] = token.decode('utf-8')
                
            if tokens[1] == 'binary':
                pass
            elif tokens[1] == 'begin':
                begin = True
            else:
                data_def = dict.fromkeys(keys)
                data_def['type'] = tokens[1]
                data_def['short_name'] = tokens[2]
                data_def['format'] = tokens[3]
                data_def['long_name'] = tokens[4].strip(',')
                data_def['units'] = tokens[5].strip(',')
                
                data_defs.append(data_def)
        
        # GENERATE STRUCT
        struct_str = "<"
        struct_len = 0
        for dt in data_defs:
            if dt['type'] == 'float':
                struct_str += 'f'
                struct_len += 4
            elif dt['type'] == 'integer':
                struct_str += 'i'
                struct_len += 4
            elif dt['type'] == 'short':
                struct_str += 'h'
                struct_len += 2
            else: # double
                struct_str += 'd'
                struct_len += 8
        
        print(f'Struct Decoding String: {struct_str}, {struct_len} bytes.')
        
        # Create the data storage
        data_keys = []
        for dt in data_defs:
            data_keys.append(dt['short_name'])
        
        print(f'Data Fields: {data_keys}')
        data_file = dict.fromkeys(data_keys)
        for idx, field in enumerate(data_file):
            data_file[field] = []
        
        ct = 0
        try: 
            while True:
                packet = f.read(struct_len)
                if len(packet) == 0: break
                data_packet = struct.unpack(struct_str, packet)

                ct +=1
                for idx, field in enumerate(data_file):
                    data_file[field].append(data_packet[idx])
        except Exception as e:
            print(f'Exception: {e}')
        print(f'{ct} records unpacked') 
        
        #convert to dataframe
        print(f'Writing to CSV: {fname+".csv"}')
        csv_data = list()
        csv_keys = list()
        for key, value in data_file.items():
            csv_keys.append(key)
            csv_data.append(value)
        
        
        with open(fname+'.csv','w') as f:
            writer = csv.writer(f,lineterminator='\n')
            writer.writerow(csv_keys)
            writer.writerows(zip(*csv_data))
        
        
        print(f'Writing info to TXT: {fname+".txt"}')
        #ok we got this far, write a txt file that describes the csv file
        with open(fname+".txt",'w') as f_out:
            f_out.write(f'{fname}\n')
            for dt in data_defs:
                for idx, field in enumerate(dt):
                    f_out.write(f'{field}: {dt[field]}, ')
                f_out.write('\n')
        
        print('Conversion Complete.\n')
        return

if __name__ == '__main__': 

    parser = argparse.ArgumentParser(description="Convert a Dorado Log File into a CSV file")
    parser.add_argument('files', metavar='FILE', type=str, nargs='+',
        help='input files')

    args = parser.parse_args()
    file_names = list()

    for file in args.files:
        file_names += glob(file)
    
    print(file_names)

    for file in file_names:
        print(f'\n\nConverting file: {file}')
        try:
            convert_file(file)
        except IndexError:
            print('Error Converting File');



