//  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_ColoredPrs3dCache_i.hh
//  Author : Oleg UVAROV
//  Module : VISU
//
#ifndef VISU_ColoredPrs3dCache_i_HeaderFile
#define VISU_ColoredPrs3dCache_i_HeaderFile

#include "VISU_I.hxx"

#include "VISU_ColoredPrs3dFactory.hh"

#include "SALOME_GenericObjPointer.hh"

namespace VISU
{
  class Result_i;
  class ColoredPrs3d_i;
  class ColoredPrs3dHolder_i;

  struct TPrs3dPtr: SALOME::GenericObjPtr<ColoredPrs3d_i>
  {
    typedef SALOME::GenericObjPtr<ColoredPrs3d_i> TSuperClass;
 
    //! Initialize smart pointer to NULL.
    TPrs3dPtr():
      TSuperClass()
    {}

    //! Initialize smart pointer to given object (TSGenericObj must be complete).
    TPrs3dPtr(ColoredPrs3d_i* thePointer):
      TSuperClass(thePointer)
    {}

    /*! 
      Initialize smart pointer with a new reference to the same object
      referenced by given smart pointer.
     */
    TPrs3dPtr(const TPrs3dPtr& thePointer):
      TSuperClass(thePointer)
    {}


    /*! 
      Assign object to reference.  This removes any reference to an old
      object.
    */
    TPrs3dPtr& 
    operator=(const TPrs3dPtr& thePointer)
    {
      TSuperClass::operator=(thePointer);
      return *this;
    }

    /*! 
      Assign object to reference.  This removes any reference to an old
      object.
    */
    TPrs3dPtr& 
    operator=(ColoredPrs3d_i* thePointer)
    {
      TSuperClass::operator=(thePointer);
      return *this;
    }

    //! Get the contained pointer.
    ColoredPrs3d_i* 
    get() const
    {
      ColoredPrs3d_i* aColoredPrs3d = TSuperClass::get();
      // To implement postponed restoring of the presentation
      if(aColoredPrs3d)
	aColoredPrs3d->InitFromRestoringState();
      return aColoredPrs3d;
    }
  };

  typedef std::deque<TPrs3dPtr> TLastVisitedPrsList;

  typedef std::string THolderEntry;
  typedef std::map<THolderEntry,TLastVisitedPrsList> TColoredPrs3dHolderMap;

  /*!
   * This interface is responsible for memory management of 3d presentations.
   * One cache corresponds to one study.
   */
  class VISU_I_EXPORT ColoredPrs3dCache_i : public virtual POA_VISU::ColoredPrs3dCache,
			      public virtual SALOME::GenericObj_i,
			      public virtual RemovableObject_i
  {
    ColoredPrs3dCache_i();
    ColoredPrs3dCache_i(const ColoredPrs3dCache_i&);
  public:
    //----------------------------------------------------------------------------
    //! A constructor to create an instance of the class
    explicit
    ColoredPrs3dCache_i(SALOMEDS::Study_ptr theStudy,
			bool thePublishInStudy = true);

    virtual
    ~ColoredPrs3dCache_i();

    //----------------------------------------------------------------------------
    /*! Creates ColoredPrs3dHolder */
    virtual
    VISU::ColoredPrs3dHolder_ptr
    CreateHolder(VISU::VISUType theType,
		 const VISU::ColoredPrs3dHolder::BasicInput& theInput);

    //----------------------------------------------------------------------------
    /*! Gets a memory which is required to create a holder. */
    virtual
    VISU::ColoredPrs3dCache::EnlargeType
    GetRequiredMemory(VISU::VISUType theType,
		      const VISU::ColoredPrs3dHolder::BasicInput& theInput,
		      CORBA::Float& theRequiredMemory);

    //----------------------------------------------------------------------------
    //! Sets a memory mode.
    virtual
    void
    SetMemoryMode(VISU::ColoredPrs3dCache::MemoryMode theMode);

    virtual
    VISU::ColoredPrs3dCache::MemoryMode
    GetMemoryMode();

    //----------------------------------------------------------------------------
    //! Sets a memory size for limited mode.
    virtual
    void
    SetLimitedMemory(CORBA::Float theMemorySize);

    virtual
    CORBA::Float
    GetLimitedMemory();

    virtual
    CORBA::Float
    GetMemorySize();

    virtual
    CORBA::Float
    GetDeviceMemorySize();

    //----------------------------------------------------------------------------
    virtual 
    VISU::VISUType 
    GetType() 
    {
      return VISU::TCOLOREDPRS3DCACHE; 
    }

    virtual
    void
    RemoveFromStudy();

    static
    std::string
    GetFolderName();

    virtual
    const char* 
    GetComment() const;

    virtual
    void
    ToStream(std::ostringstream&);

    virtual
    Storable*
    Restore(SALOMEDS::SObject_ptr theSObject,
	    const Storable::TRestoringMap& theMap);

    static
    Storable*
    StorableEngine(SALOMEDS::SObject_ptr theSObject,
		   const Storable::TRestoringMap& theMap,
		   const std::string& thePrefix,
		   CORBA::Boolean theIsMultiFile);

    //----------------------------------------------------------------------------
    //! Finds or creates instance of the ColoredPrs3dCache in the given SALOMEDS::Study
    static
    VISU::ColoredPrs3dCache_i*
    GetInstance_i(SALOMEDS::Study_ptr theStudy);

    static
    VISU::ColoredPrs3dCache_ptr
    GetInstance(SALOMEDS::Study_ptr theStudy);

    //! Creates corresponding ColoredPrs3d instance and apply the BasicInput
    VISU::ColoredPrs3d_i*
    CreateColoredPrs3d(VISU::VISUType theType,
		       VISU::ColoredPrs3dHolder::BasicInput theInput);

    //! Registers the given ColoredPrs3d instance for the ColoredPrs3dHolder
    VISU::ColoredPrs3d_i*
    RegisterInHolder(VISU::ColoredPrs3d_i* thePrs3d,
		     const std::string& theHolderEntry);

    //! Creates and registers corresponding ColoredPrs3d instance for the ColoredPrs3dHolder
    VISU::ColoredPrs3d_i*
    CreatePrs(VISU::VISUType theType,
	      VISU::ColoredPrs3dHolder::BasicInput theInput,
	      VISU::ColoredPrs3dHolder_i* theHolder);

    TLastVisitedPrsList&
    GetLastVisitedPrsList(VISU::ColoredPrs3dHolder_i* theHolder);

    TPrs3dPtr
    GetLastVisitedPrs(VISU::ColoredPrs3dHolder_i* theHolder);

    bool
    UpdateLastVisitedPrs(VISU::ColoredPrs3dHolder_i* theHolder,
			 VISU::ColoredPrs3d_i* thePrs,
			 const VISU::ColoredPrs3dHolder::BasicInput& theInput,
			 VISU::View3D_ptr theView3D);

    //! Unregister the holder instance from cache
    void
    RemoveHolder(VISU::ColoredPrs3dHolder_i* theHolder);

  public:
    static const std::string myComment;

  protected:
    //----------------------------------------------------------------------------
    virtual int
    IsPossible(VISU::VISUType theType,
	       const VISU::ColoredPrs3dHolder::BasicInput& theInput,
	       float& theMemoryToClear,
	       const std::string theHolderEntry);

    TPrs3dPtr
    FindPrsByInput(TLastVisitedPrsList& theLastVisitedPrsList,
		   const VISU::ColoredPrs3dHolder::BasicInput& theInput);

    //----------------------------------------------------------------------------
    void
    ClearCache(float theMemory = 0);

    bool
    ClearMemory(CORBA::Float theRequiredMemory, 
		const std::string& theHolderEntry);

    void
    PrintCache();

  private:
    CORBA::Float myLimitedMemory;
    VISU::ColoredPrs3dCache::MemoryMode myMemoryMode;

    TColoredPrs3dHolderMap myHolderMap; 
  };


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

#endif
