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

  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/vtkXMLKWVolumeWidgetWriter.h"

#include "vtk3DCursorAnnotation.h"
#include "vtkBoundingBoxAnnotation.h"
#include "vtkCollectionIterator.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 "vtkRenderer.h"
#include "vtkImplicitPlaneWidget.h"
#include "vtkXMLDataElement.h"

#include "XML/vtkXML3DCursorAnnotationWriter.h"
#include "XML/vtkXMLBoundingBoxAnnotationWriter.h"
#include "XML/vtkXMLImplicitPlaneWidgetWriter.h"
#include "XML/vtkXMLKWOrientationWidgetWriter.h"
#include "XML/vtkXMLKWScaleBarWidgetWriter.h"
#include "XML/vtkXMLLightWriter.h"
#include "XML/vtkXMLPiecewiseFunctionWriter.h"
#include "XML/vtkXMLScalarBarWidgetWriter.h"

vtkStandardNewMacro(vtkXMLKWVolumeWidgetWriter);
vtkCxxRevisionMacro(vtkXMLKWVolumeWidgetWriter, "$Revision: 1.34 $");

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

//----------------------------------------------------------------------------
const char* vtkXMLKWVolumeWidgetWriter::GetCroppingElementName()
{
  return "Cropping";
}

//----------------------------------------------------------------------------
const char* vtkXMLKWVolumeWidgetWriter::GetReformatElementName()
{
  return "Reformat";
}

//----------------------------------------------------------------------------
const char* vtkXMLKWVolumeWidgetWriter::GetCursor3DAnnotationElementName()
{
  return "Cursor3DAnnotation";
}

//----------------------------------------------------------------------------
const char* vtkXMLKWVolumeWidgetWriter::GetBoundingBoxAnnotationElementName()
{
  return "BoundingBoxAnnotation";
}

//----------------------------------------------------------------------------
const char* vtkXMLKWVolumeWidgetWriter::GetScaleBarWidgetElementName()
{
  return "ScaleBarWidget";
}

//----------------------------------------------------------------------------
const char* vtkXMLKWVolumeWidgetWriter::GetOrientationWidgetElementName()
{
  return "OrientationWidget";
}

//----------------------------------------------------------------------------
const char* vtkXMLKWVolumeWidgetWriter::GetScalarBarWidgetElementName()
{
  return "ScalarBarWidget";
}

//----------------------------------------------------------------------------
const char* vtkXMLKWVolumeWidgetWriter::GetPlaneWidgetElementName()
{
  return "PlaneWidget";
}

//----------------------------------------------------------------------------
const char* vtkXMLKWVolumeWidgetWriter::GetLightsElementName()
{
  return "Lights";
}

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

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

  elem->SetIntAttribute("ProjectionType", obj->GetProjectionType());

  elem->SetFloatAttribute("PerspectiveViewAngle", 
                           obj->GetPerspectiveViewAngle());

  elem->SetIntAttribute("BlendMode", obj->GetBlendMode());

  elem->SetIntAttribute("ZSampling", obj->GetZSampling());

  return 1;
}

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

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

  // Cropping

  vtkXMLDataElement *cropping_elem = this->NewDataElement();
  elem->AddNestedElement(cropping_elem);
  cropping_elem->Delete();
  cropping_elem->SetName(this->GetCroppingElementName());
  cropping_elem->SetIntAttribute("Enabled", obj->GetCropping());
  cropping_elem->SetVectorAttribute(
    "RegionPlanes", 6, obj->GetCroppingPlanes());
  cropping_elem->SetIntAttribute("RegionFlags", obj->GetCroppingRegionFlags());

  // Reformat

  vtkXMLDataElement *reformat_elem = this->NewDataElement();
  elem->AddNestedElement(reformat_elem);
  reformat_elem->Delete();
  reformat_elem->SetName(this->GetReformatElementName());
  reformat_elem->SetIntAttribute("Enabled", obj->GetReformat());
  reformat_elem->SetFloatAttribute("Thickness", obj->GetReformatThickness());
  reformat_elem->SetVectorAttribute("Normal", 3, obj->GetReformatNormal());
  reformat_elem->SetVectorAttribute("Up", 3, obj->GetReformatUp());
  reformat_elem->SetVectorAttribute("Location", 3, obj->GetReformatLocation());
  reformat_elem->SetIntAttribute(
    "ManipulationStyle", obj->GetReformatManipulationStyle());
  reformat_elem->SetIntAttribute(
    "BoxVisibility", obj->GetReformatBoxVisibility());

  // Cursor annotation

  vtk3DCursorAnnotation *cursora = obj->GetCursor3DAnnotation();
  if (cursora)
    {
    vtkXML3DCursorAnnotationWriter *xmlw = 
      vtkXML3DCursorAnnotationWriter::New();
    xmlw->SetObject(cursora);
    xmlw->CreateInNestedElement(
      elem, this->GetCursor3DAnnotationElementName());
    xmlw->Delete();
    }

  // Bounding box annotation

  vtkBoundingBoxAnnotation *bboxa = obj->GetBoundingBoxAnnotation();
  if (bboxa)
    {
    vtkXMLBoundingBoxAnnotationWriter *xmlw = 
      vtkXMLBoundingBoxAnnotationWriter::New();
    xmlw->SetObject(bboxa);
    xmlw->CreateInNestedElement(
      elem, this->GetBoundingBoxAnnotationElementName());
    xmlw->Delete();
    }

  // Scale bar widget

  vtkKWScaleBarWidget *scalebarw = obj->GetScaleBarWidget();
  if (scalebarw)
    {
    vtkXMLKWScaleBarWidgetWriter *xmlw = vtkXMLKWScaleBarWidgetWriter::New();
    xmlw->SetObject(scalebarw);
    xmlw->CreateInNestedElement(elem, this->GetScaleBarWidgetElementName());
    xmlw->Delete();
    }

  // Orientation widget

  vtkKWOrientationWidget *orientw = obj->GetOrientationWidget();
  if (orientw)
    {
    vtkXMLKWOrientationWidgetWriter *xmlw = 
      vtkXMLKWOrientationWidgetWriter::New();
    xmlw->SetObject(orientw);
    xmlw->CreateInNestedElement(elem, this->GetOrientationWidgetElementName());
    xmlw->Delete();
    }

  // Scalar bar widget

  vtkKWScalarBarWidget *scalarbarw = obj->GetScalarBarWidget();
  if (scalarbarw)
    {
    vtkXMLDataElement *sb_elem = this->NewDataElement();
    elem->AddNestedElement(sb_elem);
    sb_elem->Delete();
    sb_elem->SetName(this->GetScalarBarWidgetElementName());
    sb_elem->SetIntAttribute("Component", obj->GetScalarBarComponent());

    vtkXMLScalarBarWidgetWriter *xmlw = vtkXMLScalarBarWidgetWriter::New();
    xmlw->SetObject(scalarbarw);
    xmlw->CreateInElement(sb_elem);
    xmlw->Delete();
    }

  // Plane widget

  vtkImplicitPlaneWidget *planew = obj->GetPlaneWidget();
  if (planew)
    {
    vtkXMLImplicitPlaneWidgetWriter *xmlw = 
      vtkXMLImplicitPlaneWidgetWriter::New();
    xmlw->SetObject(planew);
    xmlw->CreateInNestedElement(elem, this->GetPlaneWidgetElementName());
    xmlw->Delete();
    }

  // Lights

  if (obj->GetNumberOfLights())
    {
    vtkXMLDataElement *lights_elem = this->NewDataElement();
    elem->AddNestedElement(lights_elem);
    lights_elem->Delete();
    lights_elem->SetName(this->GetLightsElementName());

    vtkXMLLightWriter *xmlw = vtkXMLLightWriter::New();
    vtkCollectionIterator *it = obj->GetRenderer()->GetLights()->NewIterator();

    for (it->InitTraversal(); !it->IsDoneWithTraversal(); it->GoToNextItem())
      {
      vtkLight *light = vtkLight::SafeDownCast(it->GetCurrentObject());
      if (light)
        {
        xmlw->SetObject(light);
        xmlw->CreateInElement(lights_elem);
        }
      }

    it->Delete();
    xmlw->Delete();
    }

  return 1;
}
