//  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_ColoredPrs3dFactory_HeaderFile
#define VISU_ColoredPrs3dFactory_HeaderFile

#include "SALOMEconfig.h"
#include CORBA_SERVER_HEADER(VISU_Gen)
#include CORBA_SERVER_HEADER(SALOMEDS)

#include "VISU_I.hxx"
#include "SALOME_GenericObjPointer.hh"
#include "VISU_DeformedShapeAndScalarMap_i.hh"
#include "VISU_Plot3D_i.hh"
#include "VISU_GaussPoints_i.hh"
#include "VISU_StreamLines_i.hh"
#include "VISU_Vectors_i.hh"
#include "VISU_CutLines_i.hh"
#include "VISU_CutSegment_i.hh"
#include "VISU_CutPlanes_i.hh"
#include "VISU_DeformedShape_i.hh"
#include "VISU_IsoSurfaces_i.hh"
#include "VISU_ScalarMap_i.hh"
#include "VISU_ColoredPrs3d_i.hh"
#include "VISU_Result_i.hh"
#include "VISU_TypeList.hxx"

namespace VISU
{
  namespace TL
  {
    //----------------------------------------------------------------------------
    typedef TList<DeformedShapeAndScalarMap_i,
		  TList<DeformedShapeAndScalarMap_i,
		  TList<DeformedShape_i,
			TList<StreamLines_i,
			      TList<GaussPoints_i,
				    TList<ScalarMap_i,
					  TList<IsoSurfaces_i,
						TList<CutPlanes_i,
						      TList<CutLines_i,
							    TList<CutSegment_i,
								  TList<Vectors_i,
									TList<Plot3D_i, 
									      TNullType> > > > > > > > > > > >
    TColoredPrs3dTypeList;
    

    typedef TList<TInt2Type<TSCALARMAPONDEFORMEDSHAPE>,
		  TList<TInt2Type<TDEFORMEDSHAPEANDSCALARMAP>,
		  TList<TInt2Type<TDEFORMEDSHAPE>, 
			TList<TInt2Type<TSTREAMLINES>,
			      TList<TInt2Type<TGAUSSPOINTS>,
				    TList<TInt2Type<TSCALARMAP>,
					  TList<TInt2Type<TISOSURFACES>,
						TList<TInt2Type<TCUTPLANES>,
						      TList<TInt2Type<TCUTLINES>,
							    TList<TInt2Type<TCUTSEGMENT>,
								  TList<TInt2Type<TVECTORS>,
									TList<TInt2Type<TPLOT3D>, 
									      TNullType> > > > > > > > > > > >
    TColoredPrs3dEnumList;
    

    //----------------------------------------------------------------------------
    template <unsigned int type_enum>
    struct TColoredEnum2Type
    {
      typedef typename TTypeAt<TColoredPrs3dTypeList, TIndexOf<TColoredPrs3dEnumList, TInt2Type<type_enum> >::value >::TResult TResult;
    };
    
    //----------------------------------------------------------------------------
    template <class T>
    struct TColoredType2Enum
    {
      typedef typename TTypeAt<TColoredPrs3dEnumList, TIndexOf<TColoredPrs3dTypeList, T>::value >::TResult TResult;
    };

  }

  //----------------------------------------------------------------------------
  template<typename TPrs3d_i> 
  ColoredPrs3d_i*
  CreatePrs3dByType(SALOMEDS::Study_ptr theStudy,
		    ColoredPrs3d_i::EPublishInStudyMode thePublishInStudyMode)
  {
    if(!theStudy->GetProperties()->IsLocked()){
      typedef typename TPrs3d_i::TInterface TPrs3d;
      if(TPrs3d_i* aPresent = new TPrs3d_i(thePublishInStudyMode)){
	return aPresent;
      }
    }
    return NULL;
  }


  //----------------------------------------------------------------------------
  template<unsigned int type_enum> 
  ColoredPrs3d_i*
  CreatePrs3dByEnum(SALOMEDS::Study_ptr theStudy,
		    ColoredPrs3d_i::EPublishInStudyMode thePublishInStudyMode)
  {
    typedef typename TL::TColoredEnum2Type<type_enum>::TResult TColoredPrs3d;
    return CreatePrs3dByType<TColoredPrs3d>(theStudy,
					    thePublishInStudyMode);
  };


  //----------------------------------------------------------------------------
  ColoredPrs3d_i*
  CreatePrs3d_i(VISUType theType,
		SALOMEDS::Study_ptr theStudy,
		ColoredPrs3d_i::EPublishInStudyMode thePublishInStudyMode);
  
  
  //----------------------------------------------------------------------------
  bool VISU_I_EXPORT
  CreatColoredPrs3d(ColoredPrs3d_i* theColoredPrs3d,
		    Result_i* theResult,
		    const std::string& theMeshName, 
		    VISU::Entity theEntity,
		    const std::string& theFieldName, 
		    CORBA::Long theIteration);


  //----------------------------------------------------------------------------
  //Create 3D collored Presentation Of Different Types
  template<typename TPrs3d_i> TPrs3d_i*
  CreatePrs3d(Result_ptr theResult, 
	      const std::string& theMeshName, 
	      VISU::Entity theEntity,
	      const std::string& theFieldName, 
	      CORBA::Long theTimeStampNumber)
  {
    typedef typename TPrs3d_i::TInterface TPrs3d;
    typename TPrs3d::_var_type aPrs3d;

    if(Result_i* aResult = dynamic_cast<Result_i*>(GetServant(theResult).in())){
      SALOMEDS::Study_var aStudy = aResult->GetStudyDocument();
      if(aStudy->GetProperties()->IsLocked()) 
	return NULL;
    
      if(TPrs3d_i::IsPossible(aResult, theMeshName, theEntity, theFieldName, theTimeStampNumber, true)){
	TPrs3d_i* aPresent = new TPrs3d_i(ColoredPrs3d_i::EPublishUnderTimeStamp);
	
	if(CreatColoredPrs3d(aPresent, aResult, theMeshName, theEntity, theFieldName, theTimeStampNumber))
	  return aPresent;
	
	aPresent->_remove_ref();
      }
    }
    return NULL;
  }


  //----------------------------------------------------------------------------
  template<typename TPrs3d_i> 
  typename TPrs3d_i::TInterface::_var_type
  Prs3dOnField(Result_ptr theResult, 
	       const std::string& theMeshName, 
	       VISU::Entity theEntity,
	       const std::string& theFieldName, 
	       CORBA::Long theTimeStampNumber)
  {
    if(TPrs3d_i* aPrs3d = CreatePrs3d<TPrs3d_i>(theResult,
						theMeshName,
						theEntity,
						theFieldName,
						theTimeStampNumber))
      return aPrs3d->_this();
    typedef typename TPrs3d_i::TInterface TPrs3d;
    return TPrs3d::_nil();
  }


  //----------------------------------------------------------------------------
  //! Gets the memory required for cache
  VISU_I_EXPORT VISU::ColoredPrs3dCache::EnlargeType
  GetRequiredCacheMemory(VISU::VISUType theType,
			 VISU::Result_ptr theResult, 
			 const std::string& theMeshName, 
			 VISU::Entity theEntity,
			 const std::string& theFieldName, 
			 CORBA::Long theTimeStampNumber,
			 CORBA::Float& theUsedMemory,
			 CORBA::Float& theRequiredMemory);


  //----------------------------------------------------------------------------
  //! Gets the memory required for cache
  template<class TColoredPrs3d_i> 
  VISU::ColoredPrs3dCache::EnlargeType
  GetRequiredCacheMemory(VISU::Result_ptr theResult, 
			 const std::string& theMeshName, 
			 VISU::Entity theEntity,
			 const std::string& theFieldName, 
			 CORBA::Long theTimeStampNumber,
			 CORBA::Float& theUsedMemory,
			 CORBA::Float& theRequiredMemory)
  {
    typedef typename TL::TColoredType2Enum<TColoredPrs3d_i>::TResult TEnum;
    VISU::VISUType aColoredPrs3dType = VISU::VISUType(TEnum::value);
    return GetRequiredCacheMemory(aColoredPrs3dType,
				  theResult, 
				  theMeshName, 
				  theEntity,
				  theFieldName, 
				  theTimeStampNumber,
				  theUsedMemory,
				  theRequiredMemory);
  }


  //----------------------------------------------------------------------------
  //! Creates ColoredPrs3dHolder by enumeration value and gets its first device
  VISU_I_EXPORT ColoredPrs3d_i*
  CreateHolder2GetDeviceByEnum(VISU::VISUType theType,
			       VISU::Result_ptr theResult, 
			       const std::string& theMeshName, 
			       VISU::Entity theEntity,
			       const std::string& theFieldName, 
			       CORBA::Long theTimeStampNumber,
			       VISU::ColoredPrs3dCache::EnlargeType theEnlargeType,
			       CORBA::Float theRequiredMemory);
    
  
  //----------------------------------------------------------------------------
  //! Creates ColoredPrs3dHolder by type and gets its first device
  template<class TColoredPrs3d_i> 
  TColoredPrs3d_i*
  CreateHolder2GetDeviceByType(VISU::Result_ptr theResult, 
			       const std::string& theMeshName, 
			       VISU::Entity theEntity,
			       const std::string& theFieldName, 
			       CORBA::Long theTimeStampNumber,
			       VISU::ColoredPrs3dCache::EnlargeType theEnlargeType,
			       CORBA::Float theRequiredMemory)
  {
    typedef typename TL::TColoredType2Enum<TColoredPrs3d_i>::TResult TEnum;
    VISU::VISUType aColoredPrs3dType = VISU::VISUType(TEnum::value);
    ColoredPrs3d_i* aColoredPrs3d = CreateHolder2GetDeviceByEnum(aColoredPrs3dType,
								 theResult, 
								 theMeshName, 
								 theEntity,
								 theFieldName, 
								 theTimeStampNumber,
								 theEnlargeType,
								 theRequiredMemory);
    return dynamic_cast<TColoredPrs3d_i*>(aColoredPrs3d);
  }


  //----------------------------------------------------------------------------
  template<unsigned int colored_prs3d_type_enum>
  struct TSameAsFactory
  {
    typedef typename TL::TColoredEnum2Type<colored_prs3d_type_enum>::TResult TColoredPrs3d;

    void
    Copy(ColoredPrs3d_i* theColoredPrs3dFrom, ColoredPrs3d_i* theColoredPrs3dTo)
    {
      theColoredPrs3dTo->SetCResult(theColoredPrs3dFrom->GetCResult());
      theColoredPrs3dTo->SetMeshName(theColoredPrs3dFrom->GetCMeshName().c_str());
      theColoredPrs3dTo->SetEntity(theColoredPrs3dFrom->GetEntity());
      theColoredPrs3dTo->SetFieldName(theColoredPrs3dFrom->GetCFieldName().c_str());
      theColoredPrs3dTo->SetTimeStampNumber(theColoredPrs3dFrom->GetTimeStampNumber());
      theColoredPrs3dTo->SameAs(theColoredPrs3dFrom);
    }

    SALOME::GenericObjPtr<TColoredPrs3d>
    Create(ColoredPrs3d_i* theColoredPrs3d,
	   ColoredPrs3d_i::EPublishInStudyMode thePublishInStudyMode,
	   bool theCreateAsTemporalObject = true)
    {
      SALOME::GenericObjPtr<TColoredPrs3d> aSameColoredPrs3d(new TColoredPrs3d(thePublishInStudyMode));
      Copy(theColoredPrs3d, aSameColoredPrs3d);
      if ( theCreateAsTemporalObject )
	aSameColoredPrs3d->Destroy();
      return aSameColoredPrs3d;
    }
  };

  //----------------------------------------------------------------------------
  //! Check is possible to create ColoredPrs3dHolder with the given input
  VISU_I_EXPORT size_t
  CheckIsPossible(VISU::VISUType theType,
		  const VISU::ColoredPrs3dHolder::BasicInput& theInput,
		  bool theMemoryCheck);
    
  //----------------------------------------------------------------------------
  //! Check is possible to create ColoredPrs3dHolder with the given input
  template<unsigned int colored_prs3d_type_enum> 
  size_t
  CheckIsPossible(const VISU::ColoredPrs3dHolder::BasicInput& theInput,
		  bool theMemoryCheck)
  {
    VISU::Result_i* aResult = dynamic_cast<VISU::Result_i*>( VISU::GetServant(theInput.myResult).in() );
    std::string aMeshName = theInput.myMeshName.in();
    VISU::Entity anEntity = theInput.myEntity;
    std::string aFieldName = theInput.myFieldName.in();
    CORBA::Long aTimeStampNumber = theInput.myTimeStampNumber;

    typedef typename VISU::TL::TColoredEnum2Type<colored_prs3d_type_enum>::TResult TColoredPrs3d;
    return TColoredPrs3d::IsPossible(aResult,
				     aMeshName,
				     anEntity,
				     aFieldName,
				     aTimeStampNumber,
				     theMemoryCheck);
  }

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

#endif
