import wx
import os
import vtk
from CLT_selection_Frame import *


class PUMenu(wx.Menu):
    def __init__(self, parent, thevtkobject):
        wx.Menu.__init__(self)
        
        self.parent = parent
        self.thevtkobject = thevtkobject
        
        min = wx.MenuItem(self, wx.NewId(),'Show properties window')
        self.AppendItem(min)
        self.Bind(wx.EVT_MENU, self.OnShow, id=min.GetId())
        
    def OnShow(self, evt):
        self.thevtkobject.my_property_frame_instance.Show(True)



class PropertyPanel_BasePlaneWidgets(wx.Panel):
    def __init__(self, parent, frame_parent, thevtkobject):
        wx.Panel.__init__(self, parent, -1)

        self.frame_parent = frame_parent
        self.thevtkobject = thevtkobject
        
        self.curr_max = self.frame_parent.my_loaded_volumes[0][0].data_max
        self.curr_min = self.frame_parent.my_loaded_volumes[0][0].data_min
        self.data_source_path = self.frame_parent.my_loaded_volumes[0][0].data_source_path
        
        self.sliderLevel= wx.Slider(id=-1, maxValue=self.curr_max,
              minValue=0, name='slider1', parent=self, pos=wx.Point(36,
              72), size=wx.Size(180, 16), style=wx.SL_HORIZONTAL, value=50)
        self.sliderLevel.Bind(wx.EVT_SLIDER, self.OnSliderLevel,
              id=-1)


        self.sliderWindow = wx.Slider(id=-1, maxValue=self.curr_max,
              minValue = 0, name='slider2', parent=self, pos=wx.Point(36,
              48), size=wx.Size(180, 16), style=wx.SL_HORIZONTAL, value=50)
        self.sliderWindow.Bind(wx.EVT_SLIDER, self.OnSliderWindow,
              id=-1)

        self.window_WL = wx.StaticBox(id=-1,
              label='window width/level', name='window_WL', parent=self,
              pos=wx.Point(12, 24), size=wx.Size(265, 80), style=0)


        self.W = wx.StaticText(id=-1, label='W', name='W',
              parent=self, pos=wx.Point(20, 48), size=wx.Size(10, 13),
              style=0)


        self.L = wx.StaticText(id=-1, label='L', name='L',
              parent=self, pos=wx.Point(20, 69), size=wx.Size(8, 13),
              style=0)


        self.Window_Value = wx.StaticText(id=-1, label=str(float(self.sliderWindow.GetValue()/100)), name='Win',
              parent=self, pos=wx.Point(220, 48), size=wx.Size(30, 13),
              style=0)


        self.Level_Value = wx.StaticText(id=-1, label=str(float(self.sliderLevel.GetValue()/100)), name='Level',
              parent=self, pos=wx.Point(220, 69), size=wx.Size(30, 13),
              style=0)


        self.annotations_box = wx.StaticBox(id=-1,
              label='', name='window_anno', parent=self,
              pos=wx.Point(12, 174), size=wx.Size(265, 80), style=0)
        
        
        self.source_text_label = wx.StaticText(id=-1, label='Source:', name='SourceT',
              parent=self, pos=wx.Point(20, 198), size=wx.Size(50, 13),
              style=0)

        self.source_text = wx.TextCtrl(id=-1, name='Source',
              parent=self, pos=wx.Point(70, 198), size=wx.Size(200, 20),
              style=wx.TE_RIGHT, value='%s' %self.data_source_path)
        self.source_text.SetEditable(0)

        self.source_min_max_text = wx.StaticText(id=-1, label='Data max:%s  Data min:%s' %(str(self.curr_max),str(self.curr_min)), name='MinMax',
              parent=self, pos=wx.Point(20, 229), size=wx.Size(200, 13),
              style=0)
        
        
    def OnSliderLevel(self, event):
        for i in range(len(self.frame_parent.ListOfObjects)):
            if self.frame_parent.ListOfObjects[i].my_parents_label == self.thevtkobject.my_label:
                self.frame_parent.ListOfObjects[i].SetWindowLevel(float(self.sliderWindow.GetValue()),float(self.sliderLevel.GetValue()))
                self.frame_parent.widget.Render()
                self.Level_Value.SetLabel(str(float(self.sliderLevel.GetValue())))
                event.Skip()


    def OnSliderWindow(self, event):
        for i in range(len(self.frame_parent.ListOfObjects)):
            if self.frame_parent.ListOfObjects[i].my_parents_label == self.thevtkobject.my_label:
                self.frame_parent.ListOfObjects[i].SetWindowLevel(float(self.sliderWindow.GetValue()),float(self.sliderLevel.GetValue()))
                self.frame_parent.widget.Render()
                self.Window_Value.SetLabel(str(float(self.sliderWindow.GetValue())))
                event.Skip()


class PropertyPanel_OverlayPlaneWidgets(wx.Panel):
    def __init__(self, parent, frame_parent, thevtkobject):
        wx.Panel.__init__(self, parent, -1)

        #some constants to allow handling later
        self.frame_parent = frame_parent
        self.thevtkobject = thevtkobject

        #this is used to figure out which 'number' / index object we have just created
        a_o_max = len(self.frame_parent.ListOfObjects)-1
        #indices of associated planes
        self.associated_objects = [a_o_max-3,a_o_max-2,a_o_max-1]
        
        count = self.frame_parent.overlay_count + 2

        self.curr_max = self.frame_parent.my_loaded_volumes[count][0].data_max
        self.curr_min = self.frame_parent.my_loaded_volumes[count][0].data_min
        self.data_source_path = self.frame_parent.my_loaded_volumes[count][0].data_source_path


        #a slider that controls the low threshold
        self.SliderMin= wx.Slider(id=-1, maxValue=self.frame_parent.my_loaded_volumes[count][0].data_max*100,
              minValue=self.frame_parent.my_loaded_volumes[count][0].data_min*100, name='slider1', parent=self, pos=wx.Point(54,
              72), size=wx.Size(160, 16), style=wx.SL_HORIZONTAL, value=self.frame_parent.my_loaded_volumes[count][0].data_min*100)
        self.SliderMin.Bind(wx.EVT_SLIDER, self.OnSliderMin,
              id=-1)

        #a slider that controls the high threshold
        self.SliderMax = wx.Slider(id=-1, maxValue=self.frame_parent.my_loaded_volumes[count][0].data_max*100,
              minValue = self.frame_parent.my_loaded_volumes[count][0].data_min*100, name='slider2', parent=self, pos=wx.Point(54,
              48), size=wx.Size(160, 16), style=wx.SL_HORIZONTAL, value=self.frame_parent.my_loaded_volumes[count][0].data_max*100)
        self.SliderMax.Bind(wx.EVT_SLIDER, self.OnSliderMax,
              id=-1)

        #some labels and bounding boxes for visual effect
        self.window_WL = wx.StaticBox(id=-1,
              label='Intensity threshold', name='window_WL', parent=self,
              pos=wx.Point(12, 24), size=wx.Size(265, 80), style=0)

        self.Upper_label = wx.StaticText(id=-1, label='Upper', name='W',
              parent=self, pos=wx.Point(20, 48), size=wx.Size(30, 13),
              style=0)

        self.Lower_label = wx.StaticText(id=-1, label='Lower', name='L',
              parent=self, pos=wx.Point(20, 69), size=wx.Size(30, 13),
              style=0)

        self.Upper_Value = wx.StaticText(id=-1, label=str(float(self.SliderMax.GetValue()/100)), name='W',
              parent=self, pos=wx.Point(220, 48), size=wx.Size(30, 13),
              style=0)

        self.Lower_Value = wx.StaticText(id=-1, label=str(float(self.SliderMin.GetValue()/100)), name='L',
              parent=self, pos=wx.Point(220, 69), size=wx.Size(30, 13),
              style=0)
    

        self.annotations_box = wx.StaticBox(id=-1,
              label='', name='window_anno', parent=self,
              pos=wx.Point(12, 174), size=wx.Size(265, 80), style=0)

        self.source_text_label = wx.StaticText(id=-1, label='Source:', name='SourceT',
              parent=self, pos=wx.Point(20, 198), size=wx.Size(50, 13),
              style=0)

        self.source_text = wx.TextCtrl(id=-1, name='Source',
              parent=self, pos=wx.Point(70, 198), size=wx.Size(200, 20),
              style=wx.TE_RIGHT, value='%s' %self.data_source_path)
        self.source_text.SetEditable(0)

        self.source_min_max_text = wx.StaticText(id=-1, label='Data max:%s  Data min:%s' %(str(self.curr_max),str(self.curr_min)), name='MinMax',
              parent=self, pos=wx.Point(20, 229), size=wx.Size(200, 13),
              style=0)

        self.lookup_text = wx.StaticText(id=-1, label='Select a colour table', name='ColTxt',
              parent=self, pos=wx.Point(25, 136), size=wx.Size(150, 20),
              style=0)
        
        self.LookupTableSelector = wx.BitmapButton(bitmap=wx.Bitmap(u'./CLT_images/red_yel.bmp',
              wx.BITMAP_TYPE_BMP), id=-1,
              name='bitmapButton1', parent=self, pos=wx.Point(150, 132),
              size=wx.Size(108, 24), style=wx.BU_AUTODRAW)
        self.LookupTableSelector.Bind(wx.EVT_BUTTON, self.OnLookupTableSelector,
              id=-1)
    
    
    def OnLookupTableSelector(self, event):
        main_app_frame = self.frame_parent
        t = ColourLookupTableFrame(self, main_app_frame)
        new_img = self.frame_parent.tmp_selected_lookup_table[0]
        imageFile = './CLT_images/'+new_img
        image1 = wx.Image(imageFile, wx.BITMAP_TYPE_ANY).ConvertToBitmap()
        self.LookupTableSelector.SetBitmapLabel(image1)

        voldata = self.frame_parent.my_loaded_volumes[self.index_in_volume_list][0]

        voldata.HueRangeMin = self.frame_parent.tmp_selected_lookup_table[1]
        voldata.HueRangeMax = self.frame_parent.tmp_selected_lookup_table[2]
        voldata.ValueRangeMin = self.frame_parent.tmp_selected_lookup_table[5]
        voldata.ValueRangeMax = self.frame_parent.tmp_selected_lookup_table[6]
        voldata.SaturationRangeMin = self.frame_parent.tmp_selected_lookup_table[3]
        voldata.SaturationRangeMax = self.frame_parent.tmp_selected_lookup_table[4]


        #build a new lookuptable with the new range - but existing colours in the HSVA ramp
        y = vtk.vtkLookupTable()
        y.SetNumberOfTableValues(256)
        y.SetHueRange(voldata.HueRangeMin, voldata.HueRangeMax)
        y.SetValueRange(voldata.ValueRangeMin, voldata.ValueRangeMax)
        y.SetSaturationRange(voldata.SaturationRangeMin, voldata.SaturationRangeMin)
        y.SetAlphaRange(voldata.AlphaRangeMin, voldata.AlphaRangeMax)
        y.SetTableRange(float(self.SliderMin.GetValue()/100.0), float(self.SliderMax.GetValue()/100.0))
        self.Lower_Value.SetLabel(str(float(self.SliderMin.GetValue())/100.0))
        y.Build()
        y.SetTableValue(0, (0.0,0.0,0.0,0.0))
        
        #apply the new table for later referecnce - tag it to the volume
        self.frame_parent.my_loaded_volumes[self.index_in_volume_list][0].lookuptable = y
        
        # and now tag it to the planes ...   
        for j in self.associated_objects:
            self.frame_parent.ListOfObjects[j].SetLookupTable(y)
            self.frame_parent.widget.Render()
            event.Skip()
        
    
    def OnSliderMin(self, event):
        #scan the loaded volumes and check if the data there = the data associated with the object
        # we are currently manipulating 
        for i in range(len(self.frame_parent.my_loaded_volumes)):
            if i == 2:
                pass #skip the reference volume - always index 2 in the my_loaded_volumes list
            else:
                voldata = self.frame_parent.my_loaded_volumes[self.index_in_volume_list][0]
                #build a new lookuptable with the new range - but existing colours in the HSVA ramp
                                
                y = vtk.vtkLookupTable()
                y.SetNumberOfTableValues(256)
                y.SetHueRange(voldata.HueRangeMin, voldata.HueRangeMax)
                y.SetValueRange(voldata.ValueRangeMin, voldata.ValueRangeMax)
                y.SetSaturationRange(voldata.SaturationRangeMin, voldata.SaturationRangeMin)
                y.SetAlphaRange(voldata.AlphaRangeMin, voldata.AlphaRangeMax)
                y.SetTableRange(float(self.SliderMin.GetValue()/100.0), float(self.SliderMax.GetValue()/100.0))
                self.Lower_Value.SetLabel(str(float(self.SliderMin.GetValue())/100.0))
                y.Build()
                y.SetTableValue(0, (0.0,0.0,0.0,0.0))
                
                #apply the new table for later referecnce - tag it to the volume
                self.frame_parent.my_loaded_volumes[self.index_in_volume_list][0].lookuptable = y
                
                # and now tag it to the planes ...   
                for j in self.associated_objects:
                    self.frame_parent.ListOfObjects[j].SetLookupTable(y)
                    self.frame_parent.widget.Render()
                    event.Skip()


    def OnSliderMax(self, event):
        #scan the loaded volumes and check if the data there = the data associated with the object
        # we are currently manipulating 
        for i in range(len(self.frame_parent.my_loaded_volumes)):
            if i == 2:
                pass #skip the reference volume - always index 2 in the my_loaded_volumes list
            else:
                #if they match
                if self.frame_parent.my_loaded_volumes[i][0].volume_data.GetOutput() == self.thevtkobject.my_data_volume:
                    voldata = self.frame_parent.my_loaded_volumes[i][0]
                    #build a new lookuptable with the new range - but existing colours in the HSVA ramp
                    y = vtk.vtkLookupTable()
                    y.SetNumberOfTableValues(256)
                    y.SetHueRange(voldata.HueRangeMin, voldata.HueRangeMax)
                    y.SetValueRange(voldata.ValueRangeMin, voldata.ValueRangeMax)
                    y.SetSaturationRange(voldata.SaturationRangeMin, voldata.SaturationRangeMin)
                    y.SetAlphaRange(voldata.AlphaRangeMin, voldata.AlphaRangeMax)
                    y.SetTableRange(float(self.SliderMin.GetValue()/100.0), float(self.SliderMax.GetValue()/100.0))
                    self.Upper_Value.SetLabel(str(float(self.SliderMax.GetValue())/100.0))
                    y.Build()
                    y.SetTableValue(0, (0.0,0.0,0.0,0.0))

                    #apply the new table for later referecnce - tag it to the volume                        
                    self.frame_parent.my_loaded_volumes[i][0].lookuptable = y

                    # and now tag it to the planes ...   
                    for j in self.associated_objects:
                        self.frame_parent.ListOfObjects[j].SetLookupTable(y)
                        self.frame_parent.widget.Render()
                        event.Skip()
         
        
class MyPropertyFrame(wx.Frame):
    def __init__(self, frame_parent, thevtkobject, index_in_volume_list):
        label = thevtkobject.my_label
        wx.Frame.__init__(self, None, -1, 'Properties for '+label, size=(300, 300), style=wx.STAY_ON_TOP|wx.DEFAULT_FRAME_STYLE)
        #check which type of object we are creating a property panel for
        # and call the appropriate panel class
        
        #if we are dealing with the 'base' image ...
        if thevtkobject == frame_parent.ListOfObjects[3]:      
            panel = PropertyPanel_BasePlaneWidgets(self, frame_parent, thevtkobject)
        
        #else:
        elif thevtkobject.my_property_frame_type == 'PlaneWidgetProperties':
            panel = PropertyPanel_OverlayPlaneWidgets(self, frame_parent, thevtkobject)
            #label the frame with its corresponding data volume (so we can update later)
            panel.index_in_volume_list = index_in_volume_list
        else:
            pass
        
        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
        
        
    def OnCloseWindow(self, event):
        self.Show(False)
        
        