from tkinter import *
from tkinter.filedialog import *
import platform
from get_file import *
from BSL_pack import *
from UART_send import *
import time
from generate_linker import *
import os
from txt_to_h import *


class Tkinter_app():
    def __init__(self, master):
        self.passwordfile = b''
        self.firmwaredfile = ''
        menubar = Menu(master, tearoff=0)
#        menubar.add_command(label='MoreOption')
        menufile = Menu(menubar, tearoff=0)
        menubar.add_cascade(label='MoreOption', menu=menufile)
        menufile.add_command(label='Create Linker Files', command=self.create_linker)
        menufile.add_command(label='TXT_to_H', command=self.txt_h)
        master['menu'] = menubar

        # menubar.config(bg='red')
     #   menubar.pack()

        # variable = StringVar(master)
        # variable.set("one")  # default value
        # w = OptionMenu(master, variable, "one", "two", "three")
        # w.config(bg="gray")  # Set background color to green
        # w.pack()

        frame0 = Frame(master)
        frame0.pack(padx=50, pady=20, anchor=E)
        frame1 = Frame(master)
        frame1.pack(padx=50, anchor=E)
        frame3 = Frame(master)
        frame3.pack(pady=10)
        frame4 = Frame(master)
        frame4.pack()
        frame5 = Frame(master)
        frame5.pack()
        frame2 = Frame(master)
        frame2.pack(side='bottom')

        self.label0 = Label(frame0, text='Application firmware file:')
        self.label0.pack(side='left')
        global input_name
        input_name = StringVar()
        self.entry = Entry(frame0, width=50, textvariable=input_name)
        self.entry.pack(side='left')
        self.button = Button(frame0, text='Choose .txt file', command=self.choosefile)
        self.button.pack(side='left')

        self.label1 = Label(frame1, text='Password file:')
        self.label1.pack(side='left')
        global input_name1
        input_name1 = StringVar()
        self.entry1 = Entry(frame1, width=50, textvariable=input_name1)
        self.entry1.pack(side='left')
        self.button1 = Button(frame1, text='Choose .txt file', command=self.choosefile1)
        self.button1.pack(side='left')

        global photo
#        photo = PhotoImage(file=SETUP_DIR + "\imag\oi.GIF")
        photo = PhotoImage(file="imag\oi.GIF")
        self.label2 = Label(frame2, image=photo)
        self.label2.pack()

        self.button = Button(frame3, text='Download', command=self.download)
        self.button.pack()

        self.s1 = Scrollbar(frame4)
        self.s1.pack(side=RIGHT, fill=Y)
        self.textlog = Text(frame4, yscrollcommand=self.s1.set, width=70, height=15, bg='white')
        self.s1.config(command=self.textlog.yview)
        self.textlog.pack()
        self.textlog.insert(INSERT, 'This GUI is developed with Python version: 3.8.2\n')
#        self.textlog.insert(INSERT, "Python version: "+platform.python_version() + '\n')
        self.textlog.tag_config('error', foreground='red')
        self.textlog.tag_config('pass', foreground='green')
        self.textlog.config(state=DISABLED)

        self.button_c = Button(frame5, text='Clear', command=self.clear_text)
        self.button_c.pack()
    def choosefile(self):
        f = askopenfilename(title='Choose a firmware file', initialdir='c:', filetypes=[("textfile",".txt")])
        input_name.set(f)
        self.textlog.config(state=NORMAL)
        if f:
            self.textlog.insert(INSERT, 'Choose a firmware file at:' + f + '\n')
        else:
            self.textlog.insert(INSERT, 'Error: Please choose a firmware file.\n', 'error')
        self.textlog.config(state=DISABLED)
        self.firmwaredfile = file_d.get_firmware(f)
 #       print(self.firmwaredfile)
    def choosefile1(self):
        f1 = askopenfilename(title='Choose a password file', initialdir='c:', filetypes=[("textfile",".txt")])
        input_name1.set(f1)
        self.textlog.config(state=NORMAL)
        if f1:
            self.textlog.insert(INSERT, 'Choose a password file at:' + f1 + '\n')
            self.passwordfile = file_d.get_password(f1)
        else:
            self.textlog.insert(INSERT, 'Error: Please choose a password file.\n', 'error')
        if self.passwordfile == b'':
            self.textlog.insert(INSERT, 'Error: Password format is not correct!\n', 'error')
        # else:
        #     print(self.passwordfile)
        self.textlog.config(state=DISABLED)

    def download(self):
 #       print(self.passwordfile)
#        print(self.firmwaredfile)
        self.textlog.config(state=NORMAL)
        if self.passwordfile != b'' and self.firmwaredfile != '':
            password_pack = BSL_pack.password_pack(self.passwordfile)
            firmware_pack = BSL_pack.firmware_pack(self.firmwaredfile)
            pc_pack = BSL_pack.set_pc_pack(self.firmwaredfile)
#            print(pc_pack)
            find_flag = UART_S.find_MSP_COM()
            if find_flag:
                self.textlog.insert(INSERT, 'Find MSP COM port:' + find_flag + '\n')
                ser_port = UART_S.config_uart(find_flag)
                self.textlog.insert(INSERT, 'Configure UART: 9600 baudrate, 8 data bits (LSB first), an even parity, and 1 stop bit.\n')
                UART_S.send_data(ser_port, b'\xbb')
                response = UART_S.read_data(ser_port, 1)
#                print(response)
                if response == '51':
                    self.textlog.insert(INSERT, 'MSP430 is in BSL mode.\nSend the password...\n')
                    UART_S.send_data(ser_port, password_pack)
                    response2 = UART_S.read_data(ser_port, 1)
                    check = self.check_pack(response2)
                    if check:
                        response2 = UART_S.read_data(ser_port, 7)
                        check2 = self.check_reponse(response2[8:10])
                        if check2:
                            self.textlog.insert(INSERT, 'Send the firmware...\n')
                            for list_code in firmware_pack:
                                UART_S.send_data(ser_port, list_code)
                                response3 = UART_S.read_data(ser_port, 1)
                                check = self.check_pack(response3)
                                if check:
                                    response3 = UART_S.read_data(ser_port, 7)
                                    check3 = self.check_reponse(response3[8:10])
                                    if check3:pass
                                    else: break
                                else: break
                            if check:
                                self.textlog.insert(INSERT, 'Send firmware successfully!\n')
                                self.textlog.insert(INSERT, 'Set the PC to application start address...\n')
                                self.textlog.insert(INSERT, '-----------Download finished!----------\n', 'pass')
                                UART_S.send_data(ser_port, pc_pack)
                else:
                    if response == '22':
                        self.textlog.insert(INSERT, 'MSP430 is in application mode.\nTrigger BSL first...\n')
                        UART_S.send_data(ser_port, b'\xaa')
                        time.sleep(0.06)
                        UART_S.send_data(ser_port, b'\xbb')
                        response2 = UART_S.read_data(ser_port, 1)
                        if response2 == '51':
                            self.textlog.insert(INSERT, 'MSP430 is in BSL mode.\n Send the password...\n')
                            UART_S.send_data(ser_port, password_pack)
                            response2 = UART_S.read_data(ser_port, 1)
                            check = self.check_pack(response2)
                            if check:
                                response2 = UART_S.read_data(ser_port, 7)
                                check2 = self.check_reponse(response2[8:10])
                                if check2:
                                    self.textlog.insert(INSERT, 'Send the firmware...\n')
                                    for list_code in firmware_pack:
                                        UART_S.send_data(ser_port, list_code)
                                        response3 = UART_S.read_data(ser_port, 1)
                                        check = self.check_pack(response3)
                                        if check:
                                            response3 = UART_S.read_data(ser_port, 7)
                                            check3 = self.check_reponse(response3[8:10])
                                            if check3:
                                                pass
                                            else:
                                                break
                                        else:
                                            break
                                    if check:
                                        self.textlog.insert(INSERT, 'Send firmware successfully!\n')
                                        self.textlog.insert(INSERT, 'Set the PC to application start address...\n')
                                        self.textlog.insert(INSERT, '-----------Download finished!----------\n', 'pass')
                                        UART_S.send_data(ser_port, pc_pack)
                    else:
                        self.textlog.insert(INSERT, 'Error: No response！\n', 'error')
            else:
                self.textlog.insert(INSERT, 'Error: Can not find MSP COM port!\n', 'error')
        else:
            self.textlog.insert(INSERT, 'Error: please choose all files above!\n', 'error')
        self.textlog.see(END)
        self.textlog.config(state=DISABLED)
    def clear_text(self):
        self.textlog.config(state=NORMAL)
        self.textlog.delete('2.0','end')
        self.textlog.insert(INSERT, '\n')
        self.textlog.config(state=DISABLED)
    def check_pack(self, pack_ack):
        flagg = 0
#        self.textlog.config(state=NORMAL)
        if pack_ack == '00':
            flagg = 1
            self.textlog.insert(INSERT, 'Send package successfully!\n')
        elif pack_ack == '51':
            self.textlog.insert(INSERT, 'Error: Header incorrect!\n', 'error')
        elif pack_ack == '52':
            self.textlog.insert(INSERT, 'Error: Checksum incorrect!\n', 'error')
        elif pack_ack == '53':
            self.textlog.insert(INSERT, 'Error: Packet size zero!\n', 'error')
        elif pack_ack == '54':
            self.textlog.insert(INSERT, 'Error: Packet size exceeds buffer!\n', 'error')
        elif pack_ack == '55':
            self.textlog.insert(INSERT, 'Error: Unknown error!\n', 'error')
        elif pack_ack == '56':
            self.textlog.insert(INSERT, 'Error: Unknown baud rate!\n', 'error')
        elif pack_ack == '57':
            self.textlog.insert(INSERT, 'Error: Packet size error!\n', 'error')
        else:
            self.textlog.insert(INSERT, 'Error: Unknow else error!\n', 'error')
 #       self.textlog.config(state=DISABLED)
        return flagg
    def check_reponse(self, pack_res):
        flagg = 0
 #       self.textlog.config(state=NORMAL)
        if pack_res == '00':
            flagg = 1
            self.textlog.insert(INSERT, 'Operation success!\n')
        elif pack_res == '01':
            self.textlog.insert(INSERT, 'Error: Memry write check failed!\n', 'error')
        elif pack_res == '04':
            self.textlog.insert(INSERT, 'Error: BSL locked!!\n', 'error')
        elif pack_res == '05':
            self.textlog.insert(INSERT, 'Error: BSL password error!\n', 'error')
        else:
            self.textlog.insert(INSERT, 'Error: Unknow else error!\n', 'error')
        return flagg
#        self.textlog.config(state=DISABLED)
    def create_linker(self):
        sub_win = Toplevel(root)
        sub_win.title('Generate linker files')
#        sub_win.attributes("-topmost", True)
        sub_win.geometry("700x350+300+200")
        sub_win.grab_set()
        frames0 = Frame(sub_win)
        frames0.pack(padx=50, pady=20, anchor=W)
        frames1 = Frame(sub_win)
        frames1.pack(padx=50, anchor=W)
        frames3 = Frame(sub_win)
        frames3.pack(pady=10)
        frames4 = Frame(sub_win)
        frames4.pack()

        self.labels0 = Label(frames0, text='Input device name:')
        self.labels0.pack(side='left')
        global input_name_s
        input_name_s = StringVar()
        self.entrys = Entry(frames0, width=50, textvariable=input_name_s)
        self.entrys.pack(side='left')
        self.labels2 = Label(frames0, text='(Example: MSP430FR2355)')
        self.labels2.pack(side='left')

        self.labels1 = Label(frames1, text='Choose a ouput folder:')
        self.labels1.pack(side='left')
        global out_name_s
        out_name_s = StringVar()
        self.entrys1 = Entry(frames1, width=50, textvariable=out_name_s)
        self.entrys1.pack(side='left')
        self.buttons1 = Button(frames1, text='Scan', command=self.choosefile_s)
        self.buttons1.pack(side='left')

        self.buttons2 = Button(frames3, text='Generate', command=self.generate_f)
        self.buttons2.pack()

        self.s2 = Scrollbar(frames4)
        self.s2.pack(side=RIGHT, fill=Y)
        self.textlogsub = Text(frames4, yscrollcommand=self.s2.set, width=70, height=10, bg='white')
        self.s2.config(command=self.textlogsub.yview)
        self.textlogsub.pack()
        self.textlogsub.tag_config('errors', foreground='red')
        self.textlogsub.tag_config('pass_s', foreground='green')
        self.textlogsub.config(state=DISABLED)
    def choosefile_s(self):
        f2 = askdirectory()
        out_name_s.set(f2)
        self.textlogsub.config(state=NORMAL)
        if f2:
            self.textlogsub.insert(INSERT, 'Choose a output folder:' + f2 + '\n')
        else:
            self.textlogsub.insert(INSERT, 'Error: Please choose a output folder.\n', 'errors')
        self.textlogsub.config(state=DISABLED)
    def generate_f(self):
        self.textlogsub.config(state=NORMAL)
        input_name = input_name_s.get()
        output_path = out_name_s.get()
        if input_name:
            input_name = input_name.lower()
            CMD_file = 'MSP430FRAM_CMD_FILES/lnk_' + input_name + '.cmd'
            if os.path.exists(CMD_file):
                self.textlogsub.insert(INSERT, 'You have choose device:' + input_name + '\n')
                if output_path:
#                    self.textlogsub.insert(INSERT, output_path + '\n')
                    input_name_ = input_name[3:]
                    IAR_file = 'MSP430FRAM_XCL_FILES/lnk' + input_name_ + '.xcl'
                    if os.path.exists(IAR_file):
#                        self.textlogsub.insert(INSERT, 'find the file ' + IAR_file + '\n')
                        Linker_g.get_info(CMD_file, IAR_file, output_path)
                        self.textlogsub.insert(INSERT, '-----Generate linker files for CCS and IAR -----\n', 'pass_s')
                        self.textlogsub.insert(INSERT, '-----Generate bsl_app.h header file for application project-----\n', 'pass_s')
                    else:
                       self.textlogsub.insert(INSERT, 'Error: Can not find the' + IAR_file +'.\n', 'errors')
                else:
                    self.textlogsub.insert(INSERT, 'Error: Please choose a output folder.\n', 'errors')
            else:
                self.textlogsub.insert(INSERT, 'Error: Can not find device ' + input_name, 'errors')
        else:
            self.textlogsub.insert(INSERT, 'Error: Please input device name first！', 'errors')
        self.textlogsub.config(state=DISABLED)
    def txt_h(self):
        sub_win1 = Toplevel(root)
        sub_win1.title('TXT to H')
#        sub_win1.attributes("-topmost", True)
        sub_win1.geometry("700x350+300+200")
        sub_win1.grab_set()
        frames_0 = Frame(sub_win1)
        frames_0.pack(padx=50, pady=20, anchor=W)
        frames_1 = Frame(sub_win1)
        frames_1.pack(padx=50, anchor=W)
        frames_3 = Frame(sub_win1)
        frames_3.pack(pady=10)
        frames_4 = Frame(sub_win1)
        frames_4.pack()

        self.labelss0 = Label(frames_0, text='Choose a firmware .txt file')
        self.labelss0.pack(side='left')
        global input_name_ss
        input_name_ss = StringVar()
        self.entryss = Entry(frames_0, width=50, textvariable=input_name_ss)
        self.entryss.pack(side='left')
        self.buttonss = Button(frames_0, text='Choose .txt file', command=self.choosetxtfile)
        self.buttonss.pack(side='left')

        self.labelss1 = Label(frames_1, text='Choose a ouput folder:')
        self.labelss1.pack(side='left')
        global out_name_ss
        out_name_ss = StringVar()
        self.entryss1 = Entry(frames_1, width=50, textvariable=out_name_ss)
        self.entryss1.pack(side='left')
        self.buttonss1 = Button(frames_1, text='Scan', command=self.choosefile_out)
        self.buttonss1.pack(side='left')

        self.buttonss2 = Button(frames_3, text='Convert', command=self.convert_)
        self.buttonss2.pack()

        self.s3 = Scrollbar(frames_4)
        self.s3.pack(side=RIGHT, fill=Y)
        self.textlogsubs = Text(frames_4, yscrollcommand=self.s3.set, width=70, height=10, bg='white')
        self.s3.config(command=self.textlogsubs.yview)
        self.textlogsubs.pack()
        self.textlogsubs.tag_config('errors_', foreground='red')
        self.textlogsubs.tag_config('pass_s_', foreground='green')
        self.textlogsubs.insert(INSERT, 'This function is used for the situation that using MCU as host.\n')
        self.textlogsubs.insert(INSERT, 'The output header file is used for host MCU.\n')
        self.textlogsubs.config(state=DISABLED)
    def choosetxtfile(self):
        fs = askopenfilename(title='Choose a firmware file', initialdir='c:', filetypes=[("textfile", ".txt")])
        input_name_ss.set(fs)
        self.textlogsubs.config(state=NORMAL)
        if fs:
            self.textlogsubs.insert(INSERT, 'Choose a firmware file at:' + fs + '\n')
        else:
            self.textlogsubs.insert(INSERT, 'Error: Please choose a firmware file.\n', 'errors_')
        self.textlogsubs.config(state=DISABLED)
    def choosefile_out(self):
        f3 = askdirectory()
        out_name_ss.set(f3)
        self.textlogsubs.config(state=NORMAL)
        if f3:
            self.textlogsubs.insert(INSERT, 'Choose a output folder:' + f3 + '\n')
        else:
            self.textlogsubs.insert(INSERT, 'Error: Please choose a output folder.\n', 'errors_')
        self.textlogsubs.config(state=DISABLED)
    def convert_(self):
        self.textlogsubs.config(state=NORMAL)
        input_names = input_name_ss.get()
        output_paths = out_name_ss.get()
        if input_names:
            if output_paths:
                self.textlogsubs.insert(INSERT, 'Converting...\n')
                name_file=input_names.split('/')[-1]
                name_file2 = name_file.split('.')[0]
                output_paths_n = output_paths + '/'+name_file2+'.h'
                Conver_F.conver_fun(input_names, output_paths_n)
                self.textlogsubs.insert(INSERT, '-----Convert the firmware to header file named '+ name_file2 + ".h!----\n ", 'pass_s_')
            else:
                self.textlogsubs.insert(INSERT, 'Error: Please choose a output folder.\n', 'errors_')
        else:
            self.textlogsubs.insert(INSERT, 'Error: Please choose a .txt firmware.\n', 'errors_')
        self.textlogsubs.config(state=DISABLED)

if __name__ == '__main__':
    file_d = Get_files()
    BSL_pack = BSL_Pack()
    UART_S = UART_send()
    Linker_g = Generate_link()
    Conver_F = TXT_to_h()
    root = Tk()
    root.iconbitmap('imag/Capture.ico')
    root.geometry("700x500+500+500")
    root.title("Bootloader Host")
    app = Tkinter_app(root)
    root.mainloop()