import tkinter as tk
from tkinter import ttk, messagebox
import ctypes
from ctypes import * 
from ICPDAS_USBIO import *


USBIO_DID = [
    USB2084
]
class FormPIReadValue:
    def __init__(self, master):
        self.master = master
        master.title("PI_ReadValue")
        master.geometry("660x330")

        self.USBIO = USBIO()
        self.i_pi_total=0
        self.m_bThreadRunning = False

        self.create_widgets()

    def create_widgets(self):
        # Left frame for device controls
        left_frame = tk.Frame(self.master)
        left_frame.grid(row=0, column=0, padx=10, pady=10, sticky="n")

        # Device ID
        tk.Label(left_frame, text="Device ID").grid(row=0, column=0, sticky="w")
        self.cbx_dev_id = ttk.Combobox(left_frame, values=["USB-2084"], width=8)
        self.cbx_dev_id.grid(row=0, column=1)
        self.cbx_dev_id.set("USB-2084")

        # Board ID
        tk.Label(left_frame, text="Board ID").grid(row=1, column=0, sticky="w")
        self.txt_board_id = tk.Entry(left_frame, width=10)
        self.txt_board_id.grid(row=1, column=1)
        self.txt_board_id.insert(0, "1")

        # Open/Close buttons
        self.btn_open = tk.Button(left_frame, text="Open", width=6, command=self.on_btn_open)
        self.btn_open.grid(row=2, column=0, pady=5)
        self.btn_close = tk.Button(left_frame, text="Close", width=6, command=self.on_btn_close)
        self.btn_close.grid(row=2, column=1, pady=5)

        # Information listbox
        tk.Label(left_frame, text="Information").grid(row=3, column=0, columnspan=2, sticky="w")
        self.lb_information = tk.Listbox(left_frame, width=28, height=7)
        self.lb_information.grid(row=4, column=0, columnspan=2)

        # Right frame for reading values
        right_frame = tk.Frame(self.master)
        right_frame.grid(row=0, column=1, padx=10, pady=10, sticky="n")

        # Read Value button
        self.btn_read_value = tk.Button(right_frame, text="Read Value", width=10, state=tk.DISABLED, command=self.on_btn_read_value)
        self.btn_read_value.grid(row=0, column=0, columnspan=2, pady=5)

        # Reading Value
        tk.Label(right_frame, text="Reading Value").grid(row=1, column=0, sticky="w")
        self.lb_reading_value = tk.Listbox(right_frame, width=15, height=8)
        self.lb_reading_value.grid(row=2, column=0, padx=(0, 5))

        # Channel Status
        tk.Label(right_frame, text="Channel Status").grid(row=1, column=1, sticky="w")
        self.lb_channel_status = tk.Listbox(right_frame, width=15, height=8)
        self.lb_channel_status.grid(row=2, column=1, padx=(5, 0))

    def on_btn_open(self):
        Board_id = int(self.txt_board_id.get())
        device_id =USBIO_DID[self.cbx_dev_id.current()]

        err_code = self.USBIO.OpenDevice(device_id, Board_id)

        if err_code != ERR_NO_ERR:
            messagebox.showerror("Error", f"[{err_code}]")
        else:
            self.btn_open.config(state=tk.NORMAL)
            self.btn_close.config(state=tk.NORMAL)
            self.btn_read_value.config(state=tk.NORMAL)
            self.update_module_info()

    def on_btn_close(self):
        result = self.USBIO.CloseDevice()
        if result == 0:
            self.lb_information.insert(tk.END, "Close device OK")
            self.btn_open.config(state=tk.NORMAL)
            self.btn_close.config(state=tk.DISABLED)
            self.btn_read_value.config(state=tk.DISABLED)
        else:
            self.lb_information.insert(tk.END, f"Close device fail, error code: {result}")

    def on_btn_read_value(self):
        dwValue = (ctypes.c_ulong * self.i_pi_total)()
        byStatus = (ctypes.c_char * self.i_pi_total)()
        result = self.USBIO.PI_ReadValue(dwValue, byStatus)
        if result == 0:
            self.lb_reading_value.delete(0, tk.END)
            self.lb_channel_status.delete(0, tk.END)
            for i in range(self.i_pi_total):
                self.lb_reading_value.insert(tk.END, f"CH{i}: {dwValue[i]}")
                self.lb_channel_status.insert(tk.END, f"CH{i}: {ord(byStatus[i])}")
        else:
            self.lb_information.insert(tk.END, f"Read value fail, error code: {result}")

    def update_module_info(self):
        self.lb_information.delete(0, tk.END)

        wdt_timeout = ctypes.c_ulong()
        self.USBIO.GetSoftWDTTimeout(ctypes.byref(wdt_timeout))
        self.lb_information.insert(tk.END, f"SoftWDT: {wdt_timeout.value}")

        fw_ver = ctypes.c_int()
        self.USBIO.GetFwVer(ctypes.byref(fw_ver))
        little_endian_value = int.from_bytes(fw_ver, byteorder='little')
        self.lb_information.insert(tk.END, f"Version: {little_endian_value}")

        device_nickname = (ctypes.c_char * USBIO_NICKNAME_LENGTH)()
        self.USBIO.GetDeviceNickName(device_nickname)
        nickname = ''.join([chr(i) for i in device_nickname.value]).rstrip('\x00')
        self.lb_information.insert(tk.END, f"Description: {nickname}")

        device_sn = (ctypes.c_char * USBIO_SN_LENGTH)()
        self.USBIO.GetDeviceSN(device_sn)
        sn = ''.join([chr(i) for i in device_sn.value]).rstrip('\x00')
        self.lb_information.insert(tk.END, f"SN: {sn}")

        bySupIOMask = c_char()
        self.USBIO.GetSupportIOMask(byref(bySupIOMask))
        self.lb_information.insert(tk.END, f"Support IO Mask: 0x{ord(bySupIOMask.value):02X}")   

        intvl=ord(bySupIOMask.value) 
        if SUPPORT_PI(intvl):
            pi_total =  c_char()
            self.USBIO.GetPITotal(byref(pi_total))
            self.i_pi_total=ord(pi_total.value)
            self.lb_information.insert(tk.END, f"PI channels: {self.i_pi_total}")      

if __name__ == "__main__":
    root = tk.Tk()
    app = FormPIReadValue(root)
    root.mainloop()
