#ifndef MeshBuilder_H
#define MeshBuilder_H

#include <Process.hpp>
#include <Geometry.hpp>

//#include <CellMakerUtils.hpp>

using namespace std;

// MeshBuilder
namespace mgx 
{

  class mgxBase_EXPORT MeshBuilder
  {
  public:

    double Epsilon;

    // point to pos in pVec map
    std::map<Point3d, int> pMap;

    // vector of points
    std::vector<Point3d> pVec;

    // vector of tris
    std::vector<Point3i> triVec;

    // vector of vtxs (needs to be created using writeVertexVec if points were only added by position)
    std::vector<vertex> vtxVec;

    // saves labels
    std::map<int, int> vertexLabelMap;
    std::vector<int> vertexLabels;

   MeshBuilder() { Epsilon = 1E-8; }
   MeshBuilder(double eps) : Epsilon(eps) {}

   // get the idx of vertex in vtxVec (using the pMap)
   // if it doesnt exist yet add it to vtxVec
   int getIndex(const vertex& v);

   // get the idx of point pos in pVec (using the pMap), assigning the label to the point if its new
   // if it doesnt exist yet add it to pVec
   int getIndex(Point3d pos, int label = 0);

   // add triangle vertex based (keep vertices)
   void addTri(const vertex &a, const vertex &b, const vertex &c, bool keepAll = false);

   // add tri point based (merge nearby points & save in pMap)
   //void addTri(const Point3d &a, const Point3d &b, const Point3d &c);
  
   // add tri point based (merge nearby points & save in pMap), with label for the 3 points
   void addTri(const Point3d &a, const Point3d &b, const Point3d &c, Point3i label = Point3i(0,0,0));

   // add tri with check of which side is heading up and adjusting towards a given normal
   void addTriCheckOrient(const vertex &a, const vertex &b, const vertex &c, Point3d &nrml, bool keepAll = false);

   // create the vtxVec from the pVec
   // parameters determine the vertex labels
   void writeVertexVec(bool useLabelMap, int label = 0);
   void writeVertexVec(std::map<Point3d, int> pointLabelMap);

   // merge vtxVec and triVec with the ones from another MeshBuilder object
   void addToVec(MeshBuilder mb);

   void eraseSmallComponents();

   void eraseIdenticalTris();

   void correctOrientationsComponent(std::vector<Point3i>& tris);

  };


}
#endif
