// 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)


#ifndef _GEN_DATA_CONNECTIVITY_H_
#define _GEN_DATA_CONNECTIVITY_H_

#include "genData.h"
#include "genDElement.h"

template<class E> class DataConnectivity : public genData
{
protected :
  std::vector<std::vector<DElementBase<E>*> > components;   // components (0D,1D,2D,3D) < dim
  std::vector<std::vector<DElementBase<E>*> > connectivities; // connectivities (0D,1D,2D,3D) > dim
public :
  typedef E ElementType;
  typedef typename ElementTraits<ElementType>::VertexType VertexType;
  typedef typename ElementTraits<ElementType>::EdgeType EdgeType;
  typedef typename ElementTraits<ElementType>::FaceType FaceType;

protected :
  virtual void buildVertexComponents(DElementBase<E>* de);
  virtual void buildEdgeComponents(DElementBase<E>* de);
  virtual void buildFaceComponents(DElementBase<E>* de);
  virtual void buildComponents(DElementBase<E>* de)
  {
    buildVertexComponents(de);
    buildEdgeComponents(de);
    buildFaceComponents(de);
  }
public :
  DataConnectivity(const char* s, DElementBase<E>* de) : genData(s,de), components(4), connectivities(4) {buildComponents(de);}
  virtual ~DataConnectivity() {}
  virtual int getNumComponents(int dim) const {return components[dim].size();}
  virtual DElementBase<E>* getComponent(int dim, int i) const {return components[dim][i];}
  virtual int getNumConnectivities(int dim) const {return connectivities[dim].size();}
  virtual DElementBase<E>* getConnectivity(int dim, int i) const {return connectivities[dim][i];}
  virtual void setConnectivity(DElementBase<E>* de) {connectivities[de->getDim()].push_back(de);}
  virtual void printComponents(std::ostream &os) const;
  virtual void printConnectivities(std::ostream &os) const;
  virtual void print(std::ostream &os) const;
};


////////////////////////////////////////////////////////
//////////////// MDELEMENT CLASS ///////////////////////
////////////////////////////////////////////////////////


// Special class for other components (MVertex, MEdge, MFace)
template<class M,class E,class D1=nothing,class D2=nothing,class D3=nothing> class MDElement : public DElementBase<E>
{
protected :
  M* m;
public :
  typedef E ElementType;

protected :
  virtual void addToManager(const Key &key) {DElementBase<E>::addToManager(key);}
public :
  MDElement(M* m_, const char* s1="", const char* s2="", const char* s3="") : DElementBase<E>(), m(m_)
  {
    Key key;
    getKey(key);
    addToManager(key);
    DataPolicies<E,D1>::addData(getDatas(), s1, this);
    DataPolicies<E,D2>::addData(getDatas(), s2, this);
    DataPolicies<E,D3>::addData(getDatas(), s3, this);
  }
  MDElement(M* m_, const Key &key, const char* s1="", const char* s2="", const char* s3="") : DElementBase<E>(), m(m_)
  {
    addToManager(key);
    DataPolicies<E,D1>::addData(getDatas(), s1, this);
    DataPolicies<E,D2>::addData(getDatas(), s2, this);
    DataPolicies<E,D3>::addData(getDatas(), s3, this);
  }
  virtual ~MDElement() {}
  virtual E* get() const {return DElementBase<E>::get();}
  virtual void set(E* e_) {DElementBase<E>::set(e_);}
  virtual int getDim() const {if(DElementBase<E>::get()) return DElementBase<E>::getDim(); return ElementPolicies<M>::getDim(m);}
  virtual int getNum() const {if(DElementBase<E>::get()) return DElementBase<E>::getNum(); return 0;}
  virtual int getNumVertices() {if(DElementBase<E>::get()) return DElementBase<E>::getNumVertices(); return ElementPolicies<M>::getNumVertices(m);}
  virtual int getNumEdges() {if(DElementBase<E>::get()) return DElementBase<E>::getNumEdges(); return ElementPolicies<M>::getNumEdges(m);}
  virtual int getNumFaces() {if(DElementBase<E>::get()) return DElementBase<E>::getNumFaces(); return ElementPolicies<M>::getNumFaces(m);}
  virtual typename ElementTraits<E>::VertexType* getVertex(int i) {if(DElementBase<E>::get()) return DElementBase<E>::getVertex(i); return ElementPolicies<M>::getVertex(m,i);}
  virtual typename ElementTraits<E>::EdgeType* getEdge(int i) {if(DElementBase<E>::get()) return DElementBase<E>::getEdge(i); return ElementPolicies<M>::getEdge(m,i);}
  virtual typename ElementTraits<E>::FaceType* getFace(int i) {if(DElementBase<E>::get()) return DElementBase<E>::getFace(i); return ElementPolicies<M>::getFace(m,i);}
  virtual genDataGroup* getDatas() const {return DElementBase<E>::getDatas();}
  virtual void clearDatas() {DElementBase<E>::clearDatas();}
  virtual void getKey(Key &key) const {if(DElementBase<E>::get()) return DElementBase<E>::getKey(key); ElementPolicies<M>::getKey(m,key);}
};


#include "genDataConnectivity.hpp"

#endif // _GEN_DATA_CONNECTIVITY_H_