import tkinter as tk
import tkinter.ttk as ttk
from cv2 import ellipse2Poly
import serial.tools.list_ports
import time

from soupsieve import match

help = """Programm zur Steuerung der Spritzenpumpe / Rheodyne Ventil Kombination
    - Volume wird in eignen Einheiten angeben und muss für die jeweilige Spritze
      bestimmt werden.
    - load brint das Ventil in die Load Position
    - ventil injiziert in den Reaktionslauf
    - volume fragt nach der aktuellen Postion der Spritze
    - Spritze Home zieht die Spritze auf
    - Spritze leer entleert die Spritze """
command = []

ports = serial.tools.list_ports.comports()
serialObj = serial.Serial()

def serial_ports():
    return serial.tools.list_ports.comports()

def on_select(event=None):
    serialObj.port = cb.get().split(' ')[0]
    serialObj.baudrate = 115200
    serialObj.open()

root = tk.Tk()
#configue root
root.title("Jfs Besta")
root.geometry('800x500+300+300')
root.columnconfigure(0,weight=1)
root.rowconfigure(1,weight=1)
port = tk.IntVar()

cb =ttk.Combobox(root,values=serial_ports())
cb.grid(row=0,column=0,stick="nwe")
cb.bind('<<ComboboxSelected>>',on_select)

scb =tk.Scrollbar(root)
scb.grid(row=1,column=1,sticky='ns')
txt = tk.Text(root)
txt.grid(row=1,column=0,sticky='ewns')
scb.config(command=txt.yview)
txt.config(yscrollcommand=scb.set)
txt.tag_configure('small',font=('Verdana',8),foreground='black')

portlbl = ttk.Label(root,textvariable=port,background='grey',font='none 24 bold')
portlbl.config(anchor=tk.CENTER)
portlbl.grid(row=0,column=2,sticky='nsew')

left = ttk.LabelFrame(root,text='Commands')
left.grid(row=1,column=2,sticky='ne')

down = ttk.LabelFrame(root,text='Automatik')
down.grid(row=2,column=0,sticky='nw')



class Callback:
    def __init__(self,func,*args,**kwargs):
            self.func=func
            self.args=args
            self.kwargs=kwargs
    def __call__(self):
        self.func(*self.args,**self.kwargs)

def default_callback(i):
        cmd = str(i)+'\r\n'
        command.append(cmd.encode('utf-8'))

def do_cmd(i):
        cmd = str(i)+'\r\n'
        command.append(cmd.encode('utf-8'))
        
cc = 0
max = 10
run = False
startTime = 0

injvol = tk.IntVar()
injvol.set(30)
inj = tk.IntVar()
inj.set(10)
loadtime = tk.IntVar()
loadtime.set(10)
proctime = tk.IntVar()
proctime.set(30)
jfstime = 0
cas = 0  # 0-idle 1-next Injection
dela = 2
stat = tk.StringVar()
aktvol = tk.IntVar()

ttk.Button(left,text='load',command=Callback(default_callback,1)).grid(row=0,column=0)
ttk.Button(left,text='ventil',command=Callback(default_callback,2)).grid(row=1,column=0)
ttk.Button(left,text='volume',command=Callback(default_callback,5)).grid(row=2,column=0)
ttk.Button(left,text='Spritze Home',command=Callback(default_callback,3)).grid(row=3,column=0)
ttk.Button(left,text='Spritze leer',command=Callback(default_callback,4)).grid(row=4,column=0)
ttk.Label(down,text=' Injections: ').grid(row=0,column=0)
ttk.Entry(down,textvariable=inj,width=4).grid(row=0,column=1)
ttk.Label(down,text=' Inj Vol ').grid(row=0,column=2)
ttk.Entry(down,textvariable=injvol,width=4).grid(row=0,column=3)
ttk.Label(down,text=' Loadtime ').grid(row=0,column=4)
ttk.Entry(down,textvariable=loadtime,width=4).grid(row=0,column=5)
ttk.Label(down,text=' Processtime ').grid(row=0,column=6)
ttk.Entry(down,textvariable=proctime,width=4).grid(row=0,column=7)
autom = tk.Button(down,text=' Do the job')
autom.grid(row=0,column=8,sticky='ne')
ttk.Label(down,text=' Status ').grid(row=0,column=9)
ttk.Label(down,textvariable=stat).grid(row=0,column=10)
ttk.Label(down,text=' Volume left ').grid(row=0,column=11)
ttk.Label(down,textvariable=aktvol).grid(row=0,column=12)

def do_count():
    global cc, max, startTime, cas, dela, jfstime, run
    elapsed = time.time()-startTime  
    if elapsed > 1:
        #print(cas)
        startTime = time.time()
        if  cas == 0:
                stat.set('idle.... ')
                pass
        elif cas == 1:
                stat.set('Aktual..   '+str(inj.get()))
                if inj.get() == 0:
                    run = False
                    stat.set('Finished')
                    cas = 0
                else:
                    inj.set(inj.get()-1)
                    do_cmd(1)
                    jfstime=loadtime.get()
                    if injvol.get() >= aktvol.get():
                        stat.set('Error No Vol')
                        run = False
                        cas = 0
                    else:
                        do_cmd(injvol.get())
                        cas = 2
        elif cas == 2:
                stat.set('Load..'+str(jfstime))
                if jfstime == 0:
                    do_cmd(2)
                    jfstime = proctime.get()
                    cas = 3
                else :
                    jfstime -= 1
        elif cas == 3:
                stat.set('Process..'+str(jfstime))
                if jfstime == 0:
                    do_cmd(1)
                    jfstime = dela
                    cas = 4
                else:
                    jfstime -= 1
        elif cas == 4:
                stat.set('Delay..'+str(jfstime))
                if jfstime == 0:
                    cas = 1
                else:
                    jfstime -= 1

            

            
                    

      
def doItNow():
    global run
    if run :
        do_count()
    root.after(100,doItNow)

def do_tasks():   
    global run, startTime, cas
    if run :
        run = False
        autom.configure(text='stopped')
    else :
        run = True
        startTime = time.time()
        cas = 1
        autom.configure(text='working')
        doItNow()

      
autom.configure(command=do_tasks)

txt.insert('0.1',help)

weiter = True
def checkSerialPort():
    global weiter
    if serialObj.isOpen() and serialObj.in_waiting:
       inp = serialObj.readline().decode('utf')
       txt.insert('0.1',inp)
       aktvol.set(int(inp))
       weiter = True
    if  (len(command) > 0) & (weiter==True) :
        if serialObj.isOpen() :
            x = command.pop(0)
            txt.insert('0.1',x,'small')
            serialObj.write(x)
            weiter=False
        else :
            txt.insert('0.1','Kein Port geöffnet !!!\n')
            x = command.clear()      

while True:
    root.update()
    checkSerialPort()
   