// genDElement - An abstract data element library
// Copyright (C) 2013-2026 Eric Bechet, Frederic Duboeuf
//
// See the LICENSE file for license information.
// Please report all bugs and problems to <bechet@cadxfem.org> or <duboeuf@outlook.com>.
//
// Initial design: Frederic Duboeuf (rev.1501)


#include "genDataConnectivity.h"
#include "genDElementManager.h"
#include "genDataGroup.h"


template<class E> void DataConnectivity<E>::buildVertexComponents(DElementBase<E>* de)
{
  if(de->getDim()<1) return;

  KeyManagerBase<E>* keyManager = KeyManagerBase<E>::getInstance();
  typename KeyManagerBase<E>::KeyContainer::const_iterator it;
  int nV;
  Key key;

  nV = de->getNumVertices();
  VertexType* vert;
  DElementBase<E>* Dvert;
  std::string s = list->getIndex();
  for(int i=0; i<nV; ++i)
  {
    vert = de->getVertex(i);
    ElementPolicies<VertexType>::getKey(vert,key);
    it = keyManager->find(key);
    if (it==keyManager->end())
      Dvert = new MDElement<VertexType,E,DataConnectivity>(vert,s.c_str());
    else
      Dvert = it->second;
    genDataGroup* dataGroup;
    DataConnectivity<E>* data;
    dataGroup = Dvert->getDatas();
    dataGroup->getData(s.c_str(),data);
    if (!data)
    {
      data = new DataConnectivity<E>(s.c_str(),Dvert);
      dataGroup->setData(s,data);
    }
    data->setConnectivity(de);
    components[0].push_back(Dvert);
  }
}

template<class E> void DataConnectivity<E>::buildEdgeComponents(DElementBase<E>* de)
{
  if(de->getDim()<2) return;

  KeyManagerBase<E>* keyManager = KeyManagerBase<E>::getInstance();
  typename KeyManagerBase<E>::KeyContainer::const_iterator it;
  int nE;
  Key key;

  nE = de->getNumEdges();
  EdgeType* edge;
  DElementBase<E>* Dedge;
  std::string s = list->getIndex();
  for(int i=0; i<nE; ++i)
  {
    edge = de->getEdge(i);
    ElementPolicies<EdgeType>::getKey(edge,key);
    it = keyManager->find(key);
    if (it==keyManager->end())
      Dedge = new MDElement<EdgeType,E,DataConnectivity>(edge,s.c_str());
    else
      Dedge = it->second;
    genDataGroup* dataGroup;
    DataConnectivity<E>* data;
    dataGroup = Dedge->getDatas();
    dataGroup->getData(s.c_str(),data);
    if (!data)
    {
      data = new DataConnectivity<E>(s.c_str(),Dedge);
      dataGroup->setData(s,data);
    }
    data->setConnectivity(de);
    components[1].push_back(Dedge);
  }
}

template<class E> void DataConnectivity<E>::buildFaceComponents(DElementBase<E>* de)
{
  if(de->getDim()<3) return;

  KeyManagerBase<E>* keyManager = KeyManagerBase<E>::getInstance();
  typename KeyManagerBase<E>::KeyContainer::const_iterator it;
  int nF;
  Key key;

  nF = de->getNumFaces();
  FaceType* face;
  DElementBase<E>* Dface;
  std::string s = list->getIndex();
  for(int i=0; i<nF; ++i)
  {
    face = de->getFace(i);
    ElementPolicies<FaceType>::getKey(face,key);
    it = keyManager->find(key);
    if (it==keyManager->end())
      Dface = new MDElement<FaceType,E,DataConnectivity>(face,s.c_str());
    else
      Dface = it->second;
    genDataGroup* dataGroup;
    DataConnectivity<E>* data;
    dataGroup = Dface->getDatas();
    dataGroup->getData(s.c_str(),data);
    if (!data)
    {
      data = new DataConnectivity<E>(s.c_str(),Dface);
      dataGroup->setData(s,data);
    }
    data->setConnectivity(de);
    components[2].push_back(Dface);
  }
}

template<class E> void DataConnectivity<E>::printComponents(std::ostream &os) const
{
  std::streamsize width = os.width();
  Key key;
  for (int i=0; i<4; ++i)
  {
    os.width(width); os <<"";
    os << (int)getNumComponents(i) << " " << i << "D components :\n";
    for (int j=0; j<getNumComponents(i); ++j)
    {
      DElementBase<E>* de = getComponent(i,j);
      de->getKey(key);
      os.width(width+2);
      os << key;
    }
  }
}

template<class E> void DataConnectivity<E>::printConnectivities(std::ostream &os) const
{
  std::streamsize width = os.width();
  Key key;
  for (int i=0; i<4; ++i)
  {
    os.width(width); os <<"";
    os << (int)getNumConnectivities(i) << " " << i << "D connectivities :\n";
    for (int j=0; j<getNumConnectivities(i); ++j)
    {
      DElementBase<E>* de = getConnectivity(i,j);
      de->getKey(key);
      os.width(width+2);
      os << key;
    }
  }
}

template<class E> void DataConnectivity<E>::print(std::ostream &os) const
{
  std::streamsize width = os.width();
  printComponents(os);
  os.width(width);
  printConnectivities(os);
}
