/// This file is part of the X3DToolKit library
/// Copyright (C) 2002-2004  Yannick Le Goc (legoc@imag.fr)

/// http://artis.imag.fr/Members/Yannick.Legoc/X3D/

/// 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, or (at your option) any later version.

/// 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
#ifndef X3DTK_MESH_MESH_H
#define X3DTK_MESH_MESH_H

#include "MESH_X3DMeshNode.h"
#include "MESH_SFVertex.h"
#include "MESH_SFEdge.h"
#include "MESH_SFFace.h"
#include "MESH_MeshData.h"

#include <iostream>
#include <typeinfo>

namespace X3DTK {
namespace MESH {

template<class MData, class VData, class EData, class FData, bool RW> class MeshMFTemplateVertex;
template<class MData, class VData, class EData, class FData, bool RW> class MeshMFTemplateEdge;
template<class MData, class VData, class EData, class FData, bool RW> class MeshMFTemplateFace;

/*! \brief Template class declared in <b><X3DTK/MESH/scenegraph.h></b> defining a Mesh,
 *  the most important structure of the MESH scene graph. 
 *
 *  It provides a set of interconnected vertices, oriented-edges and faces.
 *
 *  \ingroup MeshSceneGraph
 */

template<class MData, class VData, class EData, class FData, bool RW>
class TemplateMesh : public X3DMeshNode
{
public:
  typedef MeshMFTemplateVertex<MData, VData, EData, FData, RW> MFVertex;
  typedef MeshMFTemplateEdge<MData, VData, EData, FData, RW> MFEdge;
  typedef MeshMFTemplateFace<MData, VData, EData, FData, RW> MFFace;
  
  /// Constructor.
  TemplateMesh();
  /// Virtual destructor.
  virtual ~TemplateMesh(); 
   
  /// Sets the Vertex attribute.
  void setVertex(TemplateVertex<MData, VData, EData, FData, RW> *vertexSet);
 
  /// Gets the Vertices that can be shared with other Mesh.
  const MFVertex &getVertices() const;
  /// Gets the edges that can be shared with other Mesh.
  const MFEdge &getEdges() const;
  /// Gets the faces.
  inline const MFFace &getFaces() const;
  /// Gets the data.  
  inline MData &data();
  /// Gets the data.  
  inline const MData &data() const;

#ifdef TEMPLATE_SPECIALIZATION_SUPPORTED
  /// Gets the data F from MData which must be of type clist<tlist<T...> >.
  template<class F>  
  F &getData();
  /// Gets optionally the data F from MData which must be of type clist<tlist<T...> >.
  template<class F>  
  F &ogetData();
#endif
    
  /// Creates Face at the end. The vertices present in coordIndex must already be created,
  /// otherwise, it returns a NULL Face.
  SFTemplateFace<MData, VData, EData, FData, RW> *createFace(const MFInt32 &coordIndex, bool ccw = true);
  /// Creates a new face at position i.
  SFTemplateFace<MData, VData, EData, FData, RW> *createFace(unsigned int i, const MFInt32 &coordIndex, bool ccw = true);

  /// Removes face.
  bool removeFace(SFTemplateFace<MData, VData, EData, FData, RW> *face);
  
protected:
  /// Removes face from neighbourhood.
  void removeFaceFromNeighBourhood(SFTemplateFace<MData, VData, EData, FData, RW> *face);
  
private:
  MFFace _faces;
  MData _data;
};

/// Mesh for the default X3DNode nodes containing all the geometry and topology 
/// informations of an X3D scene.
typedef TemplateMesh<MeshData, VertexData, EdgeData, FaceData, true> Mesh;
typedef SFTemplateVertex<MeshData, VertexData, EdgeData, FaceData, true> SFVertex;
typedef SFTemplateEdge<MeshData, VertexData, EdgeData, FaceData, true> SFEdge;
typedef SFTemplateFace<MeshData, VertexData, EdgeData, FaceData, true> SFFace;

}
}

#include "MESH_Mesh.inl"

#endif
