/*
 * Copyright (c) 2015 Tricoire Sebastien 3dsman@free.fr
 *
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 * claim that you wrote the original software. If you use this software
 * in a product, an acknowledgment in the product documentation would be
 * appreciated but is not required.
 * 2. Altered source versions must be plainly marked as such, and must not be
 * misrepresented as being the original software.
 * 3. This notice may not be removed or altered from any source distribution.
 *
 */

#pragma once

#include <qopenglwidget.h>
#include <QOpenGLFunctions_2_0>

#include "OE_utils.h"
#include <stdint.h>
#include <vector>
#include <QDropEvent>
#include "OE_document.h"
#include "curves/OE_joincurve.h"
#include "curves/OE_subcurve.h"
#include "stitchs/OE_fillstitch.h"

static const GLuint TOOLSSELID = 0;
static const GLuint STITCHSSELID  = 1;
static const GLuint CURVESSELID = 2;

static const GLuint ZEROID  = 0;
static const GLuint TRANSTOOLID = 1;
static const GLuint MOVETOOLID = 0;
static const GLuint SCALETOOLID = 1;

class OE_controller;

class OE_display : public QOpenGLWidget, protected QOpenGLFunctions_2_0
{
	public:
		class OE_displayStyle
		{
			public:
				//OE_Color hoopColor = OE_Color(0.0, 0.0, 0.0, .5);
				OE_color hoopColor = OE_color(0.0, 0.0, 0.0, .5);
				OE_color backgroundColor = OE_color(0.85, 0.85, 0.85, 1.0);
				OE_color cursorColor = OE_color(0.0, 0.0, 0.0, 0.3);
				OE_color gridColor = OE_color(0.0, 0.0, 0.0, 0.1);
				OE_color zeroColor = OE_color(0.0, 0.0, 0.0, 1.0);
				float zeroSize = 3;

				OE_color curveColor = OE_color(0,.63,.75,1.0);
				OE_color curveTangeantColor = OE_color(.39,.235,.36,1.0);
				OE_color curvePointColor = OE_color(.39,.235,.36,1.0);
				OE_color curveControlsColor = OE_color(.78,0,0,1.0);

				float curveWidth = 1.5;
				float curveTangeantWidth = 1.5;
				float curvePointSize = 3.0;
				float curveStartPointSize = 5.0;

				OE_color stitchLineBeforeCurrentColor = OE_color(.08,.08,.08,1.0);
				OE_color stitchLineAfterCurrentColor = OE_color(.08,.08,.08,1.0);
				OE_color stitchPointBeforeCurrentColor = OE_color(.08,.08,.08,1.0);
				OE_color stitchPointAfterCurrentColor = OE_color(.08,.08,.08,1.0);
				OE_color stitchStartPointColor = OE_color(.39,.235,.36,1.0);
				OE_color stitchControlsColor = OE_color(.78,0,0,1.0);

				float stitchPointSize = 3.0;
				float stitchLineWidth = 1.5;
				float stitchStartPointSize = 5.0;

				OE_color instLineBeforeCurrentColor = OE_color(0,.63,.75,.3);
				OE_color instLineAfterCurrentColor = OE_color(0,.63,.75,1.0);
				OE_color instStartPointColor = OE_color(.39,.23,.36,1.0);
				OE_color instCurPointColor = OE_color(.78,.2,.2,1.0);
				OE_color instColor = OE_color(.39,.23,.36,1.0);
				float instPointSize = 3.0;
				float instLineWidth = 1.5;
				float instStartPointSize = 5.0;
				float instCurPointSize = 5.0;

				OE_color machineStartPointColor;
				OE_color machineCurPointColor;

				OE_color transformGizmoColor = OE_color(1,0,0,1);
				OE_color selectionBoundColor = OE_color(1,0,0,1);

				bool drawHoop = true;
				bool drawGrid = true;
				bool drawZero = true;

				bool drawCurves = true;
				bool drawCurvePoints = false;
				bool drawCurveControls = true;

				bool drawStitches = true;
				bool drawStitchControl = true;

				bool drawCommands = false;
				bool selectCurves = true;
				bool selectStitches = true;

				float moveCrossSize = 30;

				OE_displayStyle(){}
		};

		/** Default constructor */
		OE_display(QWidget* parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags());
		/** Default destructor */
		virtual ~OE_display();

		virtual void mouseMoveEvent(QMouseEvent* event) final;
		virtual void mousePressEvent(QMouseEvent* event) final;
		virtual void mouseReleaseEvent(QMouseEvent* event) final;
		virtual void wheelEvent(QWheelEvent* event) final;
		virtual void keyPressEvent(QKeyEvent* event) final;
		virtual void keyReleaseEvent(QKeyEvent* event) final;
		virtual void dragEnterEvent(QDragEnterEvent *event) final;
		virtual void dropEvent(QDropEvent *event) final;

		void loadFile(std::string file); // TODO put it elsewhere

		virtual void initializeGL() Q_DECL_OVERRIDE;
		virtual void resizeGL(int, int) Q_DECL_OVERRIDE;
		virtual void paintGL() Q_DECL_OVERRIDE;

		virtual bool setDocument(OE_document* document);
		virtual bool setController(OE_controller* controller);
		virtual bool setDisplayStyle(OE_displayStyle* style);

		virtual bool mouse_Pos(double x, double y);
		virtual bool mouse_Button(QMouseEvent* event);
		virtual void scroll(double xoffset, double yoffset);
		virtual void resize(int width, int height);
		virtual void key(QKeyEvent* event);

		vector_2d screenToDocument(vector_2d pos);

		void pick(std::list<OE_pointcurve*> selectedCurves, std::list<OE_stitchs*> selectedStitches);

		//void drawframe();
		bool refreshAll();

		void drawTriangle(vector_2d point1, vector_2d point2, float size);
		bool drawSelectionTools(bool select=false);

		bool drawCurve(OE_curve* curve);
		bool drawStitch(OE_stitchs* stitch, int curpoint);
		bool drawCurveControl(OE_curve* curve, bool select=false);
		bool drawStitchControl(OE_stitchs* stitch, bool select=false);
		void drawJoincurveControl(OE_joincurve* curve, bool select, int index=0);
		void drawFillstitchControl(OE_fillstitch* fillstitch, bool select);
		bool drawCommands();

		virtual bool draw();
		virtual void showAll();
		virtual void zoomSelection();

		vector_2d viewPos;
		vector_2d absMouse;
		float zoom;
		vector_2d mouse;
		vector_2d mouseInit;
		bool pan;
		int width, height;
		OE_displayStyle* style = NULL;

	protected:

		static const float moveCrossSize;

		bool changeDpi = true;

		/** \brief is displaying controls. */
		bool controls = false;

		BoundingBox selectionBounds;

		OE_curve* selectedCurve = nullptr;
		OE_stitchs* selectedStitch = nullptr;

		OE_document * document = NULL;
		OE_controller* controller = NULL;

};
