##
# @file   comm_message.py
# @brief
#
# @copyright
#
#
# @{

import __init__

import array

import crcmod


class Message(object):
    '''

    '''
    START = 0x02   # !< Start byte of the message
    MAX_LEN = 255  # !< Maximum message length in bytes
    HEADER_LEN = 3 # !< Length of message header(START | LEN | CMD)

    def __init__(self, cmd, data, callback=None,):
        self.crc_func = crcmod.predefined.mkCrcFun('crc-8')
        self.cmd = cmd
        self.data = [] if data is None else data
        self.length = len(self.data)+4
        self.crc = 0
        self.bytes = []
        self.binary = []
        self._pack()
        self.callback = callback

    @classmethod
    def unpack(msg, bytes):
        '''

        :return: 
        '''
        length = bytes[1]
        cmd = bytes[2]
        data = bytes[3:(length+1)]
        return msg(cmd, data)


    def _pack(self):
        '''
        assemble a serial line transport header
        :return: None
        '''
        count = len(self.data)+2
        self.bytes = []
        self.bytes.append(Message.START)
        self.bytes.append(count)
        self.bytes.append(self.cmd)

        # put it to the front of the data list
        self.bytes = self.bytes + self.data

        # CRC
        self._append_crc()

        # serialize the list and send it out
        self.binary = array.array('B', self.bytes).tostring()


    def _compute_crc(self, bytes):
        '''
        Computes CRC from the input bytes
        :param bytes: 
        :return: 
        '''
        mycrc = 0
        mycrc = sum(bytes)
        mycrc = ~mycrc
        mycrc = (mycrc & 0xFF)
        return mycrc
        #return self.crc_func(b''.join([chr(d) for d in bytes]))


    def _append_crc(self):
        '''
        Appends crc to the end of the byte stream
        :return: 
        '''
        self.crc = self._compute_crc(self.bytes)
        self.bytes.append(self.crc)

        #   @}
