// Vorosweep - Copyright (C) 2010-2014 T. Mouton
//
// See the LICENSE.txt file for license information. Please report all
// bugs and problems to <thibaud.mouton@gmail.com>.

#include "vorosweep.h"
#include "border.h"

using namespace vorosweep;

void Graph::handle_edge_bordercrash ( Event *ev )
{
  SweepEdge *se = ev->get_sweepedge();

  if ( se->is_stopped() )
    return;

  Border *bo = ev->get_border();
  bo->print();

  Grid1d *bordergrid = bo->get_grid();
  dbgprintf ( 5, "--> border crash\n" );
  double time = ev->get_time();

  if ( se->is_init() ) // case sweepedge is init : generate 1 or 2 edges
  {    
    se->update_current ( time );  
    int bgid = bordergrid->get_index ( se->get_current()->p );

    dbgprintf (2, "bgid --> %d / %d\n", bgid, bordergrid->get_bucket_size ( ) );

    // in case the point is out of border bounds
    if ( bgid < bo->get_first_bucket_index ( ) || bgid > bo->get_last_bucket_index ( ) )
    {
      add_earliest_event ( se );
      return;
    }

    se->set_stopped();

    for ( int i = 0; i < 2; i++ )
    {
      SweepFacet *sf = se->get_sweepfacet ( i );
//       printf ( "sf --> %p\n", sf );
      if ( sf )
      {
        sf->print();
        // compute new directions
        double ndir[3];
        if ( i == 1 )
          geom::cross_product3d ( sf->get_plane(), bo->get_plane(), ndir );
        else
          geom::cross_product3d ( bo->get_plane(), sf->get_plane(), ndir );
        geom::normalize3d ( ndir );
        dbgprintf ( 2, "new dir --> %lf %lf %lf\n", ndir[0], ndir[1], ndir[2] );
        if ( ndir[2] >= 0.0 )
        {
          BorderSweepEdge *nse = new BorderSweepEdge ( se->get_current(), ndir, time );
          nse->set_border ( bo );
          nse->update_speeds ( sf );
          FrontLine *fl = sf->get_frontline();
          fl->update_sweepedge ( se, nse );

          Event *ne = econtainer->get();
          ne->init ( nse, bo, nse->get_start()->p, time, Event::NEWBORDEREDGESWITCH, bgid );
          add_priority_event ( ne );
          // add also switch event in grid for facet switch
          int gid = bucketgrid->get_index ( nse->get_start()->p );
          Event *next = next_edgeswitch ( nse, nse->get_start()->p, gid );
          dbgprintf ( 5, "--> next switch event add :\n" );
          add_event ( next );

//           std::list<SweepEdge *> nlist = fl->get_edges();
//           for ( std::list<SweepEdge *>::iterator itn = nlist.begin(); itn != nlist.end(); itn++ )
//             dbgprintf ( 2, "se --> %p : start %p -- current %p, stopped ? %d\n", ( *itn ), ( *itn )->get_start(), ( *itn )->get_current(), ( *itn )->is_stopped() );
        }
        else
        {
          dbgprintf ( 2, "--> closing border front \n" );
          Front *fr = se->get_front ( i );
          if ( fr )
          {
            SweepEdge *secomp = fr->get_sweepedge ( i );
            se->merge_current ( secomp, get_time() );
            // close the front
            FrontLine *cfl = fr->get_frontline();
            cfl->close_front ( fr );
            secomp->set_stopped();
          }
        }
      }
    }
  }
  else // merge other edges
  {
    for ( int i = 0; i < 2; i++ )
    {
      Front *fr = se->get_front ( i );
      if ( fr )
      {
        SweepEdge *secomp = fr->get_sweepedge ( i );
        se->merge_current ( secomp, get_time() );
        // close the front
        FrontLine *cfl = fr->get_frontline();
        cfl->close_front ( fr );
        secomp->set_stopped();
      }
    }
  }
  se->set_stopped();
}
