#!/usr/bin/env python

# GRAPHICAL interface for setup of QMX calculations
#
# Torsten Kerber, ENS LYON: 2011, 07, 11
#
# This work is supported by Award No. UK-C0017, made by King Abdullah
# University of Science and Technology (KAUST)

#---------------------------------------------------------------------------------------------------
from Tkinter import *
from copy import deepcopy
import StringIO, os

#---------------------------------------------------------------------------------------------------
from qmxEMBED import embedDefinitions
from qmxJOB import jobDefinitions
from qmxSTR import strDefinitions
from qmxCALC import calcDefinitions, QmxCalcDefinition

from qmxWRITE import writeData

#---------------------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------
class MyLabelFrame(LabelFrame):
    def __init__(self, mainWnd, master, title, def_list, extras):
        LabelFrame.__init__(self, master, text=title)
        self.mainWnd = mainWnd
        self.definitions=[]
        self.title = title

        for definition in def_list:
            definition_new = deepcopy(definition)
            definition_new.system = title
            self.definitions.append(definition_new)

        fields=['import', 'class', 'class.options']
        if extras is not None:
            for key in extras:
                fields.append(key)

        self.entries=[]
        for key in fields:
            text=StringVar()
            text.set('')
            self.entries.append((key, text, Entry(self, textvariable=text, width=15)))
            
    def grid(self, **arguments):
        LabelFrame.grid(self, arguments, sticky=(N+W+E))
        self.listbox.selection_set(first=0)
        self.select(None)
        
    def doLayout(self):
        irow=0
        for (key, text, textfield) in self.entries:
            Label(self, text=key, width=15, anchor=W).grid(row=irow)
            textfield.grid(row=irow, column=1)
            textfield.bind("<KeyRelease>", self.update)
            irow+=1
        
        scrollbar=Scrollbar(self, orient=VERTICAL)
        self.listbox=Listbox(self, yscrollcommand=scrollbar.set, height=0, width=15, selectmode=SINGLE)
        self.listbox.grid(row=0, column=2, rowspan=irow, columnspan=2, sticky=NS)
        self.listbox.bind('<ButtonRelease-1>', self.select)

        scrollbar.config(command=self.listbox.yview)
        scrollbar.grid(row=0, column=4, rowspan=irow, sticky=NS)
       
        for item in self.definitions:
            self.listbox.insert(END, item.name)
        
    def select(self, event):
        selection=self.listbox.curselection()
        if len(selection) == 1:
            self.curr_definition=deepcopy(self.definitions[int(selection[0])])
            for (key, text, textfield) in self.entries:
                text.set(self.curr_definition.getValue(key))
        self.mainWnd.preview()
    
    def getSelection(self):
        return self.curr_definition
        
    def update(self, event):
        for (key, text, textfield) in self.entries:
            self.curr_definition.keywords[key]=text.get()
        self.mainWnd.preview()

#---------------------------------------------------------------------------------------------------
class MainWindow(Frame):
    frames=[]
    text=None
    def __init__(self, master):
        Frame.__init__(self, master)
        
        #--- Structures ---
        bigFrame = LabelFrame(self, text='Structures')
        irow=0; icol=0
        def_list=embedDefinitions
        extras=['method', 'method.options', 'calculator']
        frame=MyLabelFrame(self, bigFrame, 'Embed', def_list, extras)
        frame.doLayout()
        frame.grid(row=irow, column=icol)
        self.frames.append(frame)

        icol+=1;
        for label in ['System', 'Cluster']:
            def_list=strDefinitions
            frame=MyLabelFrame(self, bigFrame, label, def_list, None)
            frame.doLayout()
            frame.grid(row=irow, column=icol)
            self.frames.append(frame)
            icol+=1
        bigFrame.grid(row=0, columnspan=3)

        #--- Methods ---
        bigFrame = LabelFrame(self, text='Methods')
        irow=0; icol=0
        def_list=[QmxCalcDefinition()]
        frame=MyLabelFrame(self, bigFrame, 'Qmx', def_list, None)
        frame.doLayout()
        frame.grid(row=irow, column=icol)
        self.frames.append(frame)

        icol+=1
        for label in ['High-Level', 'Low-Level']:
            def_list=calcDefinitions
            frame=MyLabelFrame(self, bigFrame, label, def_list, None)
            frame.doLayout()
            frame.grid(row=irow, column=icol)
            self.frames.append(frame)
            icol+=1
        bigFrame.grid(row=1, columnspan=3)
        
        #--- General ---
        bigFrame = LabelFrame(self, text='General')
        extras=['method', 'method.options']
        frame=MyLabelFrame(self, bigFrame, 'Job', jobDefinitions, extras)
        frame.doLayout()
        frame.grid()
        self.frames.append(frame)
        bigFrame.grid(row=2, sticky=NW)

        frame=LabelFrame(self, text="PREVIEW")
        scrollbar=Scrollbar(frame, orient=VERTICAL)
        scrollbar.set(0.0, 1.0)
        self.text=Text(frame, yscrollcommand=scrollbar.set, width=60, heigh=10, state=DISABLED)
        self.text.grid(sticky=(N+W+S+E))
        scrollbar.config(command=self.text.yview)
        scrollbar.grid(row=0, column=1, sticky=NS)        
        frame.grid(row=2, column=1)

        frame = Frame(self)

        image = PhotoImage(file="exit.gif")
        buttonExit=Button(frame, image=image, command=self.quit)
        buttonExit.image = image
        buttonExit.grid(row=1, column = 1, rowspan=2, sticky= W+E+N+S)
        
        buttonSave=Button(frame, text='save settings', state=DISABLED)
        buttonSave.grid(row=1, column = 2, sticky=(EW))

        buttonPrint=Button(frame, text='Write qmx.py input file', command=self.writeButton)
        buttonPrint.grid(row=2, column = 2, sticky=EW)

        frame.grid(row=2, column=2, sticky=SE)

        #--- MainWindow ---
        self.grid(sticky=(W+N+S+E))
        self.preview()
        
    def quit(self):
        quit()
    
    def writeButton(self):
        file = open("qmx.py","w")
        definitions=[]
        for frame in self.frames:
            definition = frame.getSelection()
            if definition is not None:
                definitions.append(definition)

        writeData(file, definitions)
        file.close()
        os.system("chmod u+x qmx.py")

    def preview(self):
        stream = StringIO.StringIO()
        definitions=[]
        for frame in self.frames:
            definition = frame.getSelection()
            if definition is not None:
                definitions.append(definition)

        writeData(stream, definitions)
        s = stream.getvalue()
        
        if self.text is not None:
            pos, end = self.text.yview()
            self.text.config(state=NORMAL)
            self.text.delete(1.0, END)
            self.text.insert(END, s)
            self.text.config(state=DISABLED)
            self.text.yview(MOVETO, pos)

#---------------------------------------------------------------------------------------------------
mainWnd=MainWindow(Tk())
mainWnd.mainloop()
