// 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 "event.h"
#include "sweepobject.h"

using namespace vorosweep;

const char *Event::eventtypename[] =
{
  "NEWBORDEREDGESWITCH",
  "NEWEDGESWITCH",
  "NEWFACETSWITCH",
  "NEWGENERATOR",
  "EDGE_EDGECRASH",
  "EDGE_FACETCRASH",
  "EDGE_BORDERCRASH",
  "FACET_BORDERCRASH",
  "EDGESWITCH",
  "FACETSWITCH",
  "BORDEREDGESWITCH"
};

// bool EventPtrComp::operator() ( const Event* a, const Event* b )
// {
//   if ( a->time < b->time )
//     return true;
//   else if ( a->time == b->time && a->so[0] < b->so[0] )
//     return true;
//   else if ( a->time == b->time && a->so[0] == b->so[0] && a->so[1] < b->so[1] )
//     return true;
//   else if ( a->time == b->time && a->so[0] == b->so[0] && a->so[1] == b->so[1] && a->cg < b->cg )
//     return true;
//   else
//     return false;
// }

bool EventPtrComp::operator() ( const Event* a, const Event* b )
{
  if ( a->time < b->time )
    return true;
  else if ( a->time == b->time && a->so[0] < b->so[0] )
    return true;
  // in case the time is the same as well as the sweepobject, then check the distance
  else if ( a->time == b->time && a->so[0] && a->so[0] == b->so[0] )
  {
    double *p = a->so[0]->get_start()->p;
    if ( geom::sqrtdistance2d ( p, a->p ) < geom::sqrtdistance2d ( p, b->p ) )
      return true;
    else
      return false;
  }
  ////////////////////////
  else if ( a->time == b->time && a->so[0] == b->so[0] && a->so[1] < b->so[1] )
    return true;
  else if ( a->time == b->time && a->so[0] == b->so[0] && a->so[1] == b->so[1] && a->cg < b->cg )
    return true;
  else
    return false;
}

Event::Event ()
{
  so[0] = so[1] = NULL;
  brd = NULL;
  cg = NULL;
  p[0] = p[1] = 0.0;
  time = 0.0;
  status = Event::ENABLE;
  gid = -1;
}

void Event::init ( SweepObject *s, double *pos, double t, eventtype what, int index_in_grid )
{
  so[0] = s;
  so[1] = NULL;
  brd = NULL;
  cg = NULL;
  p[0] = pos[0];
  p[1] = pos[1];
  time = t;
  type = what;
  gid = index_in_grid;
  so[0]->insert_event ( this );
  dbgprintf ( 1, "new : " );
  print();
}

void Event::init ( SweepObject *s0, SweepObject *s1, double *pos, double t, eventtype what, int index_in_grid )
{
  so[0] = s0;
  so[1] = s1;
  brd = NULL;
  cg = NULL;
  p[0] = pos[0];
  p[1] = pos[1];
  time = t;
  type = what;
  gid = index_in_grid;
  so[0]->insert_event ( this );
  so[1]->insert_event ( this );
  dbgprintf ( 1, "new : " );
  print();
//   getchar();
}

void Event::init ( SweepObject *s, Border *b, double *pos, double t, eventtype what, int index_in_grid )
{
  so[0] = s;
  so[1] = NULL;
  brd = b;
  cg = NULL;
  p[0] = pos[0];
  p[1] = pos[1];
  time = t;
  type = what;
  gid = index_in_grid;
  so[0]->insert_event ( this );
  dbgprintf ( 1, "new : " );
  print();
//   getchar();
}

void Event::init ( Convex_generator *g, double *pos, double t, eventtype what, int index_in_grid )
{
  so[0] = NULL;
  so[1] = NULL;
  brd = NULL;
  cg = g;
  p[0] = pos[0];
  p[1] = pos[1];
  time = t;
  type = what;
  gid = index_in_grid;
  dbgprintf ( 1, "new : " );
  print();
//   getchar();
}

SweepEdge *Event::get_sweepedge()
{
//   return dynamic_cast<SweepEdge*> ( so[0] );
  return reinterpret_cast<SweepEdge*> ( so[0] );
}
SweepFacet *Event::get_sweepfacet()
{
//   return dynamic_cast<SweepFacet*> ( so[0] );
  return reinterpret_cast<SweepFacet*> ( so[0] );
}
SweepEdge *Event::get_sweepedge ( int i )
{
//   return dynamic_cast<SweepEdge*> ( so[i] );
  return reinterpret_cast<SweepEdge*> ( so[i] );
}
SweepFacet *Event::get_sweepfacet ( int i )
{
//   return dynamic_cast<SweepFacet*> ( so[i] );
  return reinterpret_cast<SweepFacet*> ( so[i] );
}
void Event::print()
{
  dbgprintf ( 1, "event %p type %s", this, eventtypename[get_type() ] );
  if ( so[0] )
  {
    dbgprintf ( 1, " with object type %s : ", SweepObject::objectname[so[0]->get_type() ] );
    dbgprintf ( 1, "pos %lf %lf, dir %lf %lf, time %.10lf, bucket %d\n", p[0], p[1], so[0]->get_dir3d() [0], so[0]->get_dir3d() [1], time, gid );
  }
  else
  {
    dbgprintf ( 1, " with object type GENERATOR : pos %lf %lf, time %.20lf, bucket %d\n", p[0], p[1], time, gid );
  }
}

