// GenFem - A high-level finite element library
// Copyright (C) 2010-2026 Eric Bechet
//
// See the LICENSE file for license information and contributions.
// Please report all bugs and problems to <bechet@cadxfem.org>.
//
// Initial design: Frederic Duboeuf (rev.1230)


#ifndef _GEN_GROUP_OF_ELEMENTS_H_
#define _GEN_GROUP_OF_ELEMENTS_H_

#include <set>
#include <vector>

#include "MElement.h"
#include "MVertex.h"

class genFilterElement;
class genFilterElementTrivial;

class GFace;
class GRegion;
class GEntity;


template<class Element> class NumElementLessThan //: public std::binary_function<Element*, Element*, bool> // deprecated
{
 public:
  bool operator()(const Element* e1, const Element* e2) const
  {
    return e1->getNum() < e2->getNum();
  }
};


class genGroupOfElements
{
 public:
  typedef std::set<MElement*,NumElementLessThan<MElement> > elementContainer;
  typedef std::set<MVertex*,NumElementLessThan<MVertex> > vertexContainer;

 protected:
  elementContainer elements; // list of elements
  elementContainer parents;  // list of parent elements
  vertexContainer vertices;  // list of vertices without virtual vertices of sub-elements

 public:
  genGroupOfElements(){}
  genGroupOfElements(int dim, int physical);
  genGroupOfElements(int dim, std::vector<int> physicals);
  genGroupOfElements(GFace*);
  genGroupOfElements(GRegion*);
  genGroupOfElements(std::vector<MElement*> &elems, const genFilterElement &filter);
  genGroupOfElements(genGroupOfElements* g, const genFilterElement &filter);
  genGroupOfElements(elementContainer::const_iterator begin, elementContainer::const_iterator end, const genFilterElement &filter);
  ~genGroupOfElements(){}

  void addElementary(GEntity* ge, const genFilterElement &filter);
  void addPhysical(int dim, int physical, const genFilterElement &filter);
  void addPhysicals(int dim, std::vector<int> physicals, const genFilterElement &filter);
  void addGroup(genGroupOfElements &g, const genFilterElement &filter);

  void insert (MElement* e);

  inline elementContainer::const_iterator begin() const {return elements.begin();}
  inline elementContainer::const_iterator end() const {return elements.end();}
  inline elementContainer::const_iterator pbegin() const {return parents.begin();}
  inline elementContainer::const_iterator pend() const {return parents.end();}
  inline vertexContainer::const_iterator vbegin() const {return vertices.begin();}
  inline vertexContainer::const_iterator vend() const {return vertices.end();}

  inline int size() const {return (int)elements.size();}
  inline int psize() const {return (int)parents.size();}
  inline int vsize() const {return (int)vertices.size();}

  inline elementContainer::const_iterator find(MElement* e) const {return elements.find(e);}
  inline elementContainer::const_iterator pfind(MElement* p) const {return parents.find(p);}
  inline vertexContainer::const_iterator vfind(MVertex* v) const {return vertices.find(v);}
  inline bool contains(MElement* e) const {return (elements.find(e) != elements.end());}
  inline bool pcontains(MElement* p) const {return (parents.find(p) != parents.end());}
  inline bool vcontains(MVertex* v) const {return (vertices.find(v) != vertices.end());}

  // int version creating temporary element
  elementContainer::const_iterator find(int num) const;
  elementContainer::const_iterator pfind(int pnum) const;
  vertexContainer::const_iterator vfind(int vnum) const;
  bool contains(int num) const;
  bool pcontains(int pnum) const;
  bool vcontains(int vnum) const;

  inline void clearAll() {vertices.clear(); elements.clear(); parents.clear();}
};

#endif // _GEN_GROUP_OF_ELEMENTS_H_
