import wx
import vtk
from common_functions import align_all_planes
from CLT_selection_Frame import *
import colorsys

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
        self.a_o_max = len(self.frame_parent.ListOfObjects)-1
        #indices of associated planes
        self.associated_objects = [self.a_o_max-3,self.a_o_max-2,self.a_o_max-1,\
                                   self.a_o_max+1,self.a_o_max+2,self.a_o_max+3]
        
        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


        #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)


        #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(140, 16), style=wx.SL_HORIZONTAL, value=0)
        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(140, 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)

        self.Upper_Value = wx.TextCtrl(id=-1, value=str(float(self.SliderMax.GetValue()/100)), name='W',
              parent=self, pos=wx.Point(200, 48), size=wx.Size(60, 20),
              style=0)
        self.Upper_Value.Bind(wx.EVT_TEXT, self.OnUpperValue, id=-1)
        

        self.Lower_Value = wx.TextCtrl(id=-1, value=str(float(self.SliderMin.GetValue()/100)), name='L',
              parent=self, pos=wx.Point(200, 69), size=wx.Size(60, 20),
              style=0)
        self.Lower_Value.Bind(wx.EVT_TEXT, self.OnLowerValue, id=-1)
        
        self.transp_Cor_text_label = wx.StaticText(id=-1, label='Transparency', name='Transp',
              parent=self, pos=wx.Point(20, 120), 
              style=0)

        self.transp_value_label = wx.TextCtrl(id=-1, name='TranspTx',
              parent=self, pos=wx.Point(200, 120), size=wx.Size(60, 20),
              style=wx.TE_RIGHT, value='0')
        self.transp_value_label.SetEditable(1)
        self.transp_value_label.Bind(wx.EVT_TEXT, self.OnManualTransp, id=-1)        

        self.SliderTransparency = wx.Slider(id=-1, maxValue=100,
              minValue = 0, name='TransparencySlider', parent=self, pos=wx.Point(90,
              120), size=wx.Size(100, 16), style=wx.SL_HORIZONTAL, value=0)
        self.SliderTransparency.Bind(wx.EVT_SLIDER, self.OnSliderTransparency,
              id=-1)

        self.annotations_box = wx.StaticBox(id=-1,
              label='', name='window_anno', parent=self,
              pos=wx.Point(12, 224), 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, 248), size=wx.Size(50, 13),
              style=0)

        self.source_text = wx.TextCtrl(id=-1, name='Source',
              parent=self, pos=wx.Point(70, 248), 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:%0.2f  Data min:%0.2f' %(self.curr_max,self.curr_min), name='MinMax',
              parent=self, pos=wx.Point(20, 279), 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(20, 152), 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, 148),
              size=wx.Size(108, 24), style=wx.BU_AUTODRAW)
        self.LookupTableSelector.Bind(wx.EVT_BUTTON, self.OnLookupTableSelector,
              id=-1)

        self.ScalarBarOnOffCheckBox = wx.CheckBox(id=-1,
              label='Show colour bar', name='ScalarBarOnOffCheckBox',
              parent=self, pos=wx.Point(20, 184),
              style=0)
        self.ScalarBarOnOffCheckBox.SetValue(True)
        self.ScalarBarOnOffCheckBox.Bind(wx.EVT_CHECKBOX, self.OnScalarBarOnOffCheckBox,
              id=-1)

        self.InterpolationOnOffCheckBox = wx.CheckBox(id=-1,
              label='Interpolate colours', name='InterpolationOnOffCheckBox',
              parent=self, pos=wx.Point(20, 209),
              style=0)
        self.InterpolationOnOffCheckBox.SetValue(True)
        self.InterpolationOnOffCheckBox.Bind(wx.EVT_CHECKBOX, self.OnInterpolationOnOffCheckBox,
              id=-1)


        self.UseBasePlaneLookupTableCheckBox = wx.CheckBox(id=-1,
              label='Use Base LUT', name='UseBaseLUTOnOffCheckBox',
              parent=self, pos=wx.Point(209, 209),
              style=0)
        self.UseBasePlaneLookupTableCheckBox.SetValue(False)
        self.UseBasePlaneLookupTableCheckBox.Bind(wx.EVT_CHECKBOX, self.OnUseBasePlaneLookupTableCheckBox,
              id=-1)

    def OnUseBasePlaneLookupTableCheckBox(self, event):
        if self.UseBasePlaneLookupTableCheckBox.GetValue() == True:
            for j in self.associated_objects:
                self.frame_parent.ListOfObjects[j].SetLookupTable(self.frame_parent.original_LU_table)
                self.frame_parent.widget.Render()


    def OnInterpolationOnOffCheckBox(self, event):
        if self.ScalarBarOnOffCheckBox.GetValue() == True:
            self.thevtkobject.TextureInterpolateOn()
            self.thevtkobject.SetResliceInterpolateToCubic()
        else:
            self.thevtkobject.TextureInterpolateOff()
            self.thevtkobject.SetResliceInterpolateToNearestNeighbour()

    def OnManualTransp(self, event):
        opacity = float(self.transp_value_label.GetValue())/100.0
        self.SliderTransparency.SetValue(float(self.transp_value_label.GetValue()))
        for j in self.associated_objects:
            self.frame_parent.ListOfObjects[j].GetTexturePlaneProperty().SetOpacity(1-opacity)
        self.frame_parent.widget.Render()
        event.Skip() 
        
    def OnSliderTransparency(self, event):
        opacity = self.SliderTransparency.GetValue()/100.0
        self.transp_value_label.SetValue(str(self.SliderTransparency.GetValue()))
        for j in self.associated_objects:
            self.frame_parent.ListOfObjects[j].GetTexturePlaneProperty().SetOpacity(1-opacity)
        self.frame_parent.widget.Render()
        event.Skip()
        
    def OnScalarBarOnOffCheckBox(self, event):
        if self.ScalarBarOnOffCheckBox.GetValue() == True:
            self.thevtkobject.myScalarBar.On()
        else:
            self.thevtkobject.myScalarBar.Off()


    def OnUpperValue(self, event):
        self.SliderMax.SetValue(int(float(self.Upper_Value.GetValue())*100))
        self.OnSliderMax(event, 1)
        
    def OnLowerValue(self, event):
        self.SliderMin.SetValue(int(float(self.Lower_Value.GetValue())*100))
        self.OnSliderMin(event, 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]
        #todo -fix
	try:
	    imageFile = './CLT_images/'+new_img
            image1 = wx.Image(imageFile, wx.BITMAP_TYPE_ANY).ConvertToBitmap()
            self.LookupTableSelector.SetBitmapLabel(image1)
	except:
	    pass

        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.SaturationRangeMin = self.frame_parent.tmp_selected_lookup_table[3]
        voldata.SaturationRangeMax = self.frame_parent.tmp_selected_lookup_table[4]
        voldata.ValueRangeMin = self.frame_parent.tmp_selected_lookup_table[5]
        voldata.ValueRangeMax = self.frame_parent.tmp_selected_lookup_table[6]
	
	print voldata.HueRangeMin, voldata.HueRangeMax, voldata.SaturationRangeMin, voldata.SaturationRangeMax, voldata.ValueRangeMin, voldata.ValueRangeMax

        #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.SaturationRangeMax)
        y.SetAlphaRange(voldata.AlphaRangeMin, voldata.AlphaRangeMax)
        y.SetTableRange(float(self.SliderMin.GetValue())/100, float(self.SliderMax.GetValue())/100)
        self.Upper_Value.SetValue(str(float(self.SliderMin.GetValue())/100))
        y.ForceBuild()
        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.ListOfObjects[self.a_o_max].myScalarBar.GetScalarBarActor().SetLookupTable(y)
            self.frame_parent.widget.Render()
            event.Skip()
        
        self.UseBasePlaneLookupTableCheckBox.SetValue(0)
        align_all_planes(self.frame_parent)
        event.Skip()
        
    
    def OnSliderMin(self, event, called_by_box = 0):
        #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
                
                if self.SliderMin.GetValue() > self.SliderMax.GetValue():
                    upper_val = float(self.SliderMin.GetValue())/100
                    lower_val = float(self.SliderMax.GetValue())/100
                else:
                    lower_val = float(self.SliderMin.GetValue())/100
                    upper_val = float(self.SliderMax.GetValue())/100                    
                         
                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(lower_val, upper_val)
                if called_by_box == 0:
                    self.Lower_Value.SetValue(str(float(self.SliderMin.GetValue())/100))
                y.Build()
                if lower_val<0 or upper_val<0:
                    y.SetTableValue(255, (0.0,0.0,0.0,0.0))
                else:
                    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.ListOfObjects[self.a_o_max].myScalarBar.GetScalarBarActor().SetLookupTable(y)
                    self.frame_parent.widget.Render()
                    event.Skip()
        
        align_all_planes(self.frame_parent)
        event.Skip()


    def OnSliderMax(self, event, called_by_box = 0):
        #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]

                    if self.SliderMin.GetValue() > self.SliderMax.GetValue():
                        upper_val = float(self.SliderMin.GetValue())/100
                        lower_val = float(self.SliderMax.GetValue())/100
                    else:
                        lower_val = float(self.SliderMin.GetValue())/100
                        upper_val = float(self.SliderMax.GetValue())/100                    
                             
                    y = vtk.vtkLookupTable()
                    y.SetNumberOfTableValues(256)
                    y.SetHueRange(voldata.HueRangeMin, voldata.HueRangeMax)
		    if upper_val > voldata.ValueRangeMax:
			y.SetValueRange(voldata.ValueRangeMin, float(self.SliderMax.GetValue()))
			print 'WARNING! - your max lookuptable range is outside the maximum values detected in the data file.'
                    else:
			y.SetValueRange(voldata.ValueRangeMin, voldata.ValueRangeMax)
		    y.SetSaturationRange(voldata.SaturationRangeMin, voldata.SaturationRangeMin)
                    y.SetAlphaRange(voldata.AlphaRangeMin, voldata.AlphaRangeMax)
                    y.SetTableRange(lower_val, upper_val)
                    if called_by_box == 0:
                        self.Upper_Value.SetValue(str(float(self.SliderMax.GetValue())/100))
                    y.Build()
                    if lower_val<0 or upper_val<0:
                        y.SetTableValue(255, (0.0,0.0,0.0,0.0))
                    else:
                        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:
			#todo fix
			try:
                            self.frame_parent.ListOfObjects[j].SetLookupTable(y)
                            self.frame_parent.ListOfObjects[self.a_o_max].myScalarBar.GetScalarBarActor().SetLookupTable(y)
			    self.frame_parent.widget.Render()
                            event.Skip()
			except:
			    pass
        align_all_planes(self.frame_parent)
        event.Skip()
         
