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

#include "mesh.h"

#ifndef CUTMESH_ENABLE_IBREP


void Mesh::ImportIbrep ( IBrep *ib )
{
}

#else

#include "IBrep.h"

// DONE !
void Mesh::ImportIbrep ( IBrep *ib )
{
  // mesh
  ib->UpdateFields();
  std::map<int,int> mp;
  int n=0;
  for ( IBrep::iterator_nodes itn=ib->begin_nodes();itn!=ib->end_nodes();++itn )
  {
    LVertex *v =new_vertex ( itn->XYZ() [0],itn->XYZ() [1],itn->XYZ() [2] );
    add_vertex ( v );
    mp[itn->num]=n;
    n++;
  }

  for ( IBrep::iterator_elements ite=ib->begin_elements();ite!=ib->end_elements();++ite )
  {
    int v[4];
    assert ( ite->Type() ==IElement::TETRAHEDRON );
    for ( int i=0;i<4;++i )
    {
      v[i]=mp[ite->GetNode ( i )->num ];
    }
    LTetra *t = new_tetra ( get_vertex ( v[0] ), get_vertex ( v[1] ), get_vertex ( v[2] ), get_vertex ( v[3] ), NULL );
    add_tetra ( t );
    for ( int j = 0; j < 4; j++ ) _hfs->addAdjFace ( t, j );
  }

//     writeMesh("initial");
  _hfs->clear();

  // levelsets
  std::map<int,int> mf;
  int nstd=0;
  int nedg=0;
  for ( IBrep::iterator_fields itf=ib->begin_fields();itf!=ib->end_fields();++itf )
  {
    int id= itf->num;
    int local_id;
    if ( ( id>=0 ) && ( itf->info.tag==0 ) )
    {
      local_id=get_entity_manager()->add_face_id ( id );
      get_entity_manager()->set_real_face ( local_id );
      mf[id]=local_id;
//            std::cout << "face " << id << " (" << local_id << ")" << std::endl;
    }
  }

  for ( IBrep::iterator_fields itf=ib->begin_fields();itf!=ib->end_fields();++itf )
  {
    int id=itf->num;
    int local_id;
    if ( ( id<0 ) || ( itf->info.tag!=0 ) )
    {
      IBrep::iterator_edges e=ib->GetEdge ( fabs ( id ) ); // need to get faces ids connected to that edge
      int nco=e->GetNumCoEdges();
      assert ( nco==2 ); // manifold surface (one edge -> 2 faces connectes)
      int s[2];
      for ( int f=0;f<nco;++f )
      {
        IBrep::iterator_coedges coe=e->GetCoEdge( f);
        s[f]=coe->GetFace()->num;
      }
      local_id = get_entity_manager()->add_cut_face_id ( id, s[0], s[1] );
      get_entity_manager()->set_virtual_face ( local_id );
//            std::cout << "edge (virtual face)" << id << " (" << local_id << ")" << std::endl;
      mf[id]=local_id;
    }

  }


  for ( IBrep::iterator_nodes itn=ib->begin_nodes();itn!=ib->end_nodes();++itn )
  {
    int n=mp[itn->num];
//      std::cout << n << " ";
    LVertex *v = get_vertex ( n );
    const IInt* fields=itn->Fields();
    const double * vals=itn->Values();
    int nf=itn->NumFields();
//      std::cout << nf << std::endl;

    for ( int i=0;i<nf;++i )
    {
      int local_id=mf[fields[i]];
//        std::cout << fields[i] << " loc=" << local_id << " " ;
      double dist=vals[i];
      dist *= -1.0; // WARNING --> hack // que faire ici ???
      if ( !v->checkSurf ( local_id ) )
      {
        v->addSurf ( local_id, dist );
        if ( fabs ( dist ) < TOL )
          v->addSurfZero ( local_id );
      }
    }
//      if (nf) std::cout << std::endl;
  }

  // variables debut
  double dotmin_merge_surface = 0.98;
  double distmin_merge_surface = 1e-1;
  // variables fin

  // on merge alors les surfaces tangentes
  if ( _opts->brep_topo )
    surface_merging ( dotmin_merge_surface, distmin_merge_surface );

  _hes->set_stack_number ( get_entity_manager()->face_size() );

  // remplissage des aretes intersectees
  for ( int i = 0; i<tetra_size(); i++ )
  {
    LTetra *t = get_tetra ( i );
    for ( int j = 0; j < 6; j++ )
    {
      int s = crossing_surf ( t, j );
      if ( s != -1 )
      {
        hashEdgeKey *k = _hes->addEdge ( t, j, s );
      }
    }
  }
}

#endif
