#!/usr/bin/env python
# -*- coding: utf-8 -*-
# generated by wxGlade 0.6.5 on Mon Jan 28 11:48:33 2013

import wx
import time
import os
import subprocess

# begin wxGlade: extracode
# end wxGlade

#Global variables to hold file paths
register_file = ""
basic_file = ""
family_file = ""
cons_file = ""
queries_txt = ""
queries_file = ""
results_file = ""
basic_parse = ""
family_parse = ""
con_parse = ""
cond_parse = ""
code_genrated = ""
compile_sh = ""
file_path = ""

class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        # begin wxGlade: MyFrame.__init__
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        
        # Menu Bar
        self.frame_1_menubar = wx.MenuBar()
        self.file_menu = wx.Menu()
        self.new_item = wx.MenuItem(self.file_menu, wx.NewId(), "New", "New", wx.ITEM_NORMAL)
        self.file_menu.AppendItem(self.new_item)
        self.open_item = wx.MenuItem(self.file_menu, wx.NewId(), "Open", "Open", wx.ITEM_NORMAL)
        self.file_menu.AppendItem(self.open_item)
        self.save_item = wx.MenuItem(self.file_menu, wx.NewId(), "Save", "Save", wx.ITEM_NORMAL)
        self.file_menu.AppendItem(self.save_item)
        self.save_as_item = wx.MenuItem(self.file_menu, wx.NewId(), "Save As", "Save As", wx.ITEM_NORMAL)
        self.file_menu.AppendItem(self.save_as_item)
        self.close_item = wx.MenuItem(self.file_menu, wx.NewId(), "Close", "Close", wx.ITEM_NORMAL)
        self.file_menu.AppendItem(self.close_item)
        self.frame_1_menubar.Append(self.file_menu, "File")
        self.help_item = wx.Menu()
        self.frame_1_menubar.Append(self.help_item, "Help")
        self.SetMenuBar(self.frame_1_menubar)
        # Menu Bar end
        self.frame_1_statusbar = self.CreateStatusBar(1, 0)
        self.button_1 = wx.Button(self, -1, "Compile")
        self.label_4 = wx.StaticText(self, -1, "Specifications:")
        self.text_ctrl_1 = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE)
        self.notebook_1 = wx.Notebook(self, -1, style=0)
        self.notebook_1_pane_1 = wx.Panel(self.notebook_1, -1)
        self.text_ctrl_2 = wx.TextCtrl(self.notebook_1_pane_1, -1, "", style=wx.TE_MULTILINE | wx.TE_READONLY)
        self.notebook_1_pane_2 = wx.Panel(self.notebook_1, -1)
        self.text_ctrl_3 = wx.TextCtrl(self.notebook_1_pane_2, -1, "", style=wx.TE_MULTILINE | wx.TE_READONLY)
        self.static_line_1 = wx.StaticLine(self, -1, style=wx.LI_VERTICAL)
        self.radio_box_1 = wx.RadioBox(self, -1, "Model", choices=["Set", "Bag"], majorDimension=2, style=wx.RA_SPECIFY_COLS)
        self.label_5 = wx.StaticText(self, -1, "Max No. of Occurence:")
        self.text_ctrl_max = wx.TextCtrl(self, -1, "")
        self.label_1 = wx.StaticText(self, -1, "Operation:")
        self.combo_box_1 = wx.ComboBox(self, -1, choices=["size", "listProducts", "refines", "listCommonality", "isSubFamily", "isEqual"], style=wx.CB_DROPDOWN)
        self.label_2 = wx.StaticText(self, -1, "Parameters:")
        self.text_ctrl_4 = wx.TextCtrl(self, -1, "")
        self.button_2 = wx.Button(self, -1, "Add Query")
        self.text_ctrl_5 = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE | wx.TE_READONLY)
        self.button_3 = wx.Button(self, -1, "Run")
        self.label_3 = wx.StaticText(self, -1, "Aspect:")
        self.text_ctrl_6 = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE)
        self.button_4 = wx.Button(self, -1, "Weave")
        self.button_5 = wx.Button(self, -1, "Verify")
        self.button_refresh = wx.Button(self, -1, "Refresh")
	
	#Get the current directory path
	self.parent_dir = os.path.dirname(os.getcwd())
	#Set file paths
	global register_file
	register_file = os.path.join(self.parent_dir, "specs/register.reg")
	global basic_file
	basic_file = os.path.join(self.parent_dir,"working_dir/basic.h")
	global family_file 
	family_file = os.path.join(self.parent_dir,"working_dir/family.h")
	global cons_file
	cons_file = os.path.join(self.parent_dir,"working_dir/constraints.h")
	global queries_txt
	queries_txt = os.path.join(self.parent_dir,"interface/queries.txt")
	global queries_file
	queries_file = os.path.join(self.parent_dir,"working_dir/queries.h")
	global results_file
	results_file = os.path.join(self.parent_dir,"interface/results.txt")
	global basic_parse
	basic_parse = os.path.join(self.parent_dir,"interface/outputd.txt")
	global family_parse
	family_parse = os.path.join(self.parent_dir,"interface/outputf.txt")
	global con_parse
	con_parse = os.path.join(self.parent_dir,"interface/outputc.txt")
	global cond_parse
	cond_parse = os.path.join(self.parent_dir,"interface/outputi.txt")
	global code_genrated
	code_genrated = os.path.join(self.parent_dir,"interface/spec.txt")
	global compile_sh
	compile_sh = os.path.join(self.parent_dir,"interface/compile.sh")

        self.__set_properties()
        self.__do_layout()

        self.Bind(wx.EVT_MENU, self.new, self.new_item)
        self.Bind(wx.EVT_MENU, self.open, self.open_item)
        self.Bind(wx.EVT_MENU, self.save, self.save_item)
        self.Bind(wx.EVT_MENU, self.save_as, self.save_as_item)
        self.Bind(wx.EVT_MENU, self.close, self.close_item)
        self.Bind(wx.EVT_BUTTON, self.Compile, self.button_1)
        self.Bind(wx.EVT_RADIOBOX, self.RadioBox, self.radio_box_1)
        self.Bind(wx.EVT_BUTTON, self.AddQuery, self.button_2)
        self.Bind(wx.EVT_BUTTON, self.Run, self.button_3)
        self.Bind(wx.EVT_BUTTON, self.Weave, self.button_4)
        self.Bind(wx.EVT_BUTTON, self.Verify, self.button_5)
	self.Bind(wx.EVT_BUTTON, self.Refresh, self.button_refresh)
        # end wxGlade

    def __set_properties(self):
        # begin wxGlade: MyFrame.__set_properties
        self.SetTitle("JORY")
        self.frame_1_statusbar.SetStatusWidths([-1])
        # statusbar fields
        frame_1_statusbar_fields = [""]
        for i in range(len(frame_1_statusbar_fields)):
            self.frame_1_statusbar.SetStatusText(frame_1_statusbar_fields[i], i)
        self.text_ctrl_1.SetMinSize((600, 400))
        self.notebook_1.SetMinSize((227, 188))
        self.radio_box_1.SetSelection(0)
        self.text_ctrl_max.SetEditable(False)
        self.text_ctrl_max.SetBackgroundColour(wx.Colour(229, 229, 229))
        self.combo_box_1.SetMinSize((200, 29))
        self.combo_box_1.SetSelection(-1)
        self.combo_box_1.SetEditable(False)
        self.text_ctrl_4.SetMinSize((200, 27))
        self.text_ctrl_5.SetMinSize((200, 130))
        self.text_ctrl_6.SetMinSize((200, 130))
        self.text_ctrl_3.SetForegroundColour(wx.Colour(0, 0, 255))
        # end wxGlade

    def __do_layout(self):
        # begin wxGlade: MyFrame.__do_layout
        sizer_1 = wx.BoxSizer(wx.VERTICAL)
        sizer_2 = wx.FlexGridSizer(1, 3, 0, 0)
        sizer_6 = wx.FlexGridSizer(3, 1, 0, 0)
        grid_sizer_2 = wx.FlexGridSizer(3, 2, 0, 0)
        grid_sizer_4 = wx.FlexGridSizer(1, 2, 0, 0)
        grid_sizer_1 = wx.FlexGridSizer(6, 2, 0, 0)
        grid_sizer_5 = wx.FlexGridSizer(3, 2, 0, 0)
        sizer_3 = wx.FlexGridSizer(5, 1, 0, 0)
        sizer_5 = wx.BoxSizer(wx.HORIZONTAL)
        sizer_4 = wx.BoxSizer(wx.HORIZONTAL)
        grid_sizer_3 = wx.FlexGridSizer(2, 2, 0, 0)
        sizer_3.Add(grid_sizer_3, 1, 0, 0)
        sizer_3.Add(self.button_1, 0, 0, 0)
        sizer_3.Add(self.label_4, 0, 0, 0)
        sizer_3.Add(self.text_ctrl_1, 1, wx.EXPAND, 0)
        sizer_4.Add(self.text_ctrl_2, 1, wx.EXPAND, 0)
        self.notebook_1_pane_1.SetSizer(sizer_4)
        sizer_5.Add(self.text_ctrl_3, 1, wx.EXPAND, 0)
        self.notebook_1_pane_2.SetSizer(sizer_5)
        self.notebook_1.AddPage(self.notebook_1_pane_1, "Messages")
        self.notebook_1.AddPage(self.notebook_1_pane_2, "Output")
        sizer_3.Add(self.notebook_1, 1, wx.EXPAND, 0)
        sizer_2.Add(sizer_3, 1, 0, 0)
        sizer_2.Add(self.static_line_1, 0, wx.ALL | wx.EXPAND, 3)
        grid_sizer_5.Add(self.radio_box_1, 0, 0, 0)
        grid_sizer_5.Add((80, 20), 0, 0, 0)
        grid_sizer_5.Add(self.label_5, 0, 0, 0)
        grid_sizer_5.Add(self.text_ctrl_max, 0, 0, 0)
        sizer_6.Add(grid_sizer_5, 1, wx.EXPAND, 0)
        grid_sizer_1.Add(self.label_1, 0, wx.RIGHT, 0)
        grid_sizer_1.Add(self.combo_box_1, 0, 0, 0)
        grid_sizer_1.Add(self.label_2, 0, wx.RIGHT, 0)
        grid_sizer_1.Add(self.text_ctrl_4, 0, 0, 0)
        grid_sizer_1.Add((80, 20), 0, 0, 0)
        grid_sizer_1.Add(self.button_2, 0, 0, 0)
        grid_sizer_1.Add((80, 20), 0, 0, 0)
        grid_sizer_1.Add(self.text_ctrl_5, 0, wx.EXPAND, 0)
        grid_sizer_1.Add((80, 20), 0, 0, 0)
        grid_sizer_1.Add(self.button_3, 0, 0, 0)
        sizer_6.Add(grid_sizer_1, 1, wx.TOP | wx.BOTTOM | wx.EXPAND, 10)
        grid_sizer_2.Add(self.label_3, 0, 0, 0)
        grid_sizer_2.Add(self.text_ctrl_6, 0, wx.EXPAND, 0)
        grid_sizer_2.Add((80, 20), 0, 0, 0)
        grid_sizer_4.Add(self.button_4, 0, 0, 0)
        grid_sizer_4.Add(self.button_5, 0, 0, 0)
        grid_sizer_2.Add(grid_sizer_4, 1, wx.EXPAND, 0)
        grid_sizer_2.Add(self.button_refresh, 0, 0, 0)
        sizer_6.Add(grid_sizer_2, 1, wx.EXPAND, 0)
        sizer_2.Add(sizer_6, 1, wx.ALL | wx.EXPAND, 2)
        sizer_1.Add(sizer_2, 1, wx.EXPAND, 3)
        self.SetSizer(sizer_1)
        sizer_1.Fit(self)
        self.Layout()
        # end wxGlade
    #This method handles the event of menu bar element new 
    def new(self, event):  # wxGlade: MyFrame.<event_handler>
        self.file_path = ""
	self.text_ctrl_1.Clear()
        #event.Skip()

    #This method handles the event of menu bar element open
    def open(self, event):  # wxGlade: MyFrame.<event_handler>
        dialog = wx.FileDialog ( None,defaultDir=self.parent_dir,  style = wx.OPEN)
        if dialog.ShowModal() == wx.ID_OK:
           self.file_path = dialog.GetPath()
           #self.text_spec.SetValue(file_path)
           self.text_ctrl_1.LoadFile(self.file_path)
	   self.text_ctrl_1.SetModified(False)
	dialog.Destroy()
        #event.Skip()

    #This method handles the event of menu bar element save
    def save(self, event):  # wxGlade: MyFrame.<event_handler>
        if self.file_path != "":
		if self.text_ctrl_1.IsModified():
			self.text_ctrl_1.SaveFile(self.file_path)
	else:
		self.save_as(event)
        #event.Skip()

    #This method handles the event of menu bar element save as
    def save_as(self, event):  # wxGlade: MyFrame.<event_handler>
        dlg = wx.FileDialog(self, "Choose a file","" ,"", "*.*", \
                wx.SAVE | wx.OVERWRITE_PROMPT)
        if dlg.ShowModal() == wx.ID_OK:
	    self.file_path = dlg.GetPath()
            self.filename=dlg.GetFilename()
            self.dirname=dlg.GetDirectory()
            filehandle=open(os.path.join(self.dirname, self.filename),'w')
            filehandle.write(self.text_ctrl_1.GetValue())
            filehandle.close()
        dlg.Destroy()
        #event.Skip()
    #This method handles the event of menu bar element close
    def close(self, event):  # wxGlade: MyFrame.<event_handler>
        self.Close(True)
        #event.Skip()

    #This method handles the event of button compile
    def Compile(self, event):  # wxGlade: MyFrame.<event_handler>
        if self.text_ctrl_1.IsEmpty(): #if the editor is empty show a message
		dlg = wx.MessageDialog(None, "No specification to be compiled", "caption" , wx.OK | wx.ICON_INFORMATION)
        	dlg.ShowModal()
	else: #if editor is not empty do the following
		self.save(event)	#save the changes to the file
		if self.file_path != "":
			compiler = Compiler() #create an object of Compiler class

			compiler.prepareClean() #prepare clean
        		compiler.cleanTemp() #clean

			
			compiler.Parse(self.file_path) #call the parser on the specification

			f = open("errors.txt", 'r') #open the file that contains parsing errors
			self.text_ctrl_2.SetValue(f.read()) #show it on the tab
			self.text_ctrl_2.SetInsertionPointEnd()
			self.text_ctrl_2.WriteText("Compilation Completed\n")
			compiler.CodeGenerate(str(basic_parse),str(family_parse), str(con_parse), str(cond_parse) ,str(code_genrated), str(cons_file)) #call code generator

			model=self.radio_box_1.GetSelection() #get the model, 1 bag model 0 set model
        		bits = self.text_ctrl_max.GetValue() #get the max number of occurence for the bag model
        		compiler.processSpecFile(str(code_genrated)) #pocess the generated PFA code
        		#term evaluation based on model selection
        		if model == 1:
           			compiler.processEval(model, bits)
        		else:
           			compiler.processEval(model, 0)
		print "DONE COMPILE"
		self.notebook_1.ChangeSelection(0)
        #event.Skip()

    #This method handles the event of change the model selection
    def RadioBox(self, event):  # wxGlade: MyFrame.<event_handler>
	model=self.radio_box_1.GetSelection()
	if model == 1:
		self.text_ctrl_max.SetEditable(True)
		self.text_ctrl_max.SetBackgroundColour(wx.Colour(255, 255, 255))
	else:
			self.text_ctrl_max.SetEditable(False)
			self.text_ctrl_max.SetBackgroundColour(wx.Colour(229, 229, 229))
        event.Skip()

    #This method handles the event of add query button
    def AddQuery(self, event):  # wxGlade: MyFrame.<event_handler>
        self.text_ctrl_5.write(str(self.combo_box_1.GetValue()) +"(" + str(self.text_ctrl_4.GetValue()) + ")\n")
        event.Skip()
    #This method handles the event of Run button
    # prepare queries, compile BDD, then execute them and show the results
    def Run(self, event):  # wxGlade: MyFrame.<event_handler>
        executer = Executer()
        executer.removeQueriesFile()
        executer.prepareQueriesFile(queries_txt, self.text_ctrl_5.GetValue()) 
        executer.processQueriesFile(queries_txt, queries_file)
        executer.prepareIncludeFile()
        executer.compileBDD()
        self.text_ctrl_3.SetValue(executer.executeBdd(results_file))
        self.notebook_1.ChangeSelection(1)
        #event.Skip()

    def Weave(self, event):  # wxGlade: MyFrame.<event_handler>
        print "Event handler `Weave' not implemented!"
        event.Skip()

    def Verify(self, event):  # wxGlade: MyFrame.<event_handler>
        print "Event handler `Verify' not implemented!"
        event.Skip()

    #This method handles the event of Refresh button
    def Refresh(self, event):  # wxGlade: MyFrame.<event_handler>
        self.text_ctrl_max.Clear()
	self.text_ctrl_4.Clear()
	self.text_ctrl_5.Clear()
	self.text_ctrl_6.Clear()
	self.text_ctrl_2.Clear()
	self.text_ctrl_3.Clear()
	self.combo_box_1.SetSelection(-1)
	self.radio_box_1.SetSelection(0)
        #event.Skip()

# end of class MyFrame

#start of compiler class
class Compiler:
  
    #This method calls the parser
    def Parse(self, infile):
	e = subprocess.call(["./../parser/pfal " + infile], shell=True)
	
    #This method calls code generator
    def CodeGenerate(self, bffile, fmfile, confile, condfile, spfile, qfile):
	p = subprocess.call(["../code_generator/CodeGen " + bffile + " " + fmfile + " " + confile + " " + condfile + " " + spfile + " " + qfile], shell=True)

    #This method prepares clean.sh
    def prepareClean(self): 
         filename = "./clean.sh"
         file = open(filename, 'w')         
         file.write("cd ./../working_dir/"+"\n")
         file.write("rm *" + "\n")
         file.write("rm " + str(register_file) + "\n")
         file.write("rm " + str(basic_file) + "\n")
         file.write("rm " + str(family_file) + "\n")
	 file.write("rm " + str(cons_file) + "\n")
         file.write("rm " + str(queries_file) + "\n")
         file.write("rm " + str(results_file) + "\n") 
	 file.write("rm " + str(code_genrated) + "\n")                           
         file.close()

    #This method exucutes clean.sh
    def cleanTemp(self):	
	 p = subprocess.call(["./clean.sh"], shell=True)

    #This method calls processSpec 
    def processSpecFile(self,filename):	
        p = subprocess.call(["../haskell/ProcessSpec " + filename + " " + str(register_file) ], shell=True)

    #This method calls processEval
    def processEval(self,model, bits):
        m = subprocess.call(["../haskell/ProcessEval " + str(model) + " " + str(self.numberOfBits(bits,model)) + " " + str(register_file)  + " " + str(basic_file) + " " + str(family_file) + " " + str(queries_file) ], shell=True) # this has to pick from the interface the model 0 for set, 1 for bag.

    #This method sets the number of bits
    def numberOfBits(self,number, model):
        if (int(model) == 0):
           bits = 0
        else:
           bits = 1
        theNumber = int(number)
        while (2**bits) <= theNumber:
           bits = bits + 1
        return bits
    
#end of compiler class

#start of executer class
class Executer:
    #This method removes old query file
    def removeQueriesFile(self):
	k = subprocess.call(["rm " + str(queries_file)], shell=True)

    #This method prepares query file	
    def prepareQueriesFile(self,filename, queries):
	qFile = open(filename,'w')
	qFile.write(queries)
	qFile.close

    #This method calls ProcessQuery 		
    def processQueriesFile(self,filename, queries):
        p = subprocess.call(["../code_generator/ProcessQuery " + filename + " " + queries ], shell=True)

    #This method prepares Include file    
    def prepareIncludeFile(self): 
	filename = "./../working_dir/includeFiles.h"
 	file = open(filename, 'w')
	file.write("#include \"./../working_dir/names.h\"" + "\n")          
	file.write("#include \"" + str(basic_file) + "\"\n")
	file.write("#include \"" + str(family_file) + "\"\n")
	file.write("#include \"" + str(cons_file) + "\"\n")
	file.write("#include \"" + str(queries_file) + "\"\n")          
	file.close()

    #This method compiles BDD by calling compile.sh     
    def compileBDD(self):
	p = subprocess.call([str (compile_sh)], shell=True)

    #This method executes BDD file and show the result
    def executeBdd(self,filename):
	e = subprocess.call(["../bdd/main > " + filename], shell=True)
	f = open(filename, 'r')
	fileRead = f.read(-1)
	f.close()
	return fileRead    
#end of executer class

if __name__ == "__main__":
    app = wx.PySimpleApp(0)
    wx.InitAllImageHandlers()
    frame_1 = MyFrame(None, -1, "")
    app.SetTopWindow(frame_1)
    frame_1.Show()
    app.MainLoop()
