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


USBIO_DID = [
    USB2026,
    USB2045,
    USB2055,
    USB2064,
    USB2045_32,
    USB2055_32,
    USB2064_16,
    USB2068_18,
    USB2255_32, 
    USB2255_64,
    USB2261_16,
    USB2261_32,
    USB2260_48,
    USB2260B_48,
    USB2260C_48,
    USB2260_24,
    USB2260B_24,
    USB2260C_24    
]

bySupIOMask = c_char()
m_byDITotal = c_char()
m_byDOTotal = c_char()
m_byAITotal = c_char()
m_byAOTotal = c_char()
m_byPITotal = c_char()
m_byPOTotal = c_char()
      
class FormDO_WriteValue(tk.Tk):

    def __init__(self):
        super().__init__()

        self.title("FormDO_WriteValue")
        self.geometry("462x264")

        self.usb = None
        self.deviceHandle = None

        self.create_widgets()        
        
       
    def create_widgets(self):
        # Device ID
        self.labDevID = ttk.Label(self, text="Device ID")
        self.labDevID.place(x=10, y=15)

        self.cbxDevID = ttk.Combobox(self, values=[
            "USB-2026", "USB-2045", "USB-2055", "USB-2064",
            "USB-2045-32", "USB-2055-32", "USB-2064-16", "USB-2068-18",
            "USB-2255-32","USB-2255-64","USB-2261-16","USB-2261-32",
            "USB-2260-48","USB-2260B-48","USB-2260C-48","USB-2260-24",
            "USB-2260B-24","USB-2260C-24",
        ])
        self.cbxDevID.place(x=90, y=15, width=120)

        # Board ID
        self.labBoardID = ttk.Label(self, text="Board ID")
        self.labBoardID.place(x=10, y=45)

        self.txtBoardID = ttk.Entry(self)
        self.txtBoardID.place(x=90, y=45, width=120)
        self.txtBoardID.insert(0, "1")

        # Open and Close buttons
        self.btnOpen = ttk.Button(self, text="Open", command=self.btnOpen_Click)
        self.btnOpen.place(x=10, y=75, width=70)

        self.btnClose = ttk.Button(self, text="Close", command=self.btnClose_Click)
        self.btnClose.place(x=90, y=75, width=70)

        # ListView for info
        self.lvInfo = tk.Listbox(self)
        self.lvInfo.place(x=10, y=105, width=260, height=150)

        # Read DO Value
        self.labReadDOValue = ttk.Label(self, text="DO Value, 0x")
        self.labReadDOValue.place(x=220, y=15)

#        self.lab0x = ttk.Label(self, text="0x")
#        self.lab0x.place(x=290, y=15)

        self.txtReadDOValue = ttk.Entry(self, state="disabled")
        self.txtReadDOValue.place(x=325, y=15, width=110)

        self.btnReadDOValue = ttk.Button(self, text="Read", command=self.btnReadDOValue_Click, state="disabled")
        self.btnReadDOValue.place(x=330, y=45, width=70)

        # Write DO Value
        self.labWriteDOValue = ttk.Label(self, text="DO Value, 0x")
        self.labWriteDOValue.place(x=220, y=75)

#        self.lab0x2 = ttk.Label(self, text="0x")
#        self.lab0x2.place(x=290, y=75)

        self.txtWriteDOValue = ttk.Entry(self, state="disabled")
        self.txtWriteDOValue.place(x=325, y=75, width=110)

        self.btnWriteDOValue = ttk.Button(self, text="Write", command=self.btnWriteDOValue_Click, state="disabled")
        self.btnWriteDOValue.place(x=330, y=105, width=70)

        
    def btnOpen_Click(self):
        try:
            #self.usb2000 = ctypes.windll.LoadLibrary("./ICPDAS_USBIO.dll")
            self.usb = USBIO()
            deviceID =int(self.cbxDevID.current())
            boardID = int(self.txtBoardID.get())
            
            #print("deviceID:", deviceID)
            #print("boardID:", boardID) 

            self.deviceHandle = self.usb.OpenDevice(USBIO_DID[deviceID], boardID) #deviceID.encode(), boardID)
            if self.deviceHandle == -1:
                raise Exception("Open device failed")

            self.lvInfo.insert(tk.END, "Open device succeeded!")
            self.enable_controls(True)
            
            self.usb.GetSupportIOMask(byref(bySupIOMask))
            print("IOMask:", ord(bySupIOMask.value))
            
            #if self.usb.SUPPORT_DI(bySupIOMask.value):
            #   self.usb.GetDITotal(byref(m_byDITotal))
            #    print("DITotal:", m_byDITotal)
                         
            intvl=ord(bySupIOMask.value)                      
            if SUPPORT_DO(intvl):
                self.usb.GetDOTotal(byref(m_byDOTotal))
                print("DOTotal:", ord(m_byDOTotal.value))
    
        except Exception as e:
            messagebox.showerror("Error", str(e))

    def btnClose_Click(self):
        if self.deviceHandle is not None:
            self.usb.CloseDevice()
            self.deviceHandle = None
            self.lvInfo.insert(tk.END, "Close device succeeded!")
            self.enable_controls(False)

    def btnReadDOValue_Click(self):
        DO_byte_count_arr = (c_char * ((USBIO_DO_MAX_CHANNEL + 7) // 8))()   
    
        if self.deviceHandle is not None:
            #doReadArr  = (c_char * 1)()
            result = self.usb.DO_ReadValue(DO_byte_count_arr)
            if result == 0:
                little_endian_value = int.from_bytes(DO_byte_count_arr, byteorder='little')
                #print("do:", f"{little_endian_value:08X}")
                
                self.txtReadDOValue.delete(0, tk.END)
                self.txtReadDOValue.insert(0, f"{little_endian_value:08X}")                
                self.lvInfo.insert(tk.END, f"Read DO value: 0x{little_endian_value:08X}")
            else:
                self.lvInfo.insert(tk.END, "Read DO value failed!")
        else:
            messagebox.showerror("Error", "Device not opened")

    def btnWriteDOValue_Click(self):
        o_byDOValue = (c_char * ((USBIO_DO_MAX_CHANNEL + 7) // 8))()   
        if self.deviceHandle is not None:
            try:
                doValue = int(self.txtWriteDOValue.get(), 16)
                print("dovalue",doValue)
                
                # Convert the integer to BYTE array
                for iIdx in range((ord(m_byDOTotal.value) + 7) // 8):
                    o_byDOValue[iIdx] = c_char((doValue >> (iIdx * 8)) & 0xFF)                
                
                result = self.usb.DO_WriteValue(o_byDOValue)
                if result == 0:
                    self.lvInfo.insert(tk.END, f"Write DO value: 0x{doValue:08X}")
                else:
                    self.lvInfo.insert(tk.END, "Write DO value failed!")
            except ValueError:
                messagebox.showerror("Error", "Invalid hexadecimal value")
        else:
            messagebox.showerror("Error", "Device not opened")

    def enable_controls(self, enabled):
        state = "normal" if enabled else "disabled"
        self.txtReadDOValue.config(state=state)
        self.btnReadDOValue.config(state=state)
        self.txtWriteDOValue.config(state=state)
        self.btnWriteDOValue.config(state=state)
        self.btnOpen.config(state="disabled" if enabled else "normal")
        self.btnClose.config(state="normal" if enabled else "disabled")

if __name__ == "__main__":
    app = FormDO_WriteValue()
    app.mainloop()
