##########################
# lcmtocsv.py
#
# author: Eric Martin 2018 MBARI
#
# script to convert lcm log files from a single channel with known lcm type into a csv
#
###########################

import sys
import lcm
import argparse
import importlib
import pandas as pd

def process_event(event, package, module):

	package_ = importlib.import_module(package)
	lcm_t = eval('package_.' + module)
	msg = lcm_t.decode(event.data)

	return msg

def event_headers(event, package, module):

    # decode the data if its the channel we want
    msg = process_event(event, package, module)

    # ignore the methods in this list
    fields = [field for field in dir(msg) if not field.startswith('_')]

    cols = list()

    #lcm event info
    cols.append("evt_channel")
    cols.append("evt_number")
    cols.append("evt_timestamp")

    for field in fields:
        value = getattr(msg, field)

        if callable(value):
            continue
        if type(value) is str or type(value) is unicode:
            s = str(field).replace(',', '_')
            cols.append("%s" % s)
            continue

        try:
            if len(value) is 0:
                continue

            for idx, val in enumerate(value):
                s = str(field).replace(',', '_')
                s += "_%s"% idx
                cols.append("%s" % s)

        except TypeError as te:
            try:
                s = str("%s" % field)
                cols.append(s)

            except TypeError as te:
                continue
        except AttributeError as ae:
    		continue
    return cols

def event_data(event, package, module):

    data = list()


    msg = process_event(event, package, module)

    # ignore the methods in this list
    fields = [field for field in dir(msg) if not field.startswith('_')]

    #lcm event info
    data.append("%s" % event.channel)
    data.append("%i" % event.eventnum)
    data.append("%i" % event.timestamp)

    for field in fields:
        value = getattr(msg, field)

        if callable(value):
            continue

        if type(value) is str or type(value) is unicode:
            s = str(value).replace(',', '_')
            data.append("%s" % s)
            continue

        if type(value) is int:
            data.append("%i" % value)
            continue

        if type(value) is bool:
            data.append("%i" % value)
            continue
        try:
            if len(value) is 0:
                continue

            for val in value:
                data.append("%f" % val)

        except TypeError as te:
            try:
                data.append("%f" % value)

            except TypeError as te:
                continue

        except AttributeError as ae:
            continue;
    return data


if __name__ ==  "__main__":

    parser = argparse.ArgumentParser(description='process lcm log files by individual channels')
    parser.add_argument('channel', type=str, help='lcm channel name to convert')
    parser.add_argument('in_file', type=str, help='lcm log filename to convert', nargs=argparse.REMAINDER)
    parser.add_argument('--module', type=str, default='pcomms_t', help='known lcm type name')
    parser.add_argument('--package', type=str, default='gss', help='package name of lcm type module')

    args = parser.parse_args()

    df = None
    cols = None
    i = 0
    rows  = list()
    # load the logfile for reading

    for logname in args.in_file:

        sys.stderr.write("Processing File: %s\r\n" % logname)
        log = lcm.EventLog(logname, "r")

        for event in log:
            if event.channel == args.channel:

                # data
                rows.append(event_data(event, args.package, args.module))

                # head
                if cols is None: cols = event_headers(event, args.package, args.module)



                # df
                #df_temp = pd.DataFrame([row,],columns=cols)

                #if df is None:
                #    df = df_temp
                #else:
                #    df = df.append(df_temp)

                i+=1

                # Write out a progress into stderr
                percentdone = float(log.tell()) / float(log.size()) * 100.0
                sys.stderr.write('Progress: %10.2f | Records Found: %i\r' % (percentdone,i))
                sys.stderr.flush()
