import Tkinter, tkFileDialog
from Tkinter import *

def done():
    global T122, other_stuff, ex_num, fan_on, partspeed
    T122 = T1.get()
    other_stuff = T2.get()
    ex_num = extruder.get()
    fan_on = check.get()
    partspeed = partspeed2.get()
    # error handling
    global top
    top = Toplevel(root)
    top.geometry("+%d+%d" % (root.winfo_rootx() + root.winfo_width() / 2, root.winfo_rooty() + root.winfo_height() / 2))
    top.grab_set()
    if thinfilename is None or thickfilename is None or outfilename is None or T122 == "" or other_stuff == "":
        error = ""
        fields = [ thinfilename, thickfilename, outfilename, T122, other_stuff ]
        for f in range(len(fields)):
            if fields[f] is None or fields[f] == "":
                if error != "":
                    error += ","
                if f == 0:
                    error += " the thin file"
                elif f == 1:
                    error += " the thick file"
                elif f == 2:
                    error += " the save file"
                elif f == 3:
                    error += " the first layer temperature"
                elif f == 4:
                    error += " the part build temperature"
        Label(top, text="You did not set" + error).grid(row=0, ipadx=20, ipady=10)
        Button(top, text="Fix", command=top.destroy).grid(row=1, ipady=10)
    else:
        process()

def get_thin_file():
    global thinfilename
    filename = tkFileDialog.askopenfilename(**{'title': 'Please select thin file'})
    if filename != '':
        thinfilename = filename
        thin_label_text.set("Thin set as: " + thinfilename)
        thin_button_text.set("Change Thin File")

def get_thick_file():
    global thickfilename
    filename = tkFileDialog.askopenfilename(**{'title': 'Please select thick file'})
    if filename != '':
        thickfilename = filename
        thick_label_text.set("Thick set as: " + thickfilename)
        thick_button_text.set("Change Thick File")

def save_as_filename():
    global outfilename
    filename = tkFileDialog.asksaveasfilename()
    if filename != '':
        outfilename = filename
        save_label_text.set("Save as set as: " + outfilename + ".bfb")
        save_button_text.set("Change Save As")

def run():
    global root
    root = Tk()
    root.title("BFB Derafter_Splicer")
    global thinfilename, thickfilename, outfilename
    thinfilename = thickfilename = outfilename = None
    
    global thin_button_text, thin_label_text
    thin_button_text = StringVar()
    thin_button_text.set("Select Thin File")
    Button(root, textvariable = thin_button_text, command = get_thin_file).grid(row=0, column=0, sticky=W, padx=20)
    thin_label_text = StringVar()
    thin_label_text.set("Thin not set yet")
    Label(root, textvariable=thin_label_text, height=4).grid(row=0, column=1, sticky=W)
    
    global thick_button_text, thick_label_text
    thick_button_text = StringVar()
    thick_button_text.set("Select Thick File")
    Button(root, textvariable = thick_button_text, command = get_thick_file).grid(row=1, column=0, sticky=W, padx=20)
    thick_label_text = StringVar()
    thick_label_text.set("Thick not set yet")
    Label(root, textvariable=thick_label_text, height=4).grid(row=1, column=1, sticky=W)
    
    Label(root, text="First Layer Temperature", height=4).grid(row=2, column=0, sticky=W, padx=20)
    
    global T1
    T1 = Entry(root, width=5)
    T1.grid(row=2, column=1, sticky=W)
    
    Label(root, text="Thin File Layer Thickness", height=4).grid(row=2, column=3, sticky=W)
    
    global partspeed2
    partspeed2 = StringVar()
    partspeed2.set('.125mm')
    OptionMenu(root, partspeed2, '.125mm', '.25mm', '.5mm').grid(row=2, column=4, sticky=W, padx=20)
    
    Label(root, text="Part Build Temperature", height=4).grid(row=3, column=0, sticky=W, padx=20)
    
    global T2
    T2 = Entry(root, width=5) 
    T2.grid(row=3, column=1, sticky=W)
    
    Label(root, text="Active Extruder Number", height=4).grid(row=4, column=0, sticky=W, padx=20)
    
    global extruder # enter 1, 2, or 3
    extruder = IntVar()
    extruder.set(1)
    OptionMenu(root, extruder, 1, 2, 3).grid(row=4, column=1, sticky=W)
    
    global check
    check = IntVar()
    Checkbutton(root, variable = check, text = "Fan on?").grid(row=5, column=0, sticky=W, padx=20)
    
    global save_button_text, save_label_text
    save_button_text = StringVar()
    save_button_text.set("Save As")
    Button(root, textvariable = save_button_text, command = save_as_filename).grid(row=6, column=0, sticky=W, padx=20)
    save_label_text = StringVar()
    save_label_text.set("Save as not set yet")
    Label(root, textvariable=save_label_text, height=4).grid(row=6, column=1, sticky=W)
    
    Button(root, text='Done!', width=20, command=done).grid(row=7, column=2, sticky=W, pady=20)
    
    root.mainloop()

def deraft(lines):
    lines.pop(1)
    lines = [string.replace('M108 S675.0','M108 S575.0') for string in lines]
    line = 0
    count = 0
    while count < 3:
        if 'M108' in lines[line]:
            count = count +1
        line = line+1
    lines = lines[line-3:]
    
    for line in range(len(lines)):
        if 'Z' in lines[line]:
            zloc = lines[line].index('Z')
            floc = lines[line].index(' ', zloc + 1)
            lines[line] = lines[line][0:zloc+1] + str(float(lines[line][zloc+1:floc])-1) + lines[line][floc:len(lines[line])]
    return(lines)

def merge(thin, thick):
    #Merges thin and thick files, using thick for Z0.5 and thin thereafter
    Z_list = [] # creates a list of lines that contain the string 'Z0.5'
    for line in range(len(thick)):
        if 'Z0.5' in thick[line]:
            Z_list.append(line)
    end_thick = max(Z_list)
    
    start_thin = 0
    line = 0
    while start_thin == 0:
        if 'Z' in thin[line]:
            zloc = thin[line].index('Z')
            floc = thin[line].index(' ', zloc + 1)
            if float(thin[line][zloc+1:floc]) > 0.5: 
                start_thin = line
        line += 1
    
    transition_list = ['M103\n', 'M542\n','M107\n','M'+str(ex_num)+'04'+' S' + str(other_stuff)+'\n']
    if fan_on ==1:
        transition_list.append('M106\n')
    transition_list.append('M55'+str(ex_num)+' P57600 S600\n')
    transition_list.append('M543\n')
    transition_list.append('M103\n')
    if partspeed == '.125mm':
        transition_list.append('M108 S80\n')
    if partspeed == '.25mm':
        transition_list.append('M108 S200\n')
    if partspeed == '.5mm':
        transition_list.append('M108 S600\n')
    c = str('M'+str(ex_num)+'01\n')
   
    start_list = ['^Axon version: 2.0.1\n','^Time: 1234\n','^Ex1: ABS black\n', '^Ex2: Evan Hot PLA\n','^Ex3: Matt HOTTER PLA\n','M113 S1.0\n','M227 P3200 S3200\n','M542\n','M107\n']
    start_list.append('M204 S'+str(T122)+'\n')
    if fan_on==1:
        start_list.append('M106\n')
    start_list.append('M55' + str(ex_num) + ' P57600 S600\n')
    start_list.append('M543\n')
    start_list.append('M107\n')
    start_list.append('M103\n')
    if fan_on == 1:
        start_list.append('M106\n')
    
    return(start_list+thick[:end_thick]+transition_list + thin[start_thin:])

def write(write_lines, write_to):
    for line in write_lines:
        write_to.write(line)

def process():
    infilethin = open(thinfilename, 'r')
    infilethick = open(thickfilename, 'r')
    outfile = open(outfilename + '.bfb','w')
    
    thin_line_list = infilethin.readlines()
    thick_line_list = infilethick.readlines()
    
    try:
        deraft_thin = deraft(thin_line_list)
        deraft_thick = deraft(thick_line_list)
        merged = merge(deraft_thin, deraft_thick)
        write(merged, outfile)
    except Exception as e:
        Label(top, text="Error: " + e.args[0]).grid(row=0, ipadx=20, ipady=10)
        Button(top, text="Fix", command=top.destroy).grid(row=1, ipady=10)
    else:
        # window that displays 'success' for 1-2 seconds.
        Label(top, text="Success!").grid(row=0, column=0, ipadx=50, ipady=50)
        top.title("Hooray")
        top.after(1000, root.destroy)
    finally:
        infilethin.close()
        infilethick.close()
        outfile.close()

run()
