//  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
//

//  File   : 
//  Author : Alexey PETROV
//  Module : VISU
//
#ifndef VISU_Structures_HeaderFile
#define VISU_Structures_HeaderFile

/*! 
  \file VISU_Structures.hxx
  \brief The file contains definitions for basic classes of the VISU CONVERTER package
*/

#include "VISUConvertor.hxx"
#include "VISU_IDMapper.hxx"
#include "VISU_ConvertorDef.hxx"

#include "MED_Vector.hxx"

#include <map>
#include <set>
#include <string>
#include <stdexcept>

namespace VISU
{
  using MED::TVector;

  //---------------------------------------------------------------
  typedef std::string TName;
  typedef TVector<TName> TNames;

  //---------------------------------------------------------------
  //! Define a basic class for all MED entites which can be identified by its number
  struct VISU_CONVERTOR_EXPORT TIntId: virtual TBaseStructure
  {
    vtkIdType myId;

    TIntId();
  };


  //---------------------------------------------------------------
  //! Define an utility base class which is repsonsible for preventing repetion
  struct VISU_CONVERTOR_EXPORT TIsVTKDone: virtual TBaseStructure
  {
    mutable bool myIsDone; //!< Say, is the corresponding MED entity already loaded into intermediate data structure 
    mutable bool myIsVTKDone; //!< Say, is the corresponding intermediate data structure already mapped into VTK representation  

    TIsVTKDone();
  };

  
  //---------------------------------------------------------------
  typedef std::map<TEntity, PMeshOnEntity> TMeshOnEntityMap;
  typedef std::map<TName, PGroup> TGroupMap;

  //! Define a basic class which corresponds to MED MESH entity
  /*!
    This class in its turn contains map of TMeshOnEntity and TGroup substructures,
    also it keeps name and dimention of corresponding MED MESH entity.
  */
  struct VISU_CONVERTOR_EXPORT TMesh: virtual TBaseStructure
  {
    TMeshOnEntityMap myMeshOnEntityMap; //!< Contains corresponding meshes for MED ENTITIES
    TGroupMap myGroupMap; //!< Contains map of bounded MED GROUPS
    TName myName; //! Name of the corresponding MED MESH
    vtkIdType myDim; //! Dimension of the corresponding MED MESH

    std::string myGroupsEntry; //!< To simplify publication of the groups in a data tree
    std::string myFieldsEntry; //!< To simplify publication of the fiels in a data tree
    std::string myPartsEntry; //!< To simplify publication of the parts in a data tree

    TMesh();
  };
  typedef std::map<std::string, PMesh> TMeshMap;


  //---------------------------------------------------------------
  //! Define a basic class which corresponds to MED PROFILE entity
  struct VISU_CONVERTOR_EXPORT TSubProfile: virtual TBaseStructure
  {
    //! Get object number of mesh cell by its VTK one
    virtual 
    vtkIdType 
    GetElemObjID(vtkIdType theID) const = 0;

    //! Get cell VTK ID for corresponding object ID
    virtual 
    vtkIdType 
    GetElemVTKID(vtkIdType theID) const = 0;
  };


  //---------------------------------------------------------------
  //! Define a containerfor MED PROFILE entities which belongs to the same MED ENTITY
  struct VISU_CONVERTOR_EXPORT TProfile: virtual TNamedIDMapper
  {};


  //---------------------------------------------------------------
  bool VISU_CONVERTOR_EXPORT
  operator<(const PSubProfile& theLeft, const PSubProfile& theRight);

  typedef std::set<PSubProfile> TProfileKey;
  typedef std::map<TProfileKey, PProfile> TProfileMap;


  //---------------------------------------------------------------
  //! Define a basic class for MED GAUSS entity
  struct VISU_CONVERTOR_EXPORT TGauss: virtual TBaseStructure
  {};


  //---------------------------------------------------------------
  //! Define a container for mesh generated from MED GAUSS and corresponding MED PROFILE
  struct VISU_CONVERTOR_EXPORT TGaussSubMesh: virtual TBaseStructure
  {
    PSubProfile mySubProfile; //!< Keeps reference on what submesh the Gauss Points are located
  };

  
  //---------------------------------------------------------------
  //! Define a container for all TGaussSubMesh that belongs to the same MED ENTITY
  struct VISU_CONVERTOR_EXPORT TGaussMesh: virtual TGaussPtsIDMapper
  {};


  //---------------------------------------------------------------
  bool VISU_CONVERTOR_EXPORT
  operator<(const PGaussSubMesh& theLeft, const PGaussSubMesh& theRight);

  typedef std::set<PGaussSubMesh> TGaussKey;
  typedef std::map<TGaussKey, PGaussMesh> TGaussMeshMap;


  //---------------------------------------------------------------

  typedef std::map<TName, PFamily> TFamilyMap;
  typedef std::map<TName, PField> TFieldMap;

  typedef std::map<vtkIdType, PFamily> TFamilyIDMap;

  //! Define a basic class which corresponds to MED ENTITY
  /*!
    This class in its turn contains map of TGaussMesh and TProfile substructures,
    also it keeps corresponding map of MED FAMILIES and FIELDS.
  */
  struct VISU_CONVERTOR_EXPORT TMeshOnEntity: virtual TNamedIDMapper
  {
    TGaussMeshMap myGaussMeshMap; //!< Contains map of Gauss mesh which exist on it
    TProfileMap myProfileMap; //!< Contains map of Profile mesh which exist on it

    TFamilyMap myFamilyMap; //!< Contains map of MED FAMILIES which belongs to it
    TFamilyIDMap myFamilyIDMap; //!< Contains map of MED FAMILIES which belongs to it

    TFieldMap myFieldMap; //!< Contains map of MED FIELDS which belongs to it

    TName myMeshName; //!< Contains name of the MED MESH where the it belongs to.
    TEntity myEntity; //!< Referes to MED ENTITY where the it belongs to.

    TMeshOnEntity();
  };


  //---------------------------------------------------------------
  //! Define a basic class for MED FAMILY entity
  struct VISU_CONVERTOR_EXPORT TFamily: virtual TIntId,
                  virtual TUnstructuredGridIDMapper
  {
    TEntity myEntity; //!< Referes to MED ENTITY where the TFamily belongs to.
    TName myName; //!< Contains name of the corresponding MED FAMILY

    TFamily();
  };


  //---------------------------------------------------------------
  bool VISU_CONVERTOR_EXPORT
  operator<(const PFamily& theLeft, const PFamily& theRight);

  typedef std::pair<TEntity, PFamily> TEnity2Family;
  typedef std::set<TEnity2Family> TFamilySet;

  //! Define a basic class for MED GROUP entity
  struct VISU_CONVERTOR_EXPORT TGroup: virtual TUnstructuredGridIDMapper
  {
    TFamilySet myFamilySet;
  };


  //---------------------------------------------------------------
  typedef std::map<vtkIdType, PValForTime> TValField;
  typedef std::pair<vtkFloatingPointType, vtkFloatingPointType> TMinMax;

  //! Define a basic class for MED FIELD entity
  struct VISU_CONVERTOR_EXPORT TField: virtual TIntId
  {
    TEntity myEntity; //!< Referes to MED ENTITY where it belongs to.
    TName myName; //!< Contains name of the corresponding MED FIELD
    TName myMeshName; //!< Contains name of the MED MESH where it belongs to.
    TValField myValField; //!< Contains sequence of values for corresponding MED TIMESTAMPS
    TNames myCompNames; //!< Contains names of components of the MED FIELD
    TNames myUnitNames; //!< Contains names of units of the MED FIELD
    vtkIdType myNbComp; //!< Keeps number of components for the MED FIELD
    bool myIsELNO;      //!< Defines whether this field contains specific "ELNO" data or not

    //! Calculate min/max values for each of the MED FIELD components among all its timestamps
    /*!
      Numeration of the components starts from 1.
      Zero component contains min/max value for modulus of corresponding vector
    */
    virtual
    TMinMax 
    GetMinMax(vtkIdType theCompID,
              const TNames& theGroupNames,
              TGaussMetric theGaussMetric = VISU::AVERAGE_METRIC) = 0;
    
    //! Calculate average min/max values for each of the MED FIELD components among all its timestamps
    virtual
    TMinMax 
    GetAverageMinMax(vtkIdType theCompID,
                     const TNames& theGroupNames,
                     TGaussMetric theGaussMetric = VISU::AVERAGE_METRIC) = 0;

    bool myIsMinMaxInitilized; //!< Is the min / max values are calculated

    TField();
  };

  // MULTIPR
  struct VISU_CONVERTOR_EXPORT TPart: virtual TIntId
  {
    vtkIdType myCurrentRes; //!< Keeps current resolution fot this part

    TPart();
  };


  //---------------------------------------------------------------
  typedef std::pair<double, std::string> TTime;

  //! Define a basic class for MED TIMESTAMP entity
  struct VISU_CONVERTOR_EXPORT TValForTime: virtual TIntId
  {
    TEntity myEntity; //!< Referes to MED ENTITY where it belongs to.
    TName myMeshName; //!< Contains name of the MED MESH where it belongs to.
    TName myFieldName; //!< Contains name of the MED FIELD where it belongs to.
    TTime myTime;

    PProfile myProfile; //!< Contains corresponding MED PROFILE where the MED TIEMSTMAP attached to
    PGaussMesh myGaussMesh;

    //! Get maximum number of Gauss Points among all geometrical types (provided for convenience)
    virtual
    int
    GetMaxNbGauss() const = 0;
  };
 

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


#endif
