//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
//
//  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
//
//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//

//  VISU OBJECT : interactive object for VISU entities implementation
//  File   : VISU_PrsObject_i.hxx
//  Author : Alexey PETROV
//  Module : VISU
//
#ifndef VISU_Prs3d_i_HeaderFile
#define VISU_Prs3d_i_HeaderFile

#include "VISU_PrsObject_i.hh"

#include "VISU_ActorFactory.h"
#include "VISU_ConvertorDef.hxx"

#include "SALOME_GenericObj_i.hh"
#include "SALOME_GenericObjPointer.hh"
#include "SALOME_InteractiveObject.hxx"

#include "VTKViewer.h"

#include <vtkSmartPointer.h>
#include <vtkTimeStamp.h>

class VISU_PipeLine;
class VISU_ActorBase;
class VISU_Actor;

class vtkPlane;
class vtkActorCollection;
class vtkDataSet;

namespace VISU
{
  //----------------------------------------------------------------------------
  class Result_i;


  //----------------------------------------------------------------------------
  struct TResultObserver: public virtual boost::signalslib::trackable
  {
    virtual
    void
    UpdateFromResult(Result_i* theResult) = 0;
  };


  //----------------------------------------------------------------------------
  //! Base class for all VTK 3D presentations.
  /*!
    It is a root class for a middle level of VISU functionality.
    Almost all functionality of the the class implemented through redirection 
    external requestes to its VISU_PipeLine.
    It define an interface and implement the following topics:
    - provide persistent mechanism;
    - implement basic actor management (CreateActor, UpdateActor, UpdateActors, RemoveActor and RemoveActors);
    - implement common 3D functionality like "clipping planes" and offset.
  */
  class VISU_I_EXPORT Prs3d_i : public virtual POA_VISU::Prs3d,
				public virtual SALOME::GenericObj_i,
				public virtual TActorFactory,
				public virtual PrsObject_i

  {
    Prs3d_i(const Prs3d_i&);

  public:
    //----------------------------------------------------------------------------
    typedef PrsObject_i TSuperClass;
    typedef VISU::Prs3d TInterface;

    //----------------------------------------------------------------------------
    //! A constructor to create a fresh instance of the class
    Prs3d_i();

    //! To create a deep copy from another instance of the class
    virtual
    void
    SameAs(const Prs3d_i* theOrigin);

    virtual
    ~Prs3d_i();

    //----------------------------------------------------------------------------
    virtual
    CORBA::Boolean 
    Apply(bool theReInit);

    //----------------------------------------------------------------------------
    void 
    SetCResult(Result_i* theResult);

    Result_i* 
    GetCResult() const;

    virtual
    void 
    SetResultObject(VISU::Result_ptr theResult);

    virtual
    VISU::Result_ptr
    GetResultObject();

    //----------------------------------------------------------------------------
    virtual
    void 
    SetMeshName(const char* theMeshName);

    virtual
    char*
    GetMeshName();

    std::string
    GetCMeshName() const;

    //----------------------------------------------------------------------------
    //! To generate an unique type name for the class (used into persistent functionality)
    virtual
    const char* 
    GetComment() const = 0;

    //! To generate an unique name for the instance of the class
    virtual
    QString
    GenerateName() = 0;

    //! To save paramters of the instance to std::ostringstream
    virtual
    void
    ToStream(std::ostringstream& theStr);

    //! To restore paramters of the instance from Storable::TRestoringMap
    virtual
    Storable* 
    Restore(SALOMEDS::SObject_ptr theSObject,
	    const Storable::TRestoringMap& theMap);

    //----------------------------------------------------------------------------
    //! Get corresponding SALOMEDS::SObject
    virtual
    SALOMEDS::SObject_var 
    GetSObject();

    //----------------------------------------------------------------------------
    //! To update is internal state
    virtual 
    void
    Update();

    //! To remove the instance from study
    virtual
    void
    RemoveFromStudy();

    //----------------------------------------------------------------------------
    //! Get corresponding VISU_PipeLine
    VISU_PipeLine* 
    GetPipeLine() const;

    bool
    IsPipeLineExists();

    //! Get input of the VISU_PipeLine
    vtkDataSet* 
    GetInput();

    //----------------------------------------------------------------------------
    //! To define a way to create VTK representation of the instance
    virtual 
    VISU_Actor* 
    CreateActor() = 0;

    //! To unregister the pointed actor
    virtual 
    void
    RemoveActor(VISU_ActorBase* theActor);

    //! To unregister all actors of the instance
    virtual 
    void
    RemoveActors();

    //! To update the pointed actor
    virtual 
    void
    UpdateActor(VISU_ActorBase* theActor);

    //! To update all actors of the instance
    virtual 
    void
    UpdateActors();

    //----------------------------------------------------------------------------
    // Clipping planes
    void
    RemoveAllClippingPlanes();

    bool
    AddClippingPlane(vtkPlane* thePlane);

    vtkIdType
    GetNumberOfClippingPlanes() const;

    vtkPlane* 
    GetClippingPlane(vtkIdType theID) const;

    void RemoveClippingPlane(vtkIdType theID);

    void
    SetPlaneParam(vtkFloatingPointType theDir[3], 
		  vtkFloatingPointType theDist, 
		  vtkPlane* thePlane);

    //----------------------------------------------------------------------------
    void
    GetBounds(vtkFloatingPointType aBounds[6]);

    int
    GetNumberOfActors();

    bool
    HasVisibleActors();

    //! Move the 3D presentation according to the given offset parameters
    void
    SetOffset(const CORBA::Float* theOffsets);

    //! Move the 3D presentation according to the given offset parameters
    virtual
    void
    SetOffset(CORBA::Float theDx, 
	      CORBA::Float theDy, 
	      CORBA::Float theDz);

    //! Gets offset parameters for the 3D presentation
    void
    GetOffset(CORBA::Float* theOffsets);

    //! Gets offset parameters for the 3D presentation
    virtual
    void
    GetOffset(CORBA::Float& theDx, 
	      CORBA::Float& theDy, 
	      CORBA::Float& theDz);

    //----------------------------------------------------------------------------
    //! Set standard point marker for the object
    virtual
    void
    SetMarkerStd(VISU::MarkerType theMarkerType, VISU::MarkerScale theMarkerScale);
  
    //! Set custom point marker
    virtual
    void
    SetMarkerTexture(CORBA::Long theTextureId);
  
    //! Get type of the point marker
    virtual
    VISU::MarkerType
    GetMarkerType();

    //! Get scale of the point marker
    virtual
    VISU::MarkerScale
    GetMarkerScale();

    //! Get texture identifier of the point marker
    virtual
    CORBA::Long
    GetMarkerTexture();
  
    //----------------------------------------------------------------------------
    //! Gets memory size actually used by the presentation (Mb).
    virtual
    CORBA::Float
    GetMemorySize();

    //----------------------------------------------------------------------------
    //! Gets know whether the factory instance can be used for actor management or not
    virtual
    bool 
    GetActiveState();

    //----------------------------------------------------------------------------
    //! Return modified time of the presentation
    virtual
    unsigned long int 
    GetMTime();

    //----------------------------------------------------------------------------
    //! Create and return the interactive object
    virtual
    Handle(SALOME_InteractiveObject)
    GetIO();

    //! Used in derived classes to initilize the IO for actors
    virtual
    std::string
    GetActorEntry();

    //----------------------------------------------------------------------------
    //! Managing "forced hidden" flag
    bool
    IsForcedHidden() const;

    void
    SetForcedHidden( bool );

  protected:
    /*! 
      Used in Apply method to get know whether it is possible to create presentation
      with the input parameters or not. The derived classes can use this method 
      to customize Apply behaviour.
    */
    virtual 
    bool 
    SetInput(bool theReInit);

    //! Restore input parameters if Apply function fails
    virtual 
    void 
    OnRestoreInput();

    //! Used in derived classes to initilize the myPipeLine member
    void
    SetPipeLine(VISU_PipeLine* thePipeLine);

    //! Used in derived classes to initilize the myPipeLine member
    void
    CreateActor(VISU_Actor* theActor);

    //! Gets or creates VISU_PipeLine instance for actor initilization
    virtual 
    VISU_PipeLine* 
    GetActorPipeLine();

    //! To check dataset validity, throws std::exception if not valid
    virtual
    void
    CheckDataSet();

    bool
    LoadMarkerTexture(int theMarkerId, VTK::MarkerTexture& theMarkerTexture);

  protected:
    vtkTimeStamp myUpdateTime;
    vtkTimeStamp myParamsTime;

  private:
    void
    SetResultEntry(const std::string& theResultEntry);

    std::string
    GetResultEntry();

    typedef SALOME::GenericObjPtr<VISU::Result_i> TResultPtr;
    TResultPtr myResult;
    TResultPtr myPreviousResult;

    std::string myMeshName;
    std::string myPreviousMeshName;

    CORBA::Float myOffset[3];

    VISU::MarkerType myMarkerType;
    VISU::MarkerScale myMarkerScale;
    int myMarkerId;

    boost::signal0<void> myUpdateActorsSignal;
    boost::signal0<void> myRemoveActorsFromRendererSignal;
    vtkSmartPointer<vtkActorCollection> myActorCollection;

    vtkSmartPointer<VISU_PipeLine> myPipeLine;

    Handle(SALOME_InteractiveObject) myIO;

  private:
    friend class ColoredPrs3dCache_i;

    //! Sets activity flag for the factory instance
    void
    SetActiveState(bool theState);
    
    bool myIsActiveSatate;

    bool myIsForcedHidden;
  };

  //----------------------------------------------------------------------------
}

#endif
