////////////////////////////////////////////////////////////////////////////////
//                            MESH_Vertex.inl                                 //
////////////////////////////////////////////////////////////////////////////////

namespace X3DTK {
namespace MESH {

template<class MData, class VData, class EData, class FData, bool RW>
TemplateVertex<MData, VData, EData, FData, RW>::TemplateVertex()
: X3DVertexNode() 
{
  define(Recorder<TemplateVertex<MData, VData, EData, FData, RW> >::getTypeName(typeid(*this).name()));
}

template<class MData, class VData, class EData, class FData, bool RW>
TemplateVertex<MData, VData, EData, FData, RW>::~TemplateVertex() 
{
  // delete edges
  for (typename MFEdge::iterator e = _edges.begin(); e != _edges.end(); ++e)
  {
//    cout << "deleting " << **e << endl;
  
    delete (*e)->_edgeContent;
    delete (*e)->getSymetric();
    delete (*e);
  }

  // delete vertices
  for (typename MFVertex::iterator v = _vertices.begin(); v != _vertices.end(); ++v)
    delete (*v);
}
  
template<class MData, class VData, class EData, class FData, bool RW>
SFTemplateVertex<MData, VData, EData, FData, RW> *TemplateVertex<MData, VData, EData, FData, RW>::createVertex() 
{
  SFTemplateVertex<MData, VData, EData, FData, RW> *V = new SFTemplateVertex<MData, VData, EData, FData, RW>(_vertices.size());
  _vertices.insert(std::pair<unsigned int, SFTemplateVertex<MData, VData, EData, FData, RW> *>(_vertices.size(), V));
  return V;
}

template<class MData, class VData, class EData, class FData, bool RW>
SFTemplateVertex<MData, VData, EData, FData, RW> *TemplateVertex<MData, VData, EData, FData, RW>::createVertex(unsigned int i) 
{
  SFTemplateVertex<MData, VData, EData, FData, RW> *V = new SFTemplateVertex<MData, VData, EData, FData, RW>(i);  
  _vertices.insert(std::pair<unsigned int, SFTemplateVertex<MData, VData, EData, FData, RW> *>(i, V));

  return V;
}  

template<class MData, class VData, class EData, class FData, bool RW>
bool TemplateVertex<MData, VData, EData, FData, RW>::removeVertex(SFTemplateVertex<MData, VData, EData, FData, RW> *vertex)
{
  typename MFVertex::iterator it = std::find(_vertices.begin(), _vertices.end(), vertex);
  if (it != _vertices.end())
  {
    _vertices.erase(it);
    return true;
  }  
  return false;
}

template<class MData, class VData, class EData, class FData, bool RW>
SFTemplateEdge<MData, VData, EData, FData, RW> *TemplateVertex<MData, VData, EData, FData, RW>::getEdge(SFTemplateVertex<MData, VData, EData, FData, RW> *from, SFTemplateVertex<MData, VData, EData, FData, RW> *to)
{
  if ((from == 0) || (to == 0))
    return 0;
  
  const typename SFTemplateVertex<MData, VData, EData, FData, RW>::MFEdge &from_edges = from->getEdges();
  
  for (typename SFTemplateVertex<MData, VData, EData, FData, RW>::MFEdge::const_iterator it = from_edges.begin(); it != from_edges.end(); ++it)
  {
    if ((*it)->getToVertex() == to) 
      return (*it);
  }
      
  return 0;
}

template<class MData, class VData, class EData, class FData, bool RW>
const typename TemplateVertex<MData, VData, EData, FData, RW>::MFVertex &TemplateVertex<MData, VData, EData, FData, RW>::getVertices() const 
{
  return _vertices;
}

template<class MData, class VData, class EData, class FData, bool RW>
const typename TemplateVertex<MData, VData, EData, FData, RW>::MFEdge &TemplateVertex<MData, VData, EData, FData, RW>::getEdges() const 
{
  return _edges;
}

template<class MData, class VData, class EData, class FData, bool RW>
SFTemplateEdge<MData, VData, EData, FData, RW> *TemplateVertex<MData, VData, EData, FData, RW>::createEdge(SFTemplateVertex<MData, VData, EData, FData, RW> *from, SFTemplateVertex<MData, VData, EData, FData, RW> *to) 
{
  if ((from == 0) || (to == 0))
    return 0;
 
  SFTemplateEdgeContent<MData, VData, EData, FData, RW> *content = new SFTemplateEdgeContent<MData, VData, EData, FData, RW>(from, to);
  SFTemplateEdge<MData, VData, EData, FData, RW> *E1 = new SFTemplateDirectEdge<MData, VData, EData, FData, RW>(content);
  SFTemplateEdge<MData, VData, EData, FData, RW> *E2 = new SFTemplateIndirectEdge<MData, VData, EData, FData, RW>(content);
  
  E1->setSymetric(E2);
  E2->setSymetric(E1);
     
  _edges.insert(E1);
  
  // updating content of A and B.
  // to complete... to respect order of edges.
  from->addEdge(E1);
  to->addEdge(E2);

//  cout << "creating " << *E1 << endl;
  
  return E1;
}

template<class MData, class VData, class EData, class FData, bool RW>
void TemplateVertex<MData, VData, EData, FData, RW>::removeEdge(SFTemplateEdge<MData, VData, EData, FData, RW> *edge)
{
  typename MFEdge::const_iterator e = _edges.find(edge);
  if (e != _edges.end())
    _edges.erase(e);
  e = _edges.find(edge->getSymetric());
  if (e != _edges.end())
    _edges.erase(e);
        
  delete edge->_edgeContent;
  delete edge->getSymetric();
  delete edge;
}
  
}
}  
