namespace X3DTK {
namespace MESH {

template<class MData, class VData, class EData, class FData, bool RW>
TemplateStatsCalculatorStateVariables<MData, VData, EData, FData, RW>::TemplateStatsCalculatorStateVariables()
: StateVariables()
{
}

template<class MData, class VData, class EData, class FData, bool RW>
void TemplateStatsCalculatorStateVariables<MData, VData, EData, FData, RW>::init()
{
  _modelMeshInfo.init();
  _modelVertexInfo.init();
  _meshInfoList.clear();
  _vertexInfoList.clear();
}

template<class MData, class VData, class EData, class FData, bool RW>
void TemplateStatsCalculatorStateVariables<MData, VData, EData, FData, RW>::finish()
{
  _nodeList.clear();
}

template<class MData, class VData, class EData, class FData, bool RW>
void TemplateStatsCalculatorStateVariables<MData, VData, EData, FData, RW>::addNode(SFNode N)
{
  _nodeList.push_back(N);
}

template<class MData, class VData, class EData, class FData, bool RW>
bool TemplateStatsCalculatorStateVariables<MData, VData, EData, FData, RW>::getNode(SFNode N) const
{
  std::list<SFNode>::const_iterator it = std::find(_nodeList.begin(), _nodeList.end(), N);
  return (it != _nodeList.end());
}

template<class MData, class VData, class EData, class FData, bool RW>
void TemplateStatsCalculatorStateVariables<MData, VData, EData, FData, RW>::setCurrentMesh(TemplateMesh<MData, VData, EData, FData, RW> *mesh)
{
  _currentMesh = mesh;
}

template<class MData, class VData, class EData, class FData, bool RW>
void TemplateStatsCalculatorStateVariables<MData, VData, EData, FData, RW>::addFaces(unsigned int faces)
{
  _modelMeshInfo.addFaces(faces);

  for (typename std::list<std::pair<SFNode, TemplateMeshInfo<MData, VData, EData, FData, RW> > >::iterator it = _meshInfoList.begin(); it != _meshInfoList.end(); ++it)
  {
    if ((*it).first == _currentMesh)
    {
      (*it).second.addFaces(faces);
      return;
    }  
  }
 
  _meshInfoList.push_back(std::pair<SFNode, TemplateMeshInfo<MData, VData, EData, FData, RW> >(_currentMesh, TemplateMeshInfo<MData, VData, EData, FData, RW>()));
  _meshInfoList.back().second.addFaces(faces);
}

template<class MData, class VData, class EData, class FData, bool RW>
void TemplateStatsCalculatorStateVariables<MData, VData, EData, FData, RW>::addVertices(unsigned int vertices)
{
  _modelVertexInfo.addVertices(vertices);

  for (typename std::list<std::pair<SFNode, TemplateVertexInfo<MData, VData, EData, FData, RW> > >::iterator it = _vertexInfoList.begin(); it != _vertexInfoList.end(); ++it)
  {
    if ((*it).first == _currentMesh)
    {
      (*it).second.addVertices(vertices);
      return;
    }  
  }
 
  _vertexInfoList.push_back(std::pair<SFNode, TemplateVertexInfo<MData, VData, EData, FData, RW> >(_currentMesh, TemplateVertexInfo<MData, VData, EData, FData, RW>()));
  _vertexInfoList.back().second.addVertices(vertices);
}

template<class MData, class VData, class EData, class FData, bool RW>
void TemplateStatsCalculatorStateVariables<MData, VData, EData, FData, RW>::addEdges(unsigned int edges)
{
  _modelMeshInfo.addEdges(edges);

  for (typename std::list<std::pair<SFNode, TemplateMeshInfo<MData, VData, EData, FData, RW> > >::iterator it = _meshInfoList.begin(); it != _meshInfoList.end(); ++it)
  {
    if ((*it).first == _currentMesh)
    {
      (*it).second.addEdges(edges);
      return;
    }  
  }
 
  _meshInfoList.push_back(std::pair<SFNode, TemplateMeshInfo<MData, VData, EData, FData, RW> >(_currentMesh, TemplateMeshInfo<MData, VData, EData, FData, RW>()));
  _meshInfoList.back().second.addEdges(edges);
}

template<class MData, class VData, class EData, class FData, bool RW>
void TemplateStatsCalculatorStateVariables<MData, VData, EData, FData, RW>::setInstances(unsigned int instances)
{
  for (typename std::list<std::pair<SFNode, TemplateMeshInfo<MData, VData, EData, FData, RW> > >::iterator it = _meshInfoList.begin(); it != _meshInfoList.end(); ++it)
  {
    if ((*it).first == _currentMesh)
    {
      (*it).second.setInstances(instances);
      return;
    }  
  }
 
  _meshInfoList.push_back(std::pair<SFNode, TemplateMeshInfo<MData, VData, EData, FData, RW> >(_currentMesh, TemplateMeshInfo<MData, VData, EData, FData, RW>()));
  _meshInfoList.back().second.setInstances(instances);
}

template<class MData, class VData, class EData, class FData, bool RW>
unsigned int TemplateStatsCalculatorStateVariables<MData, VData, EData, FData, RW>::getModelFaces() const
{
  return _modelMeshInfo.getFaces();
}

template<class MData, class VData, class EData, class FData, bool RW>
unsigned int TemplateStatsCalculatorStateVariables<MData, VData, EData, FData, RW>::getModelVertices() const
{
  return _modelVertexInfo.getVertices();
}

template<class MData, class VData, class EData, class FData, bool RW>
unsigned int TemplateStatsCalculatorStateVariables<MData, VData, EData, FData, RW>::getModelEdges() const
{
  return _modelMeshInfo.getEdges();
}

template<class MData, class VData, class EData, class FData, bool RW>
unsigned int TemplateStatsCalculatorStateVariables<MData, VData, EData, FData, RW>::getFacesOf(SFNode N)
{
  for (typename std::list<std::pair<SFNode, TemplateMeshInfo<MData, VData, EData, FData, RW> > >::iterator it = _meshInfoList.begin(); it != _meshInfoList.end(); ++it)
  {
    if ((*it).first == N)
      return (*it).second.getFaces();
  }
 
  _meshInfoList.push_back(std::pair<SFNode, TemplateMeshInfo<MData, VData, EData, FData, RW> >(N, TemplateMeshInfo<MData, VData, EData, FData, RW>()));
  return _meshInfoList.back().second.getFaces();
}

template<class MData, class VData, class EData, class FData, bool RW>
unsigned int TemplateStatsCalculatorStateVariables<MData, VData, EData, FData, RW>::getVerticesOf(SFNode N)
{
  for (typename std::list<std::pair<SFNode, TemplateVertexInfo<MData, VData, EData, FData, RW> > >::iterator it = _vertexInfoList.begin(); it != _vertexInfoList.end(); ++it)
  {
    if ((*it).first == N)
      return (*it).second.getVertices();
  }
 
  _vertexInfoList.push_back(std::pair<SFNode, TemplateVertexInfo<MData, VData, EData, FData, RW> >(N, TemplateVertexInfo<MData, VData, EData, FData, RW>()));
  return _vertexInfoList.back().second.getVertices();
}

template<class MData, class VData, class EData, class FData, bool RW>
unsigned int TemplateStatsCalculatorStateVariables<MData, VData, EData, FData, RW>::getEdgesOf(SFNode N)
{
  for (typename std::list<std::pair<SFNode, TemplateMeshInfo<MData, VData, EData, FData, RW> > >::iterator it = _meshInfoList.begin(); it != _meshInfoList.end(); ++it)
  {
    if ((*it).first == N)
      return (*it).second.getEdges();
  }
 
  _meshInfoList.push_back(std::pair<SFNode, TemplateMeshInfo<MData, VData, EData, FData, RW> >(N, TemplateMeshInfo<MData, VData, EData, FData, RW>()));
  return _meshInfoList.back().second.getEdges();
}

template<class MData, class VData, class EData, class FData, bool RW>
const TemplateMeshInfo<MData, VData, EData, FData, RW> &TemplateStatsCalculatorStateVariables<MData, VData, EData, FData, RW>::getModelMeshInfo() const
{
  return _modelMeshInfo;
}

template<class MData, class VData, class EData, class FData, bool RW>
const std::list<std::pair<SFNode, TemplateMeshInfo<MData, VData, EData, FData, RW> > > &TemplateStatsCalculatorStateVariables<MData, VData, EData, FData, RW>::getMeshInfoList() const
{
  return _meshInfoList;
}

template<class MData, class VData, class EData, class FData, bool RW>
const TemplateVertexInfo<MData, VData, EData, FData, RW> &TemplateStatsCalculatorStateVariables<MData, VData, EData, FData, RW>::getModelVertexInfo() const
{
  return _modelVertexInfo;
}

template<class MData, class VData, class EData, class FData, bool RW>
const std::list<std::pair<SFNode, TemplateVertexInfo<MData, VData, EData, FData, RW> > > &TemplateStatsCalculatorStateVariables<MData, VData, EData, FData, RW>::getVertexInfoList() const
{
  return _vertexInfoList;
}


template<class MData, class VData, class EData, class FData, bool RW>
void TemplateStatsCalculatorStateVariables<MData, VData, EData, FData, RW>::setSelectedNodes(const MFNode &selectedNodes)
{
  _selectedNodes = selectedNodes;
}

template<class MData, class VData, class EData, class FData, bool RW>
MFNode TemplateStatsCalculatorStateVariables<MData, VData, EData, FData, RW>::getSelectedNodes() const
{
  return _selectedNodes;
}

}
}
