#include "select_vertex_lasso_tool.h"
#include <QMouseEvent>
#include <QPainter>
#include "paint_canvas.h"
#include "../geometry/point_set.h"


namespace Tl {
	SelectVertexLassoTool::SelectVertexLassoTool(PaintCanvas* canvas) 
		: Tool3D(canvas)
		, drawing_(false)
		, finished_(true)
	{

	}


	void SelectVertexLassoTool::press(QMouseEvent *e) {
		if (e->button() == Qt::LeftButton)
			left_button_down_ = true;
		if (e->button() == Qt::RightButton)
			right_button_down_ = true;

		drawing_ = true;
		finished_ = false;

		stroke_.clear();
		QPoint p = e->pos();
		stroke_.push_back(Point2f(p.x(), p.y()));
	}

	void SelectVertexLassoTool::move(QMouseEvent *e)  {
		if (drawing_ && (!finished_) && (left_button_down_ || right_button_down_)) {
			QPoint p = e->pos();
			stroke_.push_back(Point2f(p.x(), p.y()));

			canvas()->updateGL();
		}
	}

	void SelectVertexLassoTool::release(QMouseEvent *e)  {
		if (drawing_ && !finished_) {
			drawing_ = false;
			finished_ = true;

			//////////////////////////////////////////////////////////////////////////
			
			process_selection();
		}
		
		stroke_.clear();
		canvas()->updateCanvas();
	}

	void SelectVertexLassoTool::draw() const  {
		draw_stroke_using_opengl();
	}

	void SelectVertexLassoTool::draw_stroke_using_opengl() const {
		canvas()->startScreenCoordinatesSystem();

		glDisable(GL_LIGHTING);

		glLineWidth(2.0f);
		glPointSize(2.0f);

		if (left_button_down_)
			glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
		else
			glColor4f(1.0f, 0.0f, 0.0f, 1.0f);

		//////////////////////////////////////////////////////////////////////////

		// draw the strokes that have been finished.
		if (stroke_.size() > 1){
			glBegin(GL_LINE_STRIP);
			for (unsigned int j=0; j<stroke_.size(); ++j) {
				const Point2f& p = stroke_[j];
				glVertex2f(p.x(), p.y());
			}
			glEnd();
		}

		// make the polygon closed
		if (stroke_.size() >= 3) {
			const Point2f& p = stroke_.front();
			const Point2f& q = stroke_.back();
			glBegin(GL_LINES);
				glVertex2f(p.x(), p.y());
				glVertex2f(q.x(), q.y());
			glEnd();
		}
		
		//////////////////////////////////////////////////////////////////////////
		// fill the joint gap 

		glBegin(GL_POINTS);
		for (unsigned int j=0; j<stroke_.size(); ++j) {
			const Point2f& p = stroke_[j];
			glVertex2f(p.x(), p.y());
		}
		glEnd();

		//////////////////////////////////////////////////////////////////////////

		glEnable(GL_LIGHTING);
		canvas()->stopScreenCoordinatesSystem();
	}


	void SelectVertexLassoTool::reset() {
		stroke_.clear();
	}


	void SelectVertexLassoTool::process_selection() 
	{
		PointSet* pset = canvas_->pointSet();
		if (pset == nil)
			return;

		if (stroke_.size() < 3)
			return;

		Bbox2f box = Global::bbox_of(stroke_);
		float minX = box.xmin();
		float maxX = box.xmax();
		float minY = box.ymin();
		float maxY = box.ymax();

		Vertex** vts = pset->vertices();
		unsigned int num = pset->nb_vertices();

		for (unsigned int i=0; i<num; ++i) {
			Vertex* v = vts[i];
			Point2f p = canvas_->projectionOf(v->point());
			float x = p.x();
			float y = p.y();
			if (x >= minX && x <= maxX && y >= minY && y <= maxY) {
				if (Global::is_point_in_polygon(p, stroke_)) {
					v->set_selected(true);
//					std::cout << "Selected vertex index: " << v->index() << std::endl;
				}
			}
		}

		canvas_->updateCanvas();
	}

}

