import logging
import lcm
import numpy
from LCM.HandlerBase import LcmHandlerBase


logger = logging.getLogger("backseat")


class LcmLogReader(LcmHandlerBase):

    def __init__(self):
        self.data = {}

    def clear(self):
        self.data = {}

    def read_log(self, log_name: str):
        """
        Read a lcm log into memory. Store the data in a python dictionary.

        :param log_name: str containing lcm log file path
        :return: updates 'data' class member
        """

        log = lcm.EventLog(log_name, "r")
        logger.info('Unpacking LCM events from log: {}'.format(log_name))
        for event in log:
            msg = self.decode(event.data)

            for name in self.get_item_names(msg):
                item = self.get_variable(name, msg)
                timestamp = msg.epochMillisec / 1000.0
                self.unpack_item(event.channel, item, timestamp)

    def unpack_item(self, channel, item, timestamp):
        """
        Unpack ByteArray|IntArray|FloatArray|DoubleArray|StringArray to a python dictionary

        :param channel: str containing the channel name on which the item was received
        :param item: a ByteArray|IntArray|FloatArray|DoubleArray|StringArray item
        :param timestamp: epoch seconds timestamp for the item data
        :return: updates 'data' class member
        """
        if channel not in self.data:
            # create new entry for channel
            self.data[channel] = {}

        name = item.name
        if name not in self.data[channel]:
            # create a new data entry for the item
            self.data[channel][name] = {
                'value': [],
                'time': [timestamp]
            }
            try:
                # add item units...
                self.data[channel][name]['unit'] = item.unit
            except AttributeError:
                # handle missing units
                self.data[channel][name]['unit'] = 'n/a'
        else:
            # item name exists, add the observation timestamp
            self.data[channel][name]['time'].extend([timestamp])

        # add the value(s) to the running data log
        if item.size > 1:
            self.data[channel][name]['value'].append(numpy.array(item.data).reshape(item.shape))  # [[a, b], [c, d],...]
        else:
            self.data[channel][name]['value'].extend(item.data)  # [a, b, c, d,...]

