#!/usr/bin/env python
import gobject
import os
import pygtk
pygtk.require('2.0')
import gtk
from export import Export
import Image
import threading
from my_exceptions import *
from  message import Message
from double_lin_reg import Double_Linear_Regression
from box_counting import Box_Counting,test_image
from config import TMP_REP
from File_mode import file_mode
from Method import Method
from Export_page import export_page

class Xfrac_dim:
    "Graphic interface for frac_dim"
    
    def delete(self, widget, event=None):
        gtk.main_quit()
        return False 

    def switch(self,widget):
        widget.set_label(self.Etat)
        if self.Etat=="File mode":
            self.File_mode.hide()
            self.Directory_mode.show()
            self.Etat="Directory mode"
        else:
            self.Directory_mode.hide()
            self.File_mode.show()
            self.Etat="File mode"
        widget.show()

        
    def __init__(self):
        
        self.Window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.Window.connect("delete_event", self.delete)
        self.Window.set_border_width(10)
        Main_box=gtk.VBox(homogeneous=False , spacing=10)
        

        # Creation of the notebook
        self.Notebook = gtk.Notebook()
        self.Notebook.set_tab_pos(gtk.POS_TOP)
        Main_box.pack_start(self.Notebook,True,True,0)
        self.Notebook.show()
        self.show_tabs = True
        self.show_border = True

        #first frame of the notebook
        self.File_mode=file_mode(self.Notebook)
        self.Directory_mode=directory_mode(self.Notebook,self.Window)

        #File Mode by default
        #self.File_mode.show()
        #self.Etat="File mode"

        #Directorty mode by default
        self.Directory_mode.show()
        self.Etat="Directory mode"
        
        # Create the close button
        Bottom_box = gtk.HBox(homogeneous=False , spacing=10)

        if self.Etat == "Directory mode":
            self.Switch_button =gtk.Button("File mode")
        else:
            self.Switch_button =gtk.Button("Directory mode")
            
        self.Switch_button.connect("clicked",self.switch)
        self.Switch_button.show()
        Bottom_box.pack_start(self.Switch_button,False ,False ,0)

        Quit_button = gtk.Button("close",gtk.STOCK_QUIT)
        Quit_button.connect("clicked", self.delete)
        Quit_button.show()
        Bottom_box.pack_start(Quit_button,False ,False ,0)
        Bottom_box.show()

        Main_box.pack_start(Bottom_box,False ,False ,0)
        

        Main_box.show()
        self.Window.add(Main_box)

        self.Window.show()











class work_data(threading.Thread):

    #variable de classe
    datalock=threading.Lock()
    data={}


    def __init__(self):
        threading.Thread.__init__(self)
        self.setDaemon(True)
      

    def add_image(self,image,method,precision=None):
        work_data.datalock.acquire()
        work_data.data[image]={'status':'Ready','method':method,'precision':precision}
        work_data.datalock.release()

    def remove(self,image):
        work_data.datalock.acquire()
        del work_data.data[image]
        work_data.datalock.release()

        
    def set_method(self,image,method,precision=None):
        work_data.datalock.acquire()
        if work_data.data[image]['status']=='Ready':
            work_data.data[image]['method']=method
            work_data.data[image]['precision']=precision
        work_data.datalock.release()
        

    def select_images(self,images):
        self.selected=images

   
    def get_selected_images(self):
        return self.selected


    def run(self):
        images=self.get_selected_images()

        work_data.datalock.acquire()

        for image in images:
            work_data.data[image]["status"]="IN QUEUE"
        work_data.datalock.release()


        for image in images:

            work_data.datalock.acquire()
            method=work_data.data[image]['method']
            precision=work_data.data[image]['precision']

            work_data.data[image]["status"]="RUNNING"
            work_data.data[image]["bc"]=Box_Counting()
            work_data.data[image]["bc"].set_image(image)

            self.data[image]["bc"].set_method(method)
            if method== "exponential":
                if precision != None:
                    self.data[image]["bc"].set_precision(precision)
                else:
                    raise "Precision needed for exponential method"

            
            work_data.datalock.release()
            self.compute(image)
    

    def compute(self,image):
        work_data.datalock.acquire()
        work_data.data[image]["bc"].compute_with_lock(work_data.datalock)
        plot=self.data[image]["bc"].plot()
        work_data.datalock.release()
        dlr=Double_Linear_Regression(plot)
        work_data.datalock.acquire()
        work_data.data[image]["DLR"]=dlr
        work_data.data[image]["status"]="DONE"          
        work_data.datalock.release()

    def export_secure(self,images,filename):
        dialog = gtk.Dialog(title="Confirmation", parent=None, flags=0, buttons=None)
        def export(widget):
            self.export(images,filename)
            dialog.destroy()

        def cancel(widget):
            dialog.destroy()
            
        if(os.path.exists(filename)):
            
            #########
            button_OK=gtk.Button("Browse",gtk.STOCK_OK)
            button_CANCEL=gtk.Button("Browse",gtk.STOCK_CANCEL)
            
            button_OK.connect("clicked", export)
            button_CANCEL.connect("clicked",cancel)

            button_OK.show()
            button_CANCEL.show()


            dialog.action_area.pack_start(button_OK, True, True, 0)
            dialog.action_area.pack_start(button_CANCEL, True, True, 0)


            label = gtk.Label("The file "+ filename+" already exists. Do you really want to overwrite this file?")
            dialog.vbox.pack_start(label, True, True, 0)
            label.show()

            dialog.show()
        else:

            self.export(images,filename)



        
    def export(self,images,filename):
        fd=os.open(filename,os.O_CREAT + os.O_WRONLY + os.O_TRUNC)
        work_data.datalock.acquire()
        for image in images:
            if work_data.data[image]["status"]=="DONE":
                os.write(fd,image+";"+  str(- self.data[image]["DLR"].coefficient()[0][0]) +";"+str(- self.data[image]["DLR"].coefficient()[1][0] )+"\n")
        os.close(fd)
        work_data.datalock.release()


    def get_text_dim(self,image):
        work_data.datalock.acquire()
        if self.data[image]['status']!="DONE":
            work_data.datalock.release()
            raise "NOT_YET_CALCULATED"
        
            
        res =  - self.data[image]["DLR"].coefficient()[0][0]
        work_data.datalock.release()
        return res

    def get_struct_dim(self,image):
        work_data.datalock.acquire()
        if self.data[image]['status']!="DONE":
            work_data.datalock.release()
            raise "NOT_YET_CALCULATED"
        
        res = - self.data[image]["DLR"].coefficient()[1][0]
        work_data.datalock.release()
        return res
        

    def get_DLR(self,image):
        work_data.datalock.acquire()
        res = self.data[image]["DLR"]
        work_data.datalock.release()
        return res

    def get_status(self,image):
        work_data.datalock.acquire()
        res= self.data[image]['status']
        work_data.datalock.release()
        return res


    def get_method(self,image):
        work_data.datalock.acquire()
        method= self.data[image]['method']
        precision= self.data[image]['precision']
        work_data.datalock.release()
        return (method,precision)


    def list_images(self):
        work_data.datalock.acquire()
        res =self.data.keys()
        work_data.datalock.release()
        return res

    def get_bc(self,image):
        work_data.datalock.acquire()
        res = work_data.data[image]["bc"]
        work_data.datalock.release()
        return res
        

class directory_mode:
    "define the directory_mode"

    def __init__(self,Notebook,Window=None):
        self.Window=Window
        self.wdata_list=[]
        
        self.frame_name = "Directory mode" 
        self.Notebook=Notebook
        self.bc_frame = gtk.Frame(self.frame_name)
        self.bc_frame.set_border_width(10)
        self.bc_frame.set_size_request(700, 500)

        
        self.bc_box=gtk.HBox(homogeneous=False , spacing=10)

        #left part
        self.bc_left_box=gtk.VBox(homogeneous=False , spacing=10)

#        self.Directory_selection_box = gtk.HBox(homogeneous=False , spacing=10)
        
 #       self.Entry = gtk.Entry()
  #      self.Entry.set_max_length(70)
   #     self.Entry.connect("activate", self.load_rep)
    #    self.Entry.set_text("My directory")
     #   self.Entry.show()
      #  
       # self.Directory_selection_box.pack_start(self.Entry,True,True,10)

        #button_browse=gtk.Button("Browse",gtk.STOCK_FIND)
        #button_browse.connect("clicked",self.directory_selection)
        #button_browse.show()

       # self.Directory_selection_box.pack_start(button_browse,False ,False ,10)


       # self.Directory_selection_box.show()        
       # self.bc_left_box.pack_start(self.Directory_selection_box,False ,False ,10)

        self.fshow=files_show(self.Notebook)
        self.bc_left_box.pack_start(self.fshow.gtk_ref() ,True ,True ,10)###False false avant



        self.bc_left_box.show()
        self.bc_box.pack_start(self.bc_left_box,True,True,10)

        #right part 
        bc_right_box=gtk.VBox(homogeneous=False , spacing=3)

        self.Method=Method()

        bc_right_box.pack_start(self.Method.get_object(),False ,False ,3)

        vspace=0
        
        self.Button_setmethod=gtk.Button("Set method")
        #self.Button_setmethod.set_sensitive(False )
        self.Button_setmethod.connect("clicked",self.set_method)
        self.Button_setmethod.show()
        bc_right_box.pack_start(self.Button_setmethod,False ,False ,vspace)

        self.Button_remove=gtk.Button("Remove")
        #self.Button_remove.set_sensitive(False )
        self.Button_remove.connect("clicked",self.remove)
        self.Button_remove.show()
        bc_right_box.pack_start(self.Button_remove,False ,False ,vspace)
       
        self.Button_adddir=gtk.Button("Add dir")
        self.Button_adddir.connect("clicked",self.directory_selection)
        self.Button_adddir.show()
        bc_right_box.pack_start(self.Button_adddir,False ,False ,vspace)
        
        self.Button_addfile=gtk.Button("Add file")
        self.Button_addfile.connect("clicked",self.file_selection)
        self.Button_addfile.show()
        bc_right_box.pack_start(self.Button_addfile,False ,False ,vspace)
        
        self.Button_compute=gtk.Button("Compute",gtk.STOCK_EXECUTE)
        self.Button_compute.set_sensitive(False )
        self.Button_compute.connect("clicked",self.compute)
        self.Button_compute.show()
        bc_right_box.pack_start(self.Button_compute,False ,False ,vspace)

        self.Button_export=gtk.Button("Export")
        self.Button_export.connect("clicked",self.export)
        self.Button_export.show()
        bc_right_box.pack_start(self.Button_export,False ,False ,vspace)

        bc_right_box.show()

        self.bc_box.pack_start(bc_right_box,False ,False ,vspace)
        self.bc_box.show()
        self.bc_frame.add(self.bc_box)
        self.bc_frame.show()

    


    def load_rep(self,widget):
        self.Directory=widget.get_text()
        try:
            Files=os.listdir(self.Directory)
            self.Images=filter(test_image,Files)
            self.Button_compute.set_sensitive(True)        
        except OSError:
            print "You have to select a directory!"


       
    
        
    def directory_selection(self,widget,output=""):
        filew = gtk.FileSelection("Directory selection")
        filew.connect("destroy", lambda w: filew.destroy())
        filew.ok_button.connect("clicked", self.file_ok_sel,filew)
        filew.cancel_button.connect("clicked", lambda w: filew.destroy())
        filew.set_filename(output)
        filew.show()

    def file_selection(self,widget,output=""):
        dialog = gtk.Dialog("test",self.Window ,gtk.DIALOG_MODAL)
        dialog.set_border_width(2)
        dialog.set_size_request(200,100)
        dialog.set_position(gtk.WIN_POS_CENTER)

        label = gtk.Label("Hi from python")
        dialog.vbox.add(label)
        dialog.show_all()



        filew = gtk.FileSelection("File selection")
        filew.connect("destroy", lambda w: filew.destroy())
        filew.ok_button.connect("clicked", self.file_ok_sel,filew)
        filew.cancel_button.connect("clicked", lambda w: filew.destroy())
        filew.set_filename(output)
        filew.show()


    def file_ok_sel(self, widget,filew):
        self.Directory=(filew.get_filename())
        #self.Entry.set_text(self.Directory)
        wdata=work_data()
        try:
            Files=os.listdir(self.Directory)
            for i in filter(test_image,Files):
                (method,parameter)=self.Method.get_method()
                wdata.add_image(self.Directory +"/" +i,method,parameter)
                             
            self.Button_compute.set_sensitive(True)
            self.fshow.update()
        except OSError:
            print "You have to select a directory!"
        filew.destroy()


    def compute(self,widget):
        selected_images=self.fshow.get_selected()
        wdata=work_data()
        wdata.select_images(selected_images)
        self.wdata_list.append(wdata)
        wdata.start()        
        self.fshow.update()
        
    def set_method(self,widget):
        wdata=work_data()
        selected_images=self.fshow.get_selected()
        (method,parameter)=self.Method.get_method()
        for image in selected_images:
            wdata.set_method(image,method,parameter)
        self.fshow.update()

        
    def remove(self,widget):
        wdata=work_data()
        selected_images=self.fshow.get_selected()
        for image in selected_images:
            wdata.remove(image)
        self.fshow.update()

    def export(self,widget):
        self.file_export_name=""
        filew = gtk.FileSelection("File Export Selection")
        filew.connect("destroy", lambda w: filew.destroy())
        filew.ok_button.connect("clicked", self.file_export_ok_sel,filew)
        filew.cancel_button.connect("clicked", lambda w: filew.destroy())
        filew.set_filename("")
        filew.show()
       

    def file_export_ok_sel(self, widget,filew):
        self.file_export_name=(filew.get_filename())
        filew.destroy()
        wdata=work_data()
        selected_images=self.fshow.get_selected()
        wdata.export_secure(selected_images,self.file_export_name)

        


    def show(self):
        Label = gtk.Label(self.frame_name)
        Label.show()
        self.Notebook.insert_page(self.bc_frame, Label,0)
        self.Notebook.set_current_page(0)

    
    def hide(self):       
        self.Notebook.remove_page(0)






class files_show:
    """Define an object to print a list of file and parameter corresponding to this files"""


    def __init__(self, notebook):
        self.Notebook=notebook
        cell_data_funcs = (self.file_name, self.status,self.method,self.struct_dim, self.tex_dim)
        self.column_names=["File","Status","Method","Structural dimension","Textural dimension"]
 
        
        # create the TreeView
        self.treeview = gtk.TreeView()
        self.treeselection = self.treeview.get_selection()
        self.treeselection.set_mode(gtk.SELECTION_MULTIPLE)
 
        # create the TreeViewColumns to display the data
        self.tvcolumn = [None] * len(self.column_names)

        cell = gtk.CellRendererText()
        self.tvcolumn[0] = gtk.TreeViewColumn(self.column_names[0], cell)        
        self.tvcolumn[0].set_cell_data_func(cell, self.file_name)
        self.treeview.append_column(self.tvcolumn[0])
        for n in range(1, len(self.column_names)):
            cell = gtk.CellRendererText()
            self.tvcolumn[n] = gtk.TreeViewColumn(self.column_names[n], cell)
            if n == 1:
                cell.set_property('xalign', 1.0)
            self.tvcolumn[n].set_cell_data_func(cell, cell_data_funcs[n])
            self.treeview.append_column(self.tvcolumn[n])

        self.treeview.connect('row-activated', self.export_result)

        self.scrolledwindow = gtk.ScrolledWindow()
        self.scrolledwindow.set_border_width(10)
        self.scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)


        self.scrolledwindow.add(self.treeview)
        self.scrolledwindow.show()
        
 
    def export_result(self, treeview, path, column):
         model = treeview.get_model()
         iter = model.get_iter(path)
         image = model.get_value(iter, 0)
         print image
         wdata=work_data()
         ex=export_page(self.Notebook,image,wdata.get_bc(image),wdata.get_DLR(image).coefficient())
         return



    #def add_files(self,files):
    #    self.files=files
    #    listmodel = self.make_list()
    #    self.treeview.set_model(listmodel)
    #    self.treeview.show()

    def update(self):
        listmodel = self.make_list()
        self.treeview.set_model(listmodel)
        self.treeview.show()

       
    def make_list(self):
        listmodel = gtk.ListStore(object)
        images=work_data().list_images()
        for f in images:
            listmodel.append([f])
        return listmodel

    def get_selected(self):
        selected=[]
        (model, pathlist) = self.treeselection.get_selected_rows()
        for path in pathlist:
            iter = model.get_iter(path)
            selected.append(model.get_value(iter, 0))
        return selected

    def file_name(self, column, cell, model, iter):
        cell.set_property('text', model.get_value(iter, 0))
        return

    def status(self,column,cell,model,iter):
        image=model.get_value(iter, 0)
        status=work_data().get_status(image)
        cell.set_property('text', str(status))
        return
        
    
    def method(self,column,cell,model,iter):
        image=model.get_value(iter, 0)
        (method,precision)=work_data().get_method(image)

        if method=="exponential":
            cell.set_property('text', str(method)+"("+str(precision)+")")
        else:
            cell.set_property('text', str(method))
        return



    def tex_dim(self, column, cell, model, iter):
        try:
            image=model.get_value(iter, 0)
            texdim=work_data().get_text_dim(image)
            cell.set_property('text', str(texdim))
        except "NOT_YET_CALCULATED":
            cell.set_property('text', "")            
        return

    def struct_dim(self, column, cell, model, iter):
        try:
            image=model.get_value(iter, 0)
            structdim=work_data().get_struct_dim(image)
            cell.set_property('text', str(structdim))
        except "NOT_YET_CALCULATED":
            cell.set_property('text', "")            
        return





    def gtk_ref(self):
        return self.scrolledwindow















def main():
    gobject.threads_init()
    gtk.main()
    return 0

if __name__ == "__main__":
    Xfrac_dim()
    main()

