#include <cassert>
using namespace std;

#include <print.h>

#include <simplexface.h>
#include <d3tess.h>
#include <d3fan2.h>

d3fan2::d3fan2( d3tess & _tess )
  : tess(_tess)
{
}


void d3fan2::addspike()
{
  uint index = tess.vi.size();
  tess.vi.push_back( simplexD2linked() );
  simplexD2linked & ti(tess.vi[index]);
  simplexD2linked const & x(tess.cpsimplex());

  virtualtriangle const & vs(tess.vs);

  simplexface cpf = tess.cpsimplexfaceget();

  ti.pi[0] = x.pi[ vs.v[1] ];
  ti.pi[1] = x.pi[ vs.v[0] ];
  ti.pi[2] = w;
  ti.ni[2] = cpf.id;

  vft.push_back(cpf);

}

void d3fan2::traverseleft(simplexface const prev)
{
  tess.surfaceleft();
  if (tess.surfaceviewable(w)==false)
    return;

  // k refers to the newely constructed triangle.
  uintc k = tess.vi.size();

  addspike();
  tess.vi[k].ni[1] = prev.id;
  tess.vi[prev.id].ni[prev.face] = k;
  
  traverseleft(simplexface(k,0));
}

void d3fan2::traverseright(simplexface const prev)
{
  tess.surfaceright();
  if (tess.surfaceviewable(w)==false)
    return;

  // k refers to the newely constructed triangle.
  uintc k = tess.vi.size();

  addspike();
  tess.vi[k].ni[0] = prev.id;
  tess.vi[prev.id].ni[prev.face] = k;
  
  traverseright(simplexface(k,1));
}

void d3fan2::eval(uintc _w )
{
  w = _w;

//  {
//    MessageGlobal mg;
//    mg() << "SHOW(w)" << endl;
//    mg() << tess << endl << endl;
//  }

  tess.debugcheck();

  assert(tess.surfaceviewable(w));

  vft.clear();

  vk = tess.vi.size();

  addspike();

  //Preserve the virtual triangle
  virtualtriangle vs0 = tess.vs;
  uint cp0 = tess.cp;

  traverseleft(simplexface(vk,0));

  // Restore starting position.
  tess.vs = vs0;
  tess.cp = cp0;

  traverseright(simplexface(vk,1));

  // Reconnect triangles.
  uint sz = vft.size();
  for (uint i=0; i<sz; ++i)
    tess.vi[vft[i].id].ni[vft[i].face] = vk + i;

  // Minimize
  for (uint i=0; i<sz; ++i)
    tess.minimizer->eval(vft[i].id,vk+i);

  assert(sz == tess.vi.size()-vk);
  tess.debugcheck();
  
}





