import vtk
from dv3dNifti2VtkImageData import *


def dv3dVolumeRender(frame_parent, preloaded_volume_data=None):
    #source_file = "E:/fin.nii.gz"
    if preloaded_volume_data==None:
        source_file = "./DV3D_essentials/MNI152_T1_1mm_brain.nii.gz"
        #source_file = "C:/DV3D_examples/Structural_MRI.nii.gz"

    else:
        source_file = preloaded_volume_data

    volume_data, data_max, data_min,       \
          data_bounds, x_slice_pos,          \
          y_slice_pos, z_slice_pos,               \
          data_s_row_x, data_s_row_y,   \
          data_s_row_z, data_spacing,   \
          = nifti2vtkImageData(source_file)
    
    #vtkFixedPointVolumeRayCastMapper
    vCompFunc = vtk.vtkVolumeRayCastCompositeFunction()
    vCompFunc.SetCompositeMethodToClassifyFirst()
    
    #vCompFunc = vtk.vtkVolumeRayCastMIPFunction()
    
    vMapper = vtk.vtkFixedPointVolumeRayCastMapper()
    #vMapper.SetVolumeRayCastFunction(vCompFunc)
    #vMapper.SetBlendModeToMaximumIntensity()
    vMapper.SetInput(volume_data.GetOutput())
    
    ctf = vtk.vtkColorTransferFunction()
    ctf.SetColorSpaceToRGB()
    ctf.AddRGBPoint(1, 255/255.0, 200/255.0, 70/255.0)
    ctf.AddRGBPoint(501, 0.3, 0.3, 0.3)
    ctf.AddRGBPoint(10000, 1, 1, 1)
    
    pwf = vtk.vtkPiecewiseFunction()
    pwf.AddPoint(501,1.0)
    pwf.AddPoint(7000,1.0)
    pwf.ClampingOff()
    
    vProp = vtk.vtkVolumeProperty()
    vProp.SetColor(ctf)
    vProp.SetScalarOpacity(pwf)
    #vProp.ShadeOn()
    vProp.SetInterpolationTypeToLinear()
    vProp.SetDiffuse(0.7)
    vProp.SetAmbient(0.5)
    vProp.SetSpecular(1.0)
    vProp.SetSpecularPower(5)
    
    
    v = vtk.vtkVolume()
    v.SetMapper(vMapper)
    v.SetProperty(vProp)
    v.Update()
    
    #frame_parent.ren.AddViewProp(v)
    frame_parent.ren.Render()
    
    
    boxWidget = vtk.vtkBoxWidget()
    boxWidget.SetInteractor(frame_parent.widget)
    boxWidget.SetPlaceFactor(1.0)
    
    # Add the actors to the renderer, set the background and size
    frame_parent.ren.AddVolume(v)

    v.SetPosition(0.0,0.0,0.0)
    v.Update()
    
    # When interaction starts, the requested frame rate is increased.
    def StartInteraction(obj, event):
        frame_parent.widget.Render()
        frame_parent.widget.GetRenderWindow().SetDesiredUpdateRate(100)
    
    # When interaction ends, the requested frame rate is decreased to
    # normal levels. This causes a full resolution render to occur.
    def EndInteraction(obj, event):
        frame_parent.widget.Render()
        frame_parent.widget.GetRenderWindow().SetDesiredUpdateRate(0.001)

    
    # The implicit function vtkPlanes is used in conjunction with the
    # volume ray cast mapper to limit which portion of the volume is
    # volume rendered.
    planes = vtk.vtkPlanes()
    def ClipVolumeRender(obj, event):
        obj.GetPlanes(planes)
        vMapper.SetClippingPlanes(planes)
        frame_parent.widget.Render()

     
    
    # Place the interactor initially. The output of the reader is used to
    # place the box widget.
    #boxWidget.SetProp3D(v)
    boxWidget.PlaceWidget(v.GetBounds()[0],-v.GetBounds()[1],v.GetBounds()[2],v.GetBounds()[3],v.GetBounds()[4],v.GetBounds()[5])
    boxWidget.InsideOutOn()
    boxWidget.AddObserver("StartInteractionEvent", ClipVolumeRender)
    boxWidget.AddObserver("InteractionEvent", ClipVolumeRender)
    boxWidget.AddObserver("EndInteractionEvent", ClipVolumeRender)
    frame_parent.Boxwidget = boxWidget
    #boxWidget.On()
    
    outlineProperty = boxWidget.GetOutlineProperty()
    outlineProperty.SetRepresentationToWireframe()
    outlineProperty.SetAmbient(1.0)
    outlineProperty.SetAmbientColor(1, 1, 1)
    outlineProperty.SetLineWidth(1)
    
    selectedOutlineProperty = boxWidget.GetSelectedOutlineProperty()
    selectedOutlineProperty.SetRepresentationToWireframe()
    selectedOutlineProperty.SetAmbient(1.0)
    selectedOutlineProperty.SetAmbientColor(1, 0, 0)
    selectedOutlineProperty.SetLineWidth(1)
