import sys
import warnings
if not sys.warnoptions:
    warnings.simplefilter("ignore")
import traceback
import h5py
import numpy as np
from asammdf import MDF, Signal

# return value
RET_OK            = 0
RET_VAR_NOT_FOUND = 1
RET_EXCEPTION     = 2
RET_PARAMETER_ERR = 3

def internal_write_string(Ah5, ALst, AStr, AMdf):
    if AStr not in ALst:
        return False, ""
    v = Ah5[AStr]
    ss = v[:, 0]
    s = "".join([chr(itm) for itm in ss])
    sStr = Signal(samples=[], timestamps=[], name=AStr, comment=s)
    signals = [sStr]
    AMdf.append(signals, comment=AStr + "=" + s)
    return True, s

def internal_write_double(Ah5, ALst, AName, AMdf):
    if AName not in ALst:
        return False, 0
    v = Ah5[AName]
    d = np.array([v[0, 0]], dtype=np.float64)
    t = np.array([0], dtype=np.float64)
    sDouble = Signal(samples=d, timestamps=t, name=AName)
    signals = [sDouble] 
    AMdf.append(signals, comment=AName + "=" + str(d))
    return True, d

# mat2MDF(r'C:\LC_Ramdisk\mdf\Mul.mat', r"C:\LC_Ramdisk\mdf\Mul.MF4")
# mat2MDF(r'C:\LC_Ramdisk\mdf\Mul.mat', r"C:\LC_Ramdisk\mdf\Mul.MDF", "2.00")
def mat2MDF(AMatFileName, AMDFFileName, AMDFVersion = "4.10", ACompression = "False"):
    print("conversion started on " + AMatFileName)
    f = h5py.File(AMatFileName, 'r')
    lstNames = list(f.keys())
    
    # create a new mdf file
    mdf4 = MDF(version=AMDFVersion)
    try:
        # Comment
        internal_write_string(f, lstNames, "Comment", mdf4)
        internal_write_string(f, lstNames, "MeasurementComments", mdf4)
        internal_write_string(f, lstNames, "DynamicComments", mdf4)
        # MeasurementStartTime
        if not internal_write_double(f, lstNames, "MeasurementStartTime", mdf4): 
            return RET_VAR_NOT_FOUND

        # MeasurementStopTime
        if not internal_write_double(f, lstNames, "MeasurementStopTime", mdf4): 
            return RET_VAR_NOT_FOUND

        # MeasurementStartTimeStr
        internal_write_string(f, lstNames, "MeasurementStartTimeStr", mdf4)

        # MeasurementStopTimeStr
        internal_write_string(f, lstNames, "MeasurementStopTimeStr", mdf4)

        # ECU_LIST, ['TD', 'XCPSim']
        r, lst = internal_write_string(f, lstNames, "ECU_LIST", mdf4)
        if not r:
            return RET_VAR_NOT_FOUND

        # TIME_LIST, ['TD_TIME_DAQ_10ms_DAQ', 'XCPSim_TIME_DAQ_100ms', 'TIME_StatisticsCAN1__StdData', 'TIME_StatisticsCAN1__BusLoad', 'TIME_Application__Connected', 'TIME_sine']
        r, lst = internal_write_string(f, lstNames, "TIME_LIST", mdf4)
        if not r:
            return RET_VAR_NOT_FOUND
        time_list = lst.split(",")

        # variable list within each time
        for tme in time_list:
            print("Writing: " + tme)
            r, lst = internal_write_string(f, lstNames, tme + "_LIST", mdf4)
            if r:                
                if tme not in lstNames:
                    print(tme + " not found")
                    continue
                var_list = lst.split(",")
                v = f[tme]
                t = v[0, :]
                signals = []
                for var in var_list:
                    v = f[var]
                    a = np.array(v[0, :], dtype=np.float64)
                    if (len(t) == len(a)):
                        d = Signal(samples=a, timestamps=t, name=var)
                        signals.append(d)
                    else:
                        print('signal ' + var + ' time count ' + str(len(t)) + ' <> sample count ' + str(len(a)))
                mdf4.append(signals, comment=tme + ' variables')        
        return RET_OK
    except:
        traceback.print_exc()
        return RET_EXCEPTION

    finally:
        # save new file
        compressionCode = 0
        if ACompression == "True":
            compressionCode = 2
        mdf4.save(AMDFFileName, overwrite=True, compression=compressionCode)
        print("Saved: " + AMDFFileName + ", version = " + AMDFVersion)

if __name__ == '__main__':
    if len(sys.argv) != 5:
        print("Parameter error")
        for i in range(0, len(sys.argv)):
            print("Parameter " + str(i) + ": " + sys.argv[i])
        sys.exit(RET_PARAMETER_ERR)
    else:
        sys.exit(mat2MDF(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4]))
        