##
# @file    main.py
# @brief   Conversion and display of serial data from Intercomp SW500 to CAN
# @version 1.0
#

import gui
import serial
import can
import ustruct as us

class UI_Box:
    def __init__(self, x, y, w, h, title=None, font=24, val=0, bg_colour=gui.RGB(0,0,0), line_colour=gui.RGB(255,255,255)):
        self.x = x
        self.y = y
        self.w = w
        self.h = h
        self.bg_colour = bg_colour
        self.title = title
        self.line_colour = line_colour
        self.val = val
        self.font = font
        self.line_width = 3

    def draw_box(self):
        self.gui_l = [
                gui.SUBLIST,
                [gui.DL_COLOR(self.line_colour)],
                [gui.DL_LINE_WIDTH(10)],
                [gui.DL_COLOR_A(150)],
                [gui.DL_BEGIN(gui.PRIM_RECTS)],
                [gui.DL_VERTEX2F(self.x, self.y)], # Outer box
                [gui.DL_VERTEX2F(self.x + self.w, self.y + self.h)],
                [gui.DL_COLOR(self.bg_colour)],
                [gui.DL_COLOR_A(200)],
                [gui.DL_VERTEX2F(self.x + self.line_width, self.y + self.line_width)], # Inner box
                [gui.DL_VERTEX2F(self.x + (self.w-self.line_width), self.y + (self.h-self.line_width))],
                [gui.DL_END()],
                [gui.DL_COLOR(self.line_colour)],
                [gui.DL_COLOR_A(255)],
                [gui.CTRL_TEXT, int(self.x + (self.w *0.5)), int(self.y), self.font, gui.OPT_CENTERX, self.title],
                [gui.DL_COLOR(gui.RGB(255,255,255))],
                [gui.CTRL_NUMBER, int(self.x + (self.w *0.5)), int(self.y + (self.h *0.4)), 31, gui.OPT_CENTERX, '%.1f', self.val],
            ]
        return self.gui_l


serial_buffer = [0] * 32
read_pos = 0
FL,FR,RL,RR = [0.0],[0.0],[0.0],[0.0]

def draw():
    gui_l = [
        [gui.DL_CLEAR_COLOR_RGB(0,0,0)],
        [gui.DL_CLEAR(1,1,1)],
        [gui.DL_COLOR_RGB(0, 0, 0)],  
    ]
    gui_l.append(fl_box.draw_box())
    gui_l.append(fr_box.draw_box())
    gui_l.append(rl_box.draw_box())
    gui_l.append(rr_box.draw_box())
    gui.show(gui_l)

def send_can():
    global FL,FR,RL,RR  
    gui.redraw()  
    try:
        can.send_msg(can.CAN0,[0x401,0,[int(FL[0]*10) >> 8,int(FL[0]*10) & 0xff,int(FR[0]*10) >> 8,int(FR[0]*10) & 0xff,int(RL[0]*10) >> 8,int(RL[0]*10) & 0xff,int(RR[0]*10) >> 8,int(RR[0]*10) & 0xff]])
    except TimeoutError:
        pass

def process_line():
    global read_pos,FL,FR,RL,RR
    if serial_buffer[2] == b'0':
        FL[0] = float(b''.join(serial_buffer[3:10]).decode('utf-8'))
    elif serial_buffer[2] == b'1':
        FR[0] = float(b''.join(serial_buffer[3:10]).decode('utf-8'))
    elif serial_buffer[2] == b'2':
        RL[0] = float(b''.join(serial_buffer[3:10]).decode('utf-8'))
    elif serial_buffer[2] == b'3':
        RR[0] = float(b''.join(serial_buffer[3:10]).decode('utf-8')) 
        send_can()
    read_pos = 0

def serial_data():
    global serial_buffer, read_pos
    while serial.available():
        serial_buffer[read_pos] = serial.read(1);
        if serial_buffer[read_pos] == b'\n':
            process_line()
        else:
            read_pos +=1
        if read_pos == 31:
            read_pos = 0;
            
   


def main():
    global fl_box, fr_box, rl_box, rr_box

    fl_box = UI_Box(20,20,350,190,'FRONT LEFT (KG)', val=FL)
    fr_box = UI_Box(410,20,350,190,'FRONT RIGHT (KG)', val=FR)
    rl_box = UI_Box(20,250,350,190,'REAR LEFT (KG)', val=RL)
    rr_box = UI_Box(410,250,350,190,'REAR RIGHT (KG)', val=RR)

    draw()

    can.reset(can.CAN0,500000)
    can.termination(can.CAN0,True)
    can.test_mode(can.CAN0,0)

    serial.open()
    serial.set_callback(serial_data)


if __name__ == "__main__":
    main()
