#include <CGAL/Cartesian.h>
#include <CGAL/Point_2.h>
#include <CGAL/Delaunay_triangulation_2.h>
#include <CGAL/IO/Qt_widget_Delaunay_triangulation_2.h>
#include <CGAL/IO/Qt_widget.h>
#include <CGAL/IO/Qt_widget_layer.h>
#include <qapplication.h>

typedef CGAL::Cartesian<double>		    Rep;
typedef CGAL::Point_2<Rep>		    Point;
typedef CGAL::Circle_2<Rep>		    Circle;
typedef CGAL::Delaunay_triangulation_2<Rep> Delaunay;
typedef Delaunay::Vertex_handle             VertexH;
typedef Delaunay::Vertex_circulator         VCirculator;

class Dist_order {
  const Delaunay *t;
  const Point *p;

public:
  Dist_order(const Delaunay *tr, const Point *po)
    : t(tr), p(po) {}

  bool operator()(VertexH v1, VertexH v2) const 
  {
    return CGAL::compare_distance_to_point(*p, v1->point(), v2->point())
           == CGAL::SMALLER;
  }
};

typedef  std::set<VertexH, Dist_order> Queue;


/////////////////////////////////////////////////////////
//  The displayed objects are declared here as global variables.
//  The display code is the "draw" member function below.

Delaunay         dt;
Point            the_point=Point();
Queue            queue(Dist_order(&dt, &the_point));
Queue::iterator  all_neighbors;
Point            the_neighbor;

class My_layer : public CGAL::Qt_widget_layer {
  void draw() {
    *widget << CGAL::RED << dt << CGAL::PointSize(6) << CGAL::BLUE << the_point;

    if (dt.number_of_vertices() < 2) return;
    if (the_neighbor == Point() ) return;

    *widget << CGAL::YELLOW 
	    << Circle(the_point, CGAL::squared_distance(the_point, the_neighbor))
	    << CGAL::GREEN << the_neighbor;
  }
};

class My_window : public CGAL::Qt_widget {
public:
  My_window(int x, int y)
  {
    resize(x,y);
    attach(&layer);
  }
private:
  //this method is called when the user presses the mouse
  void mousePressEvent(QMouseEvent *e)
  {
    Qt_widget::mousePressEvent(e);

    /////////////////////////////////////////////////////////////
    //  HERE IS WHAT IS EXECUTED ON A MOUSE CLICK !
    //
    if (e->button() == Qt::LeftButton) {
      dt.insert(Point(x_real(e->x()), y_real(e->y())));
      the_neighbor = Point();
      the_point = Point();
    }    
    if (e->button() == Qt::MidButton) {
      if (the_point == Point()) {
	std::cout << "no point to which find the neighbors !" << std::endl;
      } else if (all_neighbors == queue.end()) {
	std::cout << "it's finished !" << std::endl;
	the_neighbor = Point();
	the_point = Point();
      } else {
	VertexH v = *all_neighbors;
	the_neighbor = v->point();
	VCirculator circ = dt.incident_vertices(v), circDone = circ;
	do {
	  if (!dt.is_infinite(circ)) queue.insert(circ);
	  ++circ;
	} while (circ != circDone);
	++all_neighbors;
      }
    }
    if (e->button() == Qt::RightButton) {
      the_point =  Point(x_real(e->x()), y_real(e->y()));
      queue.clear();
      queue.insert(dt.nearest_vertex(the_point));
      all_neighbors = queue.begin();
      the_neighbor = Point();
    }
    /////////////////////////////////////////////////////////////

    redraw();
  }
  My_layer layer;
};

int main( int argc, char **argv )
{
    QApplication app( argc, argv );
    My_window *W = new My_window(400, 400);
    app.setMainWidget(W);
    W->show();
    W->set_window(0, 400, 0, 400);
    return app.exec();
}
