from lib2to3 import refactor
from shutil import register_unpack_format
import tkinter as tk
import tkinter.ttk as ttk
import os
from configparser  import ConfigParser
import serial.tools.list_ports
from idlelib.tooltip import *
from labrobot import LabReactBlock
from labrobot import ChemLoc
import labrobot as lrb
# serial ports
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 = 115000
    serialObj.open()

# commands
command = []

## main,'
orders =['Home','HomeX','HomeY']

## chemicals
substances = ['Water','Propanol','Aceton']
clabels = ['x','y','z','volume','z/ml','reakvolume']
centrys = []
chem_config = ConfigParser()

def load_chem_config():
    chem_config.read(os.path.join(os.path.dirname(__file__), "chemicals.ini"),)
def conf_chem_write():
     for p in substances:
        chem_config[p] =  {}
        for x in centrys:
            if x[0] == p:
                chem_config[p][x[1]] = x[2].get()
     with open(os.path.join(os.path.dirname(__file__), "chemicals.ini"),'w') as f:
         chem_config.write(f)
def init_chem():
    c =0 
    r = 0
    for p in substances:
        frame = ttk.LabelFrame(chemframe,text=p)
        frame.grid(column=c,row=r)
        c +=1
        if c > 4:
            c=0
            r +=1
        for i in range(len(clabels)):
            tk.Label(frame,text=clabels[i]).grid(row=i,column=0)
            var = tk.StringVar()
            entry = tk.Entry(frame,width=10,textvariable=var)
            var.set(chem_config[p][clabels[i]])
            entry.grid(row=i,column=1,sticky='w')
            centrys.append([p,clabels[i],entry])

## vessels
vessels = ['1ml','HPLC','Kuvette']
vlabels = ['rxoffset','ryoffset','rrows','rcols','rxspace','ryspace','rzlevel']
ventrys = []
vess_config = ConfigParser()
def load_vess_config():
    vess_config.read(os.path.join(os.path.dirname(__file__), "vessels.ini"),)
def conf_vess_write():
     for p in vessels:
        vess_config[p] =  {}
        for x in ventrys:
            if x[0] == p:
                vess_config[p][x[1]] = x[2].get()
     with open(os.path.join(os.path.dirname(__file__), "vessels.ini"),'w') as f:
         vess_config.write(f)
def init_vess():
    c =0 
    r = 0
    for p in vessels:
        frame = ttk.LabelFrame(vessframe,text=p)
        frame.grid(column=c,row=r)
        c +=1
        if c > 4:
            c=0
            r +=1
        for i in range(len(vlabels)):
            tk.Label(frame,text=vlabels[i]).grid(row=i,column=0)
            var = tk.StringVar()
            entry = tk.Entry(frame,width=10,textvariable=var)
            var.set(vess_config[p][vlabels[i]])
            entry.grid(row=i,column=1,sticky='w')
            ventrys.append([p,vlabels[i],entry])

##pipettes

pipettes = ['1000','200','100']
plabels = ['xoffset','yoffset','rows','cols','xspace','yspace','tipvol','zlevel','tipup','tipdown','tipspeed','tiphub']
pentrys = []
pipet_config = ConfigParser()
def load_pipet_config():
    pipet_config.read(os.path.join(os.path.dirname(__file__), "pipettes.ini"),)
def pipet_vess_write():
     for p in pipettes:
        pipet_config[p] =  {}
        for x in pentrys:
            if x[0] == p:
                pipet_config[p][x[1]] = x[2].get()
     with open(os.path.join(os.path.dirname(__file__), "pipettes.ini"),'w') as f:
         pipet_config.write(f)
def init_pipet():
    c =0 
    r = 0
    for p in pipettes:
        frame = ttk.LabelFrame(pipetframe,text=p)
        frame.grid(column=c,row=r)
        c +=1
        if c > 4:
            c=0
            r +=1
        for i in range(len(plabels)):
            tk.Label(frame,text=plabels[i]).grid(row=i,column=0)
            var = tk.StringVar()
            entry = tk.Entry(frame,width=10,textvariable=var)
            var.set(pipet_config[p][plabels[i]])
            entry.grid(row=i,column=1,sticky='w')
            pentrys.append([p,plabels[i],entry])

root = tk.Tk()
akttip = tk.IntVar()
lbp = lrb.LabPipBlock
pip = lrb.LabPip
startVessel = tk.IntVar()
lastVessel = tk.IntVar()
##init
load_chem_config()
substances = chem_config.sections()
load_vess_config()
vessels = vess_config.sections()
load_pipet_config()
pipettes= pipet_config.sections()
print(pipettes)

#configue root
root.title("Jfs Labrobot")
root.geometry('800x500+300+300')
notebook = ttk.Notebook(root)
#notebook.grid(sticky='news',padx=5,pady=5)
notebook.pack(fill='both',expand=1)
notebook.enable_traversalrightmainframe = ttk.Frame(notebook)
## mainframe left
mainframe = ttk.Frame(notebook)
mainframe.columnconfigure(0,weight=1)
notebook.add(mainframe,text='main',underline=0)
leftframe = ttk.LabelFrame(mainframe,text='Serial Connection')
leftframe.columnconfigure(0,weight=1)
leftframe.rowconfigure(1,weight=1)
leftframe.grid(column=0,row=0,sticky='news')
cb =ttk.Combobox(leftframe,values=serial_ports())
cb.grid(row=0,column=0,stick="nwe")
cb.bind('<<ComboboxSelected>>',on_select)
scb =tk.Scrollbar(leftframe)
scb.grid(row=1,column=1,sticky='ns')
#txt = tk.Text(leftframe,height=30,width=50)
txt = tk.Text(leftframe)
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')
#mainframe right
rightframe = ttk.Frame(mainframe)
rightframe.columnconfigure(0,weight=1)
rightframe.rowconfigure(0,weight=1)
rightframe.grid(column=1,row=0,sticky='new')

uprightframe =ttk.LabelFrame(rightframe,text='Basic')
uprightframe.grid(column=0,row=0,sticky='ns')

downrightframe =ttk.LabelFrame(rightframe,text='More to select')
downrightframe.grid(column=0,row=1,sticky='new',pady=5)

b1 = ttk.Button(uprightframe,text='Home All',width=12)
b1.grid(row=0,column=0,sticky='nw')
b1t = Hovertip(b1,'All Axis to Home\nZ-axis first')
b2 = ttk.Button(uprightframe,text='Home X',width=12)
b2.grid(row=0,column=1,sticky='ne')
b3 = ttk.Button(uprightframe,text='Home Y',width=12)
b3.grid(row=1,column=0,sticky='nw')
b4 = ttk.Button(uprightframe,text='Home Z',width=12)
b4.grid(row=1,column=1,sticky='ne')
b6 = ttk.Button(uprightframe,text='Home P',width=12)
b6.grid(row=2,column=0,sticky='nw')
b7 = ttk.Button(uprightframe,text='Get Position',width=12)
b7.grid(row=2,column=1,sticky='ne')
l1 = ttk.Label(uprightframe,text="Enter G-Code").grid(row=3,column=0)
e1 = ttk.Entry(uprightframe)
e1.grid(row=3,column=1)
b5 = ttk.Button(uprightframe,text='Send Code')
b5.grid(row=4,column=1,sticky="ne")
b5t = Hovertip(b5,'Send Gcode\ndon\'t forget < >')

b8 = ttk.Button(downrightframe,text='Next Tip')
b8.grid(row=0,column=0,sticky='ne')
b9 = ttk.Button(downrightframe,text='Up')
b9.grid(row=0,column=1,sticky='ne')
b10 = ttk.Button(downrightframe,text='Down')
b10.grid(row=0,column=2,sticky='ne')
b11 = ttk.Button(downrightframe,text='Top')
b11.grid(row=1,column=0,sticky='ne')
b13 = ttk.Button(downrightframe,text='Load')
b13.grid(row=1,column=1,sticky='ne')
b12 = ttk.Button(downrightframe,text='Dispense')
b12.grid(row=1,column=2,sticky='ne')
b14 = ttk.Button(downrightframe,text='Take Chem')
b14.grid(row=2,column=0,sticky='ne')
b15 = ttk.Button(downrightframe,text='Next Vessel')
b15.grid(row=2,column=1,sticky='ne')
b16 = ttk.Button(downrightframe,text='Load Next')
b16.grid(row=2,column=2,sticky='ne')
ttk.Label(downrightframe,text='Start Vessel').grid(row=3,column=0,sticky='e')
e2 =ttk.Entry(downrightframe,width=5)
e2.grid(row=3,column=1,sticky='w')
ttk.Label(downrightframe,text='Last Vessel').grid(row=4,column=0,sticky='e')
e3 =ttk.Entry(downrightframe,width=5)
e3.grid(row=4,column=1,sticky='w')
b17 = ttk.Button(downrightframe,text='Load All')
b17.grid(row=4,column=2,sticky='e')
b18 = ttk.Button(downrightframe,text='Clear Tip')
b18.grid(row=3,column=2,sticky='e')

## Robot
downrightframe2 =ttk.LabelFrame(rightframe,text='Robot')
downrightframe2.grid(column=0,row=3,sticky='new',pady=5)  
## Chemicals  
fra1 = ttk.LabelFrame(downrightframe2,text=' Chemicals')
fra1.grid(row=0,column=0,sticky='nw')
chemsub = tk.StringVar()
chemvol = tk.StringVar()            #Volumen
reacvol = tk.StringVar()            #Reaktionsvolumen
ttk.Label(fra1,text='Vol[ml]').grid(row=0,column=1)
ttk.Label(fra1,textvariable=chemvol).grid(row=0,column=2)
ttk.Label(fra1,text='Reac[ul]').grid(row=0,column=3)
ttk.Label(fra1,textvariable=reacvol).grid(row=0,column=4)

def do_chemicals(*args):
    global chem 
    chem = ChemLoc(chem_config[chemsub.get()]['x'],
                    chem_config[chemsub.get()]['y'],
                    chem_config[chemsub.get()]['z'],
                    chem_config[chemsub.get()]['volume'],
                    chem_config[chemsub.get()]['z/ml'],
                    chem_config[chemsub.get()]['reakvolume'],
                    )

    chemvol.set(chem_config[chemsub.get()]['volume'])
    reacvol.set(chem_config[chemsub.get()]['reakvolume'])

chemopt = ttk.OptionMenu(fra1,chemsub,substances[0],*substances,command=do_chemicals)
chemopt.grid(row=0,column=0,sticky='e')

do_chemicals()

## Pipettes
fra2 = ttk.LabelFrame(downrightframe2,text=' Pipettes')
fra2.grid(row=1,column=0,sticky='nw')
pips = tk.StringVar()
def do_pipettes(*args):
    global lpb
    lpb = lrb.LabPipBlock(pipet_config[pips.get()]['xoffset'],
            pipet_config[pips.get()]['yoffset'],
            pipet_config[pips.get()]['zlevel'],
            pipet_config[pips.get()]['rows'],
            pipet_config[pips.get()]['cols'],
            pipet_config[pips.get()]['xspace'],
            pipet_config[pips.get()]['yspace'])
    global pip
    pip = lrb.LabPip(pipet_config[pips.get()]['tipvol'],
                    pipet_config[pips.get()]['tiphub'],
                    pipet_config[pips.get()]['tipspeed'],
                    pipet_config[pips.get()]['tipup'])

pipopt = ttk.OptionMenu(fra2,pips,pipettes[0],*pipettes,command=do_pipettes)
pipopt.grid(row=0,column=0,sticky='ew')
do_pipettes()
aktvol = tk.StringVar()
aktvol.set('----')
ttk.Label(fra2,textvariable=aktvol).grid(row=0,column=1,sticky='ew')
ttk.Label(fra2,text='Tip Nr').grid(row=0,column=2)
ttk.Label(fra2,textvariable=akttip).grid(row=0,column=4)

## Vessels
fra3 = ttk.LabelFrame(downrightframe2,text=' Vessels')
fra3.grid(row=2,column=0,sticky='nw')
vess = tk.StringVar()
aktvess = tk.StringVar()
def do_vessels(*args):
    global reakt
    reakt = LabReactBlock(vess_config[vess.get()]['rxoffset'],
                          vess_config[vess.get()]['ryoffset'],
                          vess_config[vess.get()]['rzlevel'],
                          vess_config[vess.get()]['rrows'],
                          vess_config[vess.get()]['rcols'],
                          vess_config[vess.get()]['rxspace'],
                          vess_config[vess.get()]['ryspace'],
                        
    )
vessopt = ttk.OptionMenu(fra3,vess,vessels[0],*vessels,command= do_vessels)
vessopt.grid(row=0,column=0)
ttk.Label(fra3,text='Vessel Nr').grid(row=0,column=1)
ttk.Label(fra3,textvariable=aktvess).grid(row=0,column=2)

do_vessels()

## main serial command
def homeAll():
    serialObj.write(b'<G28>\n')  
    #print(lpb.say_ok(), pip.getVol())  
b1.configure(command=homeAll)

def homeX():
    serialObj.write(b'<JX>\n')
b2.configure(command=homeX)

def homeY():
    serialObj.write(b'<JY>\n')
b3.configure(command=homeY)

def homeZ():
    serialObj.write(b'<JZ>\n')    
b4.configure(command=homeZ)

def homeP():
    serialObj.write(b'<JP>\n')    
b6.configure(command=homeP)

def getPos():
    serialObj.write(b'<J2>\n')      
b7.configure(command=getPos)

def do_gcode():
    s = e1.get()
    s = s + '\n'
    print(s)
    serialObj.write(s.encode('utf-8')) 
b5.configure(command=do_gcode)

def upTip():
    command.append(pip.up().encode('utf-8'))    
b9.configure(command=upTip)

def downTip():
    command.append(pip.down().encode('utf-8'))  
b10.configure(command=downTip)

def top():
    command.append(pip.go_top().encode('utf-8'))     
b11.config(command=top)

def nextTip():
    upTip()
    top()
    serialObj.write(pip.get_tip(lpb.next()).encode('utf-8')) 
    akttip.set(lpb.akt)
    downTip()    
b8.configure(command=nextTip)

def load():
    if pip.amIdown() == False:
        command.append(pip.go_top().encode('utf-8'))
        command.append(pip.go_down().encode('utf-8'))
        command.append(pip.go_top().encode('utf-8'))
    else:
        command.append(pip.go_top().encode('utf-8'))
    pip.setVolMax()
    aktvol.set(pip.getVol())
b13.config(command=load)

def dispense():
    v = float(reacvol.get())
    if pip.dispenseVol(v):
        command.append(pip.sendE().encode('utf-8'))
    else : 
        takeChem()
        upTip()
        command.append(pip.get_tip(reakt.same()).encode('utf-8'))
        downTip()
        if pip.dispenseVol(v):
            command.append(pip.sendE().encode('utf-8'))
        else:
            print('Error')
    aktvol.set(pip.getVol()) 
    print(pip.getVol())   

b12.config(command=dispense)


def takeChem():
    upTip()
    pip.setXY(chem.getXY())
    command.append(pip.sendXY().encode('utf-8'))
    pip.setZ(chem.load(pip.vol/1000))  #load 1ml
    command.append(pip.down().encode('utf-8'))
    load()
    command.append(pip.up().encode('utf-8'))
    #chemVol.set(chem.vol)
b14.config(command=takeChem)

def nextVessel():
    upTip()
    command.append(pip.get_tip(reakt.next()).encode('utf-8')) 
    aktvess.set(reakt.akt)
    downTip()   
b15.config(command=nextVessel)

def loadNext():
    upTip()
    takeChem()
    nextVessel()
    dispense()
    upTip()
b16.config(command=loadNext)

def loadSerie():
    takeChem()
    p = startVessel.get()
    q = lastVessel.get() + 1
    for i in range(p,q):       
        print(i)
        reakt.akt = i
        aktvess.set(reakt.akt)
        upTip()
        command.append(pip.get_tip(reakt.same()).encode('utf-8'))
        downTip()
        dispense()
    upTip()
b17.config(command=loadSerie)

def clearTip():
    upTip()
    pip.setXY(chem.getXY())
    command.append(pip.sendXY().encode('utf-8'))
    pip.clearVol()
    command.append(pip.sendE().encode('utf-8'))

b18.config(command=clearTip)


##chemicals
chemframe = ttk.Frame(notebook)
notebook.add(chemframe,text='chemicals',underline=0)
init_chem()
tk.Button(chemframe,text='Load',command = load_chem_config).grid(row=100,column=0,sticky='ew')
tk.Button(chemframe,text='Save',command = conf_chem_write).grid(row=100,column=1,sticky='ew')
##vessels
vessframe = ttk.Frame(notebook)
notebook.add(vessframe,text='vessel',underline=0)
init_vess()
##pipettes
pipetframe = ttk.Frame(notebook)
notebook.add(pipetframe,text='pipettes',underline=0)
init_pipet()

### Init Vars
startVessel.set(1)
e2.config(textvariable=startVessel)
lastVessel.set(6)
e3.config(textvariable=lastVessel)

## looping and working
weiter = True
def checkSerialPort():
    global weiter
    if serialObj.isOpen() and serialObj.in_waiting:
        recentPacket = serialObj.readline()
        recentPacketString  = recentPacket.decode('utf')
        txt.insert('0.1',recentPacketString,'small')
        weiter = True
    if  (len(command) > 0) & (weiter==True) :
            x = command.pop(0)
            txt.insert('0.1',x,'small')
            serialObj.write(x)
            weiter=False
           


while True:
    root.update()
    checkSerialPort()