/****************************************************************************
* MeshLab                                                           o o     *
* A versatile mesh processing toolbox                             o     o   *
*                                                                _   O  _   *
* Copyright(C) 2005                                                \/)\/    *
* Visual Computing Lab                                            /\/|      *
* ISTI - Italian National Research Council                           |      *
*                                                                    \      *
* All rights reserved.                                                      *
*                                                                           *
* This program is free software; you can redistribute it and/or modify      *
* it under the terms of the GNU General Public License as published by      *
* the Free Software Foundation; either version 2 of the License, or         *
* (at your option) any later version.                                       *
*                                                                           *
* This program is distributed in the hope that it will be useful,           *
* but WITHOUT ANY WARRANTY; without even the implied warranty of            *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
* for more details.                                                         *
*                                                                           *
****************************************************************************/

#ifndef EXTRADECORATEPLUGIN_H
#define EXTRADECORATEPLUGIN_H

#include <common/plugins/interfaces/decorate_plugin.h>
#include <common/ml_shared_data_context/ml_shared_data_context.h>

#include <wrap/gui/coordinateframe.h>
#include "colorhistogram.h"

class QGLShaderProgram;
typedef vcg::ColorHistogram<float>  CHist;

typedef std::pair<Point3m,vcg::Color4b> PointPC; // this type is used to have a simple coord+color pair to rapidly draw non manifold faces

class DecorateBasePlugin : public QObject, public DecoratePlugin
{
	Q_OBJECT
	MESHLAB_PLUGIN_IID_EXPORTER(DECORATE_PLUGIN_IID)
	Q_INTERFACES(DecoratePlugin)
	QString decorationName(ActionIDType filter) const;
	QString decorationInfo(ActionIDType filter) const;
	QString pluginName() const;
	
	enum {
		DP_SHOW_AXIS,
		DP_SHOW_BOX_CORNERS,
		DP_SHOW_SELECTED_MESH,
		DP_SHOW_CAMERA,
		DP_SHOW_NORMALS,
		DP_SHOW_TEXPARAM,
		DP_SHOW_VERT_QUALITY_HISTOGRAM,
		DP_SHOW_FACE_QUALITY_HISTOGRAM,
		DP_SHOW_QUALITY_CONTOUR,
		DP_SHOW_CURVATURE,
		DP_SHOW_LABEL,
	};
	
	float niceRound2(float value,float base);
	float niceRound(float value);
	
	void	drawQuotedLine(const vcg::Point3d &a,const vcg::Point3d &b,float aVal, float bVal,float tickDist,QPainter *painter, QFont qf,float angle =0,bool rightAlign=false);
	void drawHistogram(QGLWidget *gla, CHist &ch);
	
	vcg::Color4b textColor;
public:
	
	DecorateBasePlugin()
	{
		typeList <<
					DP_SHOW_AXIS <<
					DP_SHOW_BOX_CORNERS <<
					DP_SHOW_SELECTED_MESH <<
					DP_SHOW_CAMERA << 
					DP_SHOW_NORMALS <<
					DP_SHOW_TEXPARAM << 
					DP_SHOW_VERT_QUALITY_HISTOGRAM <<
					DP_SHOW_FACE_QUALITY_HISTOGRAM <<
					DP_SHOW_QUALITY_CONTOUR <<
					DP_SHOW_CURVATURE <<
					DP_SHOW_LABEL;
		
		ActionIDType tt;
		foreach(tt , types())
		{
			actionList << new QAction(decorationName(tt), this);
			/*if(tt==DP_SHOW_SELECTED_VERT)        actionList.last()->setIcon(QIcon(":/images/selected_vert.png"));
	  if(tt==DP_SHOW_SELECTED_FACE)        actionList.last()->setIcon(QIcon(":/images/selected_face.png"));*/
			if(tt==DP_SHOW_AXIS)                 actionList.last()->setIcon(QIcon(":/images/show_axis.png"));
		}
		
		QAction *ap;
		foreach(ap,actionList){
			ap->setCheckable(true);
		}
		
	}
	
	void DrawBBoxCorner(MeshModel &m, bool absBBoxFlag=true);
	void DrawVertLabel(MeshModel &m, QPainter *gla);
	void DrawEdgeLabel(MeshModel &m, QPainter *gla);
	void DrawFaceLabel(MeshModel &m, QPainter *gla);
	void DisplayCamera(QString who, const Shotm& ls, int cameraSourceId);
	void DrawCamera(const MeshModel* m, const Shotm& ls, vcg::Color4b camcolor, Matrix44m &currtr, const RichParameterList *rm, QPainter *painter, QFont qf);
	void PlaceTexParam(int TexInd, int TexNum);
	void DrawTexParam(MeshModel &m, GLArea *gla, QPainter *painter, const RichParameterList*, QFont qf);
	void DrawColorHistogram(CHist &ch, GLArea *gla, QPainter *painter, const RichParameterList*, QFont qf, bool perVertex);
	void DrawLineVector(std::vector<PointPC> &EV);
	//void DrawTriVector(std::vector<PointPC> &EV);
	//void DrawDotVector(std::vector<PointPC> &EV, float basesize=4.0);
	
	
	
	void decorateDoc(const QAction *a, MeshDocument &md, const RichParameterList *, GLArea *gla, QPainter *painter, GLLogStream &_log);
	void decorateMesh(const QAction *a, MeshModel &md, const RichParameterList *, GLArea *gla, QPainter *painter, GLLogStream &_log);
	bool startDecorate(const QAction* /*mode*/, MeshModel &/*m*/, const RichParameterList *, GLArea * /*parent*/);
	void endDecorate(const QAction* /*mode*/, MeshModel &/*m*/, const RichParameterList *, GLArea * /*parent*/);
	bool startDecorate(const QAction * /*mode*/, MeshDocument &/*m*/, const RichParameterList *, GLArea * /*parent*/);
	bool isDecorationApplicable(const QAction *action, const MeshModel& m, QString &ErrorMessage) const;
	int getDecorationClass(const QAction* /*action*/) const;
	void initGlobalParameterList(const QAction *, RichParameterList &/*globalparam*/);
	
	inline QString CameraScaleParam() const    { return  "MeshLab::Decoration::CameraRenderScaleType" ; }
	inline QString FixedScaleParam() const     { return  "MeshLab::Decoration::CameraFixedScaleParam" ; }
	
	inline QString ShowCameraDetails() const     { return  "MeshLab::Decoration::CameraShowCameraDetails" ; }
	inline QString ApplyMeshTr() const { return  "MeshLab::Decoration::ApplyMeshTr"; }
	inline QString ShowMeshCameras() const     { return  "MeshLab::Decoration::ShowMeshCameras" ; }
	inline QString ShowRasterCameras() const   { return  "MeshLab::Decoration::ShowRasterCameras" ; }
	
	inline QString ShowNonRegular() const     { return  "MeshLab::Decoration::ShowNonRegular" ; }
	inline QString ShowSeparatrix() const     { return  "MeshLab::Decoration::ShowSeparatrix" ; }
	inline QString ShowBorderFlag() const     { return  "MeshLab::Decoration::ShowBorderFlag" ; }
	inline QString ShowPerVertexCurvature() const     { return  "MeshLab::Decoration::ShowPerVertexCurvature" ; }
	inline QString ShowPerFaceCurvature() const     { return  "MeshLab::Decoration::ShowPerFaceCurvature" ; }
	inline QString CurvatureLength() const { return  "MeshLab::Decoration::CurvatureLength" ; }
	inline QString CurvatureScaling() const { return  "MeshLab::Decoration::CurvatureScaling" ; }
	
	inline QString TextureStyleParam() const   { return  "MeshLab::Decoration::TextureStyle" ; }
	inline QString TextureFaceColorParam() const   { return  "MeshLab::Decoration::TextureFaceColor" ; }
	inline QString TextureIndexParam() const   { return  "MeshLab::Decoration::TextureIndex"; }
	inline QString VertDotSizeParam() const    { return  "MeshLab::Decoration::VertDotSize" ; }
	
	inline QString perVertexHistBinNumParam() const     { return  "MeshLab::Decoration::PerVertexHistBinNumParam" ; }
	inline QString perFaceHistBinNumParam() const     { return  "MeshLab::Decoration::PerFaceHistBinNumParam" ; }
	inline QString perVertexHistFixedParam() const   { return  "MeshLab::Decoration::PerVertexUseFixedHistParam" ; }
	inline QString perFaceHistFixedParam() const   { return  "MeshLab::Decoration::PerFaceUseFixedHistParam" ; }
	inline QString perVertexHistFixedMinParam() const   { return  "MeshLab::Decoration::PerVertexFixedHistMinParam" ; }
	inline QString perFaceHistFixedMinParam() const   { return  "MeshLab::Decoration::PerFaceFixedHistMinParam" ; }
	inline QString perVertexHistFixedMaxParam() const   { return  "MeshLab::Decoration::PerVertexFixedHistMaxParam" ; }
	inline QString perFaceHistFixedMaxParam() const   { return  "MeshLab::Decoration::PerFaceFixedHistMaxParam" ; }
	inline QString perVertexHistFixedWidthParam() const { return  "MeshLab::Decoration::PerVertexFixedHistWidthParam" ; }
	inline QString perFaceHistFixedWidthParam() const { return  "MeshLab::Decoration::PerFaceFixedHistWidthParam" ; }
	inline QString perVertexHistAreaParam() const { return  "MeshLab::Decoration::PerVertexAreaHistParam" ; }
	inline QString perFaceHistAreaParam() const { return  "MeshLab::Decoration::PerFaceAreaHistParam" ; }
	inline QString perVertexHistFontSize() const { return "MeshLab::Decoration::PerVertexHistFontSize" ; }
	inline QString perFaceHistFontSize() const { return "MeshLab::Decoration::PerFaceHistFontSize" ; }

	inline QString TextColorParam() const { return  "MeshLab::Decoration::TextColor" ; }
	
	inline QString ShowFauxEdgeWidth() const { return  "MeshLab::Decoration::FauxEdgeWidth" ; }
	inline QString ShowFauxEdgeColor() const { return  "MeshLab::Decoration::FauxEdgeColor" ; }
	
	
	inline QString ShowContourFreq() const { return  "MeshLab::Decoration::ShowContourFreq" ; }
	inline QString ShowContourAlpha() const { return  "MeshLab::Decoration::ShowContourAlpha" ; }
	inline QString ShowContourWidth() const { return  "MeshLab::Decoration::ShowContourWidth" ; }
	inline QString ShowContourRamp() const { return  "MeshLab::Decoration::ShowContourRamp" ; }
	inline QString ShowContourColorMap() const { return  "MeshLab::Decoration::ShowContourColorMap" ; }
	
	inline QString LabelVertFlag() const { return  "MeshLab::Decoration::LabelVertFlag" ; }
	inline QString LabelEdgeFlag() const { return  "MeshLab::Decoration::LabelEdgeFlag" ; }
	inline QString LabelFaceFlag() const { return  "MeshLab::Decoration::LabelFaceFlag" ; }
	
	inline QString NormalLength() const { return  "MeshLab::Decoration::NormalLength" ; }
	inline QString NormalWidth() const { return  "MeshLab::Decoration::NormalWidth" ; }
	inline QString NormalVertColor() const { return  "MeshLab::Decoration::NormalVertColor" ; }
	inline QString NormalFaceColor() const { return  "MeshLab::Decoration::NormalFaceColor" ; }
	inline QString NormalSelection() const { return  "MeshLab::Decoration::NormalSelection"; }
	inline QString NormalVertFlag() const { return  "MeshLab::Decoration::NormalVertFlag" ; }
	inline QString NormalFaceFlag() const { return  "MeshLab::Decoration::NormalFaceFlag" ; }
	
	inline QString BBAbsParam() const { return  "MeshLab::Decoration::BBAbs" ; }
	
	inline QString selectedMeshBlendingColor() const { return  "MeshLab::Decoration::MeshBlendingColor" ; }
	
signals:
	void askViewerShot(QString);
	
public slots:
	void  setValue(QString name, vcg::Shotf val);
	
private:
	vcg::Shotf curShot;
	
	QMap<MeshModel *, QGLShaderProgram *> contourShaderProgramMap;
};

#endif
