// Created on: 2011-10-27
// Created by: Roman KOZLOV
// Copyright (c) 2011-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.

#include <IVtkTools_ShapeObject.hxx>
#include <IVtkTools_ShapeDataSource.hxx>

// prevent disabling some MSVC warning messages by VTK headers
#ifdef _MSC_VER
  #pragma warning(push)
#endif
#include <vtkActor.h>
#include <vtkObjectFactory.h>
#include <vtkDataSet.h>
#include <vtkInformation.h>
#include <vtkInformationObjectBaseKey.h>
#include <vtkPolyData.h>
#ifdef _MSC_VER
  #pragma warning(pop)
#endif

IVtkTools_ShapeObject::KeyPtr IVtkTools_ShapeObject::myKey = 0;

//============================================================================
//  Method: getKey
// Purpose: Static method to get vtkInformationKey for retrieving OccShape
//          instance from the actor.
//============================================================================
IVtkTools_ShapeObject::KeyPtr IVtkTools_ShapeObject::getKey()
{
  if (!myKey)
  {
    myKey = new vtkInformationObjectBaseKey("OccShapePtr", "IVtkTools_ShapeObject::Key");
  }

  return myKey;
}

//============================================================================
//  Method: GetOccShape
// Purpose: Static method to get OCC shape from VTK actor's data from
//          information object by key.
//============================================================================
IVtkOCC_Shape::Handle IVtkTools_ShapeObject::GetOccShape(vtkActor* theActor)
{
  IVtkOCC_Shape::Handle                      anOccShape;
  vtkSmartPointer<IVtkTools_ShapeDataSource> aSrc = IVtkTools_ShapeObject::GetShapeSource(theActor);
  if (aSrc.GetPointer() != NULL)
  {
    anOccShape = aSrc->GetShape();
  }
  return anOccShape;
}

//============================================================================
//  Method: GetShapeSource
// Purpose: Static method to get OCC shape source from VTK actor's data from
//          information object by key.
//============================================================================
vtkSmartPointer<IVtkTools_ShapeDataSource> IVtkTools_ShapeObject ::GetShapeSource(
  vtkActor* theActor)
{
  vtkSmartPointer<IVtkTools_ShapeDataSource> anOccShapeSource;
  vtkSmartPointer<vtkInformation>            anInfo = theActor->GetPropertyKeys();
  if (anInfo.GetPointer() != NULL)
  {
    KeyPtr aKey = getKey();
    if (aKey->Has(anInfo))
    {
      vtkSmartPointer<IVtkTools_ShapeObject> aShapeObj =
        IVtkTools_ShapeObject::SafeDownCast(aKey->Get(anInfo));
      anOccShapeSource = aShapeObj->GetShapeSource();
    }
  }
  return anOccShapeSource;
}

//============================================================================
//  Method: SetShapeSource
// Purpose: Static method to set OCC shape source to VTK dataset in information
//          object with key.
//============================================================================
void IVtkTools_ShapeObject::SetShapeSource(IVtkTools_ShapeDataSource* theDataSource,
                                           vtkDataSet*                theDataSet)
{
  if (!theDataSet->GetInformation())
  {
    theDataSet->SetInformation(vtkSmartPointer<vtkInformation>::New());
  }
  vtkSmartPointer<vtkInformation>        aDatasetInfo = theDataSet->GetInformation();
  KeyPtr                                 aKey         = getKey();
  vtkSmartPointer<IVtkTools_ShapeObject> aShapeObj = vtkSmartPointer<IVtkTools_ShapeObject>::New();
  aShapeObj->SetShapeSource(theDataSource);
  aKey->Set(aDatasetInfo, aShapeObj);
}

//============================================================================
//  Method: SetShapeSource
// Purpose: Static method to set OCC shape source to VTK actor in information
//          object with key.
//============================================================================
void IVtkTools_ShapeObject::SetShapeSource(IVtkTools_ShapeDataSource* theDataSource,
                                           vtkActor*                  theActor)
{
  if (!theActor->GetPropertyKeys())
  {
    theActor->SetPropertyKeys(vtkSmartPointer<vtkInformation>::New());
  }

  vtkSmartPointer<vtkInformation>        anInfo    = theActor->GetPropertyKeys();
  KeyPtr                                 aKey      = getKey();
  vtkSmartPointer<IVtkTools_ShapeObject> aShapeObj = vtkSmartPointer<IVtkTools_ShapeObject>::New();
  aShapeObj->SetShapeSource(theDataSource);
  aKey->Set(anInfo, aShapeObj);
}

//! @class IVtkTools_ShapeObject
//! @brief VTK holder class for OCC shapes to pass them through pipelines.
vtkStandardNewMacro(IVtkTools_ShapeObject)

  //============================================================================
  //  Method: Constructor
  // Purpose: Protected constructor.
  //============================================================================
  IVtkTools_ShapeObject::IVtkTools_ShapeObject()
{
}

//============================================================================
//  Method: Destructor
// Purpose: Protected destructor.
//============================================================================
IVtkTools_ShapeObject::~IVtkTools_ShapeObject() {}

//============================================================================
//  Method: SetShapeSource
// Purpose:
//============================================================================
void IVtkTools_ShapeObject::SetShapeSource(IVtkTools_ShapeDataSource* theDataSource)
{
  myShapeSource = theDataSource;
}

//============================================================================
//  Method: GetShapeSource
// Purpose:
//============================================================================
IVtkTools_ShapeDataSource* IVtkTools_ShapeObject::GetShapeSource() const
{
  return myShapeSource;
}
