// Cutmesh - Copyright (C) 2010-2018 T. Mouton, E. Bechet 
//
// See the LICENSE file for license information and contributions.
// bugs and problems to <thibaud.mouton@gmail.com>.

#ifndef _CUTTER_CUTMESH_H_
#define _CUTTER_CUTMESH_H_

//#define DEFINE_OLD_CUTTER

#include <Context.h>
#include <GModel.h>
#include <MPoint.h>
#include <MLine.h>
#include <MTetrahedron.h>
#include <MTriangle.h>

#include <MSubElement.h>
#include <gmshVertex.h>
#include <discreteEdge.h>
#include <discreteFace.h>
#include <discreteRegion.h>

#include "common.h"
#include "LTetra.h"
#include "LVertex.h"
#include "hashstruct.h"
#include "mesh.h"
#include "surface.h"
#include "topo.h"
#include "brep.h"
#include "discreteSurface.h"
#include "cadlevelset.h"
#include "lsquery.h"

#if defined(CUTMESH_ENABLE_IBREP)
#include "IBrep.h"
#endif




class IBrep;
class MeshCutter
{
  protected:
    cadLevelset *_mycadls;
    Mesh *_mymesh;
    LSurface *_mysurface;
    Topo *_mytopo;
    Topology_query *_myquery;
    GModel *_gm;
    std::vector<MTetrahedron*> _lmt;
    std::vector<MVertex*> _lmv;
    options *_opts;

  public:
//     int readConfigFile();
    MeshCutter ( options *opt );
    ~MeshCutter() {if (_mycadls) delete _mycadls;}
    int restore();
    void load_GModel_mesh ( GModel *gm );
    void load_GModel_geometry ( GModel *gm, int face_max_sample );
    int process();

    void stat_GModel();

    void build_GModel_Old(); // using old polyhedra

    void build_GModel(); // using new subentities in gmsh

    // Get physicals of volumes (phys[3]), faces (phys[2]), edges (phys[1]) and vertices (phys[0]) corresponding to the subset generated by the boolean expression given in the query string
    // A query contains :
    // --> operands : a levelset index + a position indicator {NEG, ZERO, POS} depending of the part of the domain we want. An operand corresponds to a subset containing
    // volumes, faces, edges and vertices
    // --> operators : {union, inter, sub} for union, intersection or substraction of subsets
    //
    // A query is given in the Reverse Polish Notation (RPN) : every operator follows all of its operands.
    // Ex : let levelsets of index 1 and 2 cutting a domain :
    // --> the domain defined by the negative part of both levelset has expression : 1 NEG 2 NEG inter
    // --> edges defined by the intersection of both levelset has expression : 1 ZERO 2 ZERO inter
    // --> combining both examples to obtain the subset of example 1 without edges obtained in example 2 --> 1 NEG 2 NEG inter 1 ZERO 2 ZERO inter sub
    //
    // To prevent any problems of topology recognition, the mesh must include only one physical per entity
    void physical_query ( const char *query, std::vector<int> phys[4] );

    inline GModel *get_gmodel()
    {
      assert ( _gm != NULL );
      return _gm;
    }
    inline Mesh *get_mesh()
    {
      assert ( _mymesh != NULL );
      return _mymesh;
    }
    MVertex *get_vertex ( LVertex *v );
    MTetrahedron *get_tetra ( LTetra *t );
    MVertex *add_vertex ( LVertex *v, GRegion *gr );
    MTetrahedron *add_tetra ( LTetra *t, GRegion *gr );
};

#endif
