//  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 CONVERTOR :
//  File   : VISU_Convertor.hxx
//  Author : Alexey PETROV
//  Module : VISU
//
#ifndef VISU_PointCoords_HeaderFile
#define VISU_PointCoords_HeaderFile

/*! 
  \file VISU_PointCoords.hxx
  \brief The file contains declarations for basic interfaces that defines point coords of mesh elements
*/

#include "VISUConvertor.hxx"
#include "VISU_Convertor.hxx"
#include "VISU_ConvertorDef_impl.hxx"

#include "MED_SliceArray.hxx"
#include "MED_Structures.hxx"

#include <vtkSmartPointer.h>

class vtkPointSet;

namespace VISU
{
  //---------------------------------------------------------------
  typedef vtkSmartPointer<vtkPointSet> PPointSet;

  typedef MED::TFloat TCoord;
  using MED::TCoordSlice;
  using MED::TCCoordSlice;

  //---------------------------------------------------------------
  //! This class is responsible for keeping the mesh node coordinates
  class VISU_CONVERTOR_EXPORT TCoordHolderBase: public virtual TBaseStructure
  {
  public:
    //! To initilize the instance
    void
    Init(vtkIdType theNbPoints,
         vtkIdType theDim);

    vtkIdType
    GetNbPoints() const;

    vtkIdType
    GetDim() const;

    size_t
    size() const;

    //! Gets memory size used by the instance (bytes).
    virtual
    unsigned long int
    GetMemorySize();

    //! Get slice of coordinates for defined node (const version)
    virtual
    TCCoordSlice
    GetCoordSlice(vtkIdType theNodeId) const = 0;

    //! Get slice of coordinates for defined node
    virtual
    TCoordSlice 
    GetCoordSlice(vtkIdType theNodeId) = 0;

    virtual
    unsigned char*
    GetValuePtr() = 0;

  protected:
    vtkIdType myDim; //!< Dimension of the nodal coordinates
    vtkIdType myNbPoints; //!< Number of nodes in corresponding mesh
  };
  typedef MED::SharedPtr<TCoordHolderBase> PCoordHolder;


  //---------------------------------------------------------------
  template<class TContainerType>
  class TCoordHolder: public virtual TCoordHolderBase
  {
  public:
    //! To initilize the class instance
    void
    Init(vtkIdType theNbPoints,
         vtkIdType theDim,
         const TContainerType& theCoord)
    {
      TCoordHolderBase::Init(theNbPoints, theDim);
      myCoord = theCoord;
    }

    //! Gets pointer to the first element in the node coordinates array
    virtual
    TCoord*
    GetPointer() = 0;

    //! Gets pointer to the first element in the node coordinates array (const version)
    virtual
    const TCoord*
    GetPointer() const = 0;

    //! Get slice of coordinates for defined node (const version)
    virtual
    TCCoordSlice
    GetCoordSlice(vtkIdType theNodeId) const
    {
      return TCCoordSlice(this->GetPointer(), 
                          this->size(),
                          std::slice(theNodeId * this->GetDim(), this->GetDim(), 1));
    }

    //! Get slice of coordinates for defined node
    virtual
    TCoordSlice 
    GetCoordSlice(vtkIdType theNodeId)
    {
      return TCoordSlice(this->GetPointer(), 
                         this->size(),
                         std::slice(theNodeId * this->GetDim(), this->GetDim(), 1));
    }

    virtual
    unsigned char*
    GetValuePtr()
    {
      return (unsigned char*)this->GetPointer();
    }

  protected:
    mutable TContainerType myCoord; //!< Keeps the node coordinates container itself
  };


  //---------------------------------------------------------------
  //! This class is responsible for representation of mesh nodes
  class VISU_CONVERTOR_EXPORT TPointCoords: public virtual TIsVTKDone
  {
  public:
    TPointCoords();

    //! To initilize the class
    void
    Init(const PCoordHolder& theCoord);

    vtkIdType
    GetNbPoints() const;

    vtkIdType
    GetDim() const;

    virtual
    vtkPointSet*
    GetPointSet() const; //!< Gets corresponding VTK structure

    //! Gets memory size used by the instance (bytes).
    virtual
    unsigned long int
    GetMemorySize();

    //! Get slice of coordinates for defined node (const version)
    TCCoordSlice
    GetCoordSlice(vtkIdType theNodeId) const;

    //! Get slice of coordinates for defined node
    TCoordSlice 
    GetCoordSlice(vtkIdType theNodeId);

    //! Get object number for node by its VTK one
    virtual
    vtkIdType
    GetObjID(vtkIdType theID) const;

    //! Get VTK number for node by its object one
    virtual
    vtkIdType
    GetVTKID(vtkIdType theID) const;

  protected:
    //! An container for coordinates of the nodes
    /*!
      Usage of slices allow to minimize amount of memory to store the nodal coordinates and
      provide unifirm way of conversation with this coordinates (independant from mesh dimension)
    */
    PCoordHolder myCoord; //!< A pointer to the coordinates container holder
    PPointSet myPointSet; //!< VTK representation for the mesh nodes

    void
    SetVoidArray() const; //!< Passes the MED node coordinates data directly to VTK
  };


  //---------------------------------------------------------------
  //! This class is responsible for representation of mesh nodes
  /*!
    In additition to its base functionlity it support mapping of VTK to object numeration and
    keeps names for each of nodes.
  */
  class VISU_CONVERTOR_EXPORT TNamedPointCoords: public virtual TPointCoords
  {
  public:
    //! To initilize the class (numeration of the nodes can be missed)
    void
    Init(const PCoordHolder& theCoord);
    
    //! Get name for defined dimension
    std::string&
    GetName(vtkIdType theDim);
    
    //! Get name for defined dimension (const version)
    const std::string&
    GetName(vtkIdType theDim) const;

    //! Get name of node by its object number
    virtual
    std::string 
    GetNodeName(vtkIdType theObjID) const;

    virtual
    vtkPointSet*
    GetPointSet() const; //!< Gets initialized corresponding VTK structure

    //! Gets memory size used by the instance (bytes).
    virtual
    unsigned long int
    GetMemorySize();

  protected:
    typedef TVector<std::string> TPointsDim;
    TPointsDim myPointsDim; //!< Keeps name of each dimension
  };


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

#endif
