/*=========================================================================

  Copyright (c) Kitware, Inc.
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/VolViewCopyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "XML/vtkXMLKWVolumeWidgetReader.h"

#include "vtk3DCursorAnnotation.h"
#include "vtkBoundingBoxAnnotation.h"
#include "vtkCollection.h"
#include "vtkImageData.h"
#include "vtkKWOrientationWidget.h"
#include "vtkKWScalarBarWidget.h"
#include "vtkKWScaleBarWidget.h"
#include "vtkKWVolumeWidget.h"
#include "vtkLight.h"
#include "vtkLightCollection.h"
#include "vtkObjectFactory.h"
#include "vtkPiecewiseFunction.h"
#include "vtkProperty.h"
#include "vtkRenderer.h"
#include "vtkImplicitPlaneWidget.h"
#include "vtkXMLDataElement.h"

#include "XML/vtkXML3DCursorAnnotationReader.h"
#include "XML/vtkXMLBoundingBoxAnnotationReader.h"
#include "XML/vtkXMLImplicitPlaneWidgetReader.h"
#include "XML/vtkXMLKWOrientationWidgetReader.h"
#include "XML/vtkXMLKWScaleBarWidgetReader.h"
#include "XML/vtkXMLKWVolumeWidgetWriter.h"
#include "XML/vtkXMLLightReader.h"
#include "XML/vtkXMLPiecewiseFunctionReader.h"
#include "XML/vtkXMLScalarBarWidgetReader.h"

vtkStandardNewMacro(vtkXMLKWVolumeWidgetReader);
vtkCxxRevisionMacro(vtkXMLKWVolumeWidgetReader, "$Revision: 1.43 $");

//----------------------------------------------------------------------------
const char* vtkXMLKWVolumeWidgetReader::GetRootElementName()
{
  return "KWVolumeWidget";
}

//----------------------------------------------------------------------------
int vtkXMLKWVolumeWidgetReader::Parse(vtkXMLDataElement *elem)
{
  if (!this->Superclass::Parse(elem))
    {
    return 0;
    }

  vtkKWVolumeWidget *obj = vtkKWVolumeWidget::SafeDownCast(this->Object);
  if (!obj)
    {
    vtkWarningMacro(<< "The KWVolumeWidget is not set!");
    return 0;
    }

  // Get attributes

  float fval;
  double dbuffer3[3], dbuffer6[6];
  int ival;

  if (elem->GetScalarAttribute("ProjectionType", ival))
    {
    obj->SetProjectionType(ival);
    }
    
  if (elem->GetScalarAttribute("PerspectiveViewAngle", fval))
    {
    obj->SetPerspectiveViewAngle(fval);
    }
    
  if (elem->GetScalarAttribute("BlendMode", ival))
    {
    obj->SetBlendMode(ival);
    }
    
  if (elem->GetScalarAttribute("ZSampling", ival))
    {
    obj->SetZSampling(ival);
    }

  // Get nested elements
  
  vtkXMLDataElement *nested_elem;
  
  // Cropping

  nested_elem = elem->FindNestedElementWithName(
    vtkXMLKWVolumeWidgetWriter::GetCroppingElementName());
  if (nested_elem)
    {
    if (nested_elem->GetScalarAttribute("Enabled", ival))
      {
      obj->SetCropping(ival);
      }
    if (nested_elem->GetVectorAttribute("RegionPlanes", 6, dbuffer6) == 6)
      {
      obj->SetCroppingPlanes(dbuffer6);
      }
    if (nested_elem->GetScalarAttribute("RegionFlags", ival))
      {
      obj->SetCroppingRegionFlags(ival);
      }
    }

  // Reformat

  nested_elem = elem->FindNestedElementWithName(
    vtkXMLKWVolumeWidgetWriter::GetReformatElementName());
  if (nested_elem)
    {
    if (nested_elem->GetScalarAttribute("Enabled", ival))
      {
      obj->SetReformat(ival);
      }
    if (nested_elem->GetScalarAttribute("Thickness", fval))
      {
      obj->SetReformatThickness(fval);
      }
    if (nested_elem->GetVectorAttribute("Normal", 3, dbuffer3) == 3)
      {
      obj->SetReformatNormal(dbuffer3);
      }
    if (nested_elem->GetVectorAttribute("Up", 3, dbuffer3) == 3)
      {
      obj->SetReformatUp(dbuffer3);
      }
    if (nested_elem->GetVectorAttribute("Location", 3, dbuffer3) == 3)
      {
      obj->SetReformatLocation(dbuffer3);
      }
    if (nested_elem->GetScalarAttribute("ManipulationStyle", ival))
      {
      obj->SetReformatManipulationStyle(ival);
      }
    if (nested_elem->GetScalarAttribute("BoxVisibility", ival))
      {
      obj->SetReformatBoxVisibility(ival);
      }
    }

  // Cursor annotation

  vtk3DCursorAnnotation *cursora = obj->GetCursor3DAnnotation();
  if (cursora)
    {
    vtkXML3DCursorAnnotationReader *xmlr = 
      vtkXML3DCursorAnnotationReader::New();
    xmlr->SetObject(cursora);
    if (xmlr->ParseInNestedElement(
          elem,
          vtkXMLKWVolumeWidgetWriter::GetCursor3DAnnotationElementName()))
      {
      obj->UpdateAccordingTo3DCursorAnnotation();
      }
    xmlr->Delete();
    }

  // Bounding box annotation

  vtkBoundingBoxAnnotation *bboxa = obj->GetBoundingBoxAnnotation();
  if (bboxa)
    {
    vtkXMLBoundingBoxAnnotationReader *xmlr = 
      vtkXMLBoundingBoxAnnotationReader::New();
    xmlr->SetObject(bboxa);
    if (xmlr->ParseInNestedElement(
          elem, 
          vtkXMLKWVolumeWidgetWriter::GetBoundingBoxAnnotationElementName()))
      {
      obj->SetBoundingBoxVisibility(bboxa->GetVisibility()); // force add prop
      }
    xmlr->Delete();
    }

  // Scale bar widget
  
  vtkKWScaleBarWidget *scalebarw = obj->GetScaleBarWidget();
  if (scalebarw)
    {
    vtkXMLKWScaleBarWidgetReader *xmlr = vtkXMLKWScaleBarWidgetReader::New();
    xmlr->SetObject(scalebarw);
    xmlr->ParseInNestedElement(
      elem, vtkXMLKWVolumeWidgetWriter::GetScaleBarWidgetElementName());
    xmlr->Delete();
    }

  // Orientation widget
  
  vtkKWOrientationWidget *orientw = obj->GetOrientationWidget();
  if (orientw)
    {
    vtkXMLKWOrientationWidgetReader *xmlr = 
      vtkXMLKWOrientationWidgetReader::New();
    xmlr->SetObject(orientw);
    xmlr->ParseInNestedElement(
      elem, vtkXMLKWVolumeWidgetWriter::GetOrientationWidgetElementName());
    xmlr->Delete();
    }

  // Scalar bar widget
  
  vtkKWScalarBarWidget *scalarbarw = obj->GetScalarBarWidget();
  if (scalarbarw)
    {
    nested_elem = elem->FindNestedElementWithName(
      vtkXMLKWVolumeWidgetWriter::GetScalarBarWidgetElementName());
    if (nested_elem)
      {
      if (nested_elem->GetScalarAttribute("Component", ival))
        {
        obj->SetScalarBarComponent(ival);
        }
      
      vtkXMLScalarBarWidgetReader *xmlr = vtkXMLScalarBarWidgetReader::New();
      xmlr->SetObject(scalarbarw);
      xmlr->ParseInElement(nested_elem);
      xmlr->Delete();
      }
    }

  // Plane widget

  vtkImplicitPlaneWidget *planew = obj->GetPlaneWidget();
  if (planew)
    {
    nested_elem = elem->FindNestedElementWithName(
      vtkXMLKWVolumeWidgetWriter::GetPlaneWidgetElementName());
    if (nested_elem)
      {
      vtkXMLImplicitPlaneWidgetReader *xmlr = 
        vtkXMLImplicitPlaneWidgetReader::New();
      xmlr->SetObject(planew);
      int res = xmlr->ParseInElement(nested_elem) ? 1 : 0;
      xmlr->Delete();
      if (res)
        {
        obj->UpdateProbe();
        }
      }
    }

  // Lights

  nested_elem = elem->FindNestedElementWithName(
    vtkXMLKWVolumeWidgetWriter::GetLightsElementName());
  if (nested_elem)
    {
    vtkXMLLightReader *xmlr = vtkXMLLightReader::New();

    int idx, nb=0, nb_nested_elems = nested_elem->GetNumberOfNestedElements();
    for (idx = 0; idx < nb_nested_elems; idx++)
      {
      vtkXMLDataElement *light_elem = nested_elem->GetNestedElement(idx);
      if (light_elem && 
          !strcmp(light_elem->GetName(), xmlr->GetRootElementName()))
        {
        vtkLight *light = vtkLight::SafeDownCast(
          obj->GetRenderer()->GetLights()->GetItemAsObject(nb));
        if (!light)
          {
          light = vtkLight::New();
          obj->GetRenderer()->GetLights()->AddItem(light);
          light->Delete();
          }
        xmlr->SetObject(light);
        xmlr->Parse(light_elem);
        nb++;
        }
      }
    xmlr->Delete();
    }

  return 1;
}


