import gi
import threading
import time
import usb.core
import usb.util
import requests
import json

gi.require_version('Gtk', '4.0')
from gi.repository import Gtk, Gio, Gdk

DEBUG = False

if DEBUG == True:
    index = 2
else:
    index = 1
activeCards = []

TIME = 600

USB_IF      = 0 # Interface
USB_TIMEOUT = 5 # Timeout in ms
USB_VENDOR  = 0xffff # Vendor-ID:
USB_PRODUCT = 0x0035 # Product-ID

with open('people.json', 'r') as f:
    db = json.load(f)

class UsbCardReader():
    def __init__(self, **kargs):
        # Find the HID device by vendor/product ID
        self.dev = usb.core.find(idVendor=USB_VENDOR, idProduct=USB_PRODUCT)
        # Get and store the endpoint
        self.endpoint = self.dev[0][(0,0)][0]
        if self.dev.is_kernel_driver_active(USB_IF) is True:
            self.dev.detach_kernel_driver(USB_IF)
        # Claim the device
        usb.util.claim_interface(self.dev, USB_IF)
        self.receivedNumber = 0

        cardread=threading.Thread(target=self.read)
        cardread.start()

    def read(self):
        global win, activeCards, db

        print("Waiting for card")
        receivedNumber = 0

        while True:
            control = None
            try:
                control = self.dev.read(self.endpoint.bEndpointAddress, self.endpoint.wMaxPacketSize, USB_TIMEOUT)
                if (control[2] != 40) & (control[2] != 0):
                    receivedDigit = control[2] - 29
                    if receivedDigit == 10:
                        receivedDigit = 0
                    receivedNumber = 10 * receivedNumber + receivedDigit

                if (( control[0] == 0 )) & (( control[2] == 40 )) & (( not receivedNumber == 0 )):
                    try:
                        with open('people.json', 'r') as f:
                            db = json.load(f)
                        for i in db:
                            if db[i] == receivedNumber:
                                if i not in activeCards:
                                    activeCards.append(i)
                                    win.arb(i)
                                else:
                                    print("Card is active now")
                    except Exception as e: print(e)
                    receivedNumber = 0

            except KeyboardInterrupt:
                exit()
            except:
                pass

            time.sleep(0.001)

class GridRow():
    def __init__(self, parent, runner, index):
        self.id = runner
        self.index = index
        self.parent = parent

        self.grid = Gtk.Grid()

        if index % 2 == 0:
            self.grid.set_name("lightgrid")
        else:
            self.grid.set_name("darkgrid")

        self.runid = Gtk.Label(label=str(runner), name="gridlabel")
        self.runid.set_justify(2)
        self.runid.set_width_chars(10)

        self.runb = Gtk.Label(label='00:00', name="gridlabel")
        self.runb.set_hexpand(1)

        self.grid.attach(self.runid, 0, 0, 1, 1)
        self.grid.attach(self.runb, 1, 0, 1, 1)

        parent.grid.attach(self.grid, 0, index, 2, 1)

        countdown=threading.Thread(target=self.updateTime)
        countdown.start()

    def printIndex(self, button):
        print(self.index)

    def updateTime(self):
        t = TIME
        while t >= -10:
            if t < 0:
                mins, secs = divmod((t * -1), 60)
                timer = '-{:02d}:{:02d}'.format(mins, secs)
            else:
                mins, secs = divmod(t, 60)
                timer = '{:02d}:{:02d}'.format(mins, secs)
            self.runb.set_label(timer)
            time.sleep(1)
            t -= 1
            if t == 10:
                if self.grid.get_name() == "lightgrid":
                    self.grid.set_name("lredgrid")
                else:
                    self.grid.set_name("dredgrid")

        GridWindow.remRow(self.parent)

class GridWindow(Gtk.ApplicationWindow):
    def __init__(self, **kargs):
        super().__init__(**kargs, title='Alkator Clock')

        css_provider = Gtk.CssProvider()
        css_provider.load_from_file(Gio.File.new_for_path("style.css"))
        Gtk.StyleContext.add_provider_for_display(Gdk.Display.get_default(), css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)

        button1 = Gtk.Button(label='addrow')
        button2 = Gtk.Button(label='rmrow')

        button1.connect("clicked", self.arb)
        button2.connect("clicked", self.rrb)

        runlabel = Gtk.Label(label="ID", name="gridlabel")
        runlabel.set_justify(2)
        cntlabel = Gtk.Label(label="Countdown", name="gridlabel")
        cntlabel.set_justify(2)

        self.runners = []

        self.grid = Gtk.Grid()
        if DEBUG == True:
            self.grid.attach(button1, 0, 0, 1, 1)
            self.grid.attach(button2, 1, 0, 2, 1)
            self.grid.attach(runlabel, 0, 1, 1, 1)
            self.grid.attach(cntlabel, 1, 1, 2, 1)
        else:
            self.grid.attach(runlabel, 0, 0, 1, 1)
            self.grid.attach(cntlabel, 1, 0, 2, 1)

        self.set_child(self.grid)

    def arb(self, personId):
        global index
        self.runners.append(GridRow(self, personId, index))
        index += 1

    def rrb(self, button):
        global index
        self.remRow()

    def addRow(self, runner, index):
        runid = Gtk.Label(label=str(runner))
        runb = Gtk.Button(label='time_placeholder')

        self.grid.attach(runid, 0, index, 1, 1)
        self.grid.attach(runb, 1, index, 1, 1)

    def remRow(self):
        global index, activeCards
        if index > 1:
            self.grid.remove_row(1)
            index -= 1
            del activeCards[0]


def on_activate(app):
    # Create window
    global win
    win = GridWindow(application=app)
    win.present()

UsbCardReader()
app = Gtk.Application(application_id='com.example.App')
app.connect('activate', on_activate)

app.run(None)
