/***************************** LICENSE START ***********************************

 Copyright 2012 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#ifndef MvQMagnifier_H
#define MvQMagnifier_H

#include <vector>

#include <QGraphicsWidget>
#include <QPen>

#include "MvQPlotItem.h"

class QImage;
class QPainter;
class QPixmap;

class MgQMagnifierLayoutItem;

using namespace std;

class MvQMagnifierFactorCell
{
public:
	MvQMagnifierFactorCell(float value, QColor colour) :
			value_(value), colour_(colour) {};
	float value_;
	QColor colour_;
};


class MvQMagnifierSlider
{
public:
	MvQMagnifierSlider(QList<float> &, int,QColor);
	void    setGeometry(float);

	float cellSweepAngle() {return cellSweepAngle_;}
	float cellInnerRadius() {return cellInnerRadius_;}
	float cellOuterRadius() {return cellOuterRadius_;}

	const  MvQMagnifierFactorCell* cell(int i) const {return cells_[i];}
	float   factorValue(int i) {return cells_.at(i)->value_;}
	QColor& cellColour(int i) {return cells_.at(i)->colour_;}
	float  actFactorValue() {return cells_.at(actCellIndex_)->value_;}
	int    cellNum() {return cells_.count();}
	float  cellBarStartAngle() {return cellBarStartAngle_;}
	float  cellBarSweepAngle() {return cellBarSweepAngle_;}

	float panelInnerRadius() {return panelInnerRadius_;}
	float panelOuterRadius() {return panelOuterRadius_;}

	int   actCellIndex() {return actCellIndex_;}
	void  setActCellIndex(int i) {actCellIndex_=i;}
	float actCellAngle();

	bool  checkPointInHandler(float,float);
	bool  checkPointInCell(float,float,int&);
	bool  checkPointInPanel(float,float);

	float handlerSize() {return handlerSize_;}
	void  setHandlerSize(float s) {handlerSize_=s;}
	bool  shiftHandler(float, float,int &);
	void  handlerCentre(float &, float &);

public:
	float radius_;
	float actCellIndex_;
	float handlerSize_;

	//Cell item
	float   cellSweepAngle_;	
	float   cellWidth_;	
	float   cellHeight_;
	float   cellInnerRadius_;
	float   cellOuterRadius_;
	QPen    cellPen_;
		
	//All the cells
	float 	cellBarStartAngle_;
	float 	cellBarEndAngle_;
	float cellBarSweepAngle_;
	QList<MvQMagnifierFactorCell*> cells_;
	
	//Panel
	QPen 	panelPen_;
	float 	panelWidth_;
	float   panelInnerRadius_;
	float   panelOuterRadius_;
};


class MagnifierFrameData
{
public:
	MagnifierFrameData(float,float, float, int);
	bool checkRadius(float r) { return r>=minRadius_ && r< maxRadius_;};
	
	float width_;
	float minRadius_;
	float maxRadius_;
	vector<float> coeffCos_;
	vector<float> coeffSin_;
	int ptNum_;	
};


class MvQMagnifier : public MvQPlotItem
{
  
Q_OBJECT

public:
	enum MagnifierAction {NoAction, MoveAction, ResizeAction, HandlerAction};
	enum ScenePointType {InnerScenePoint,CoveredScenePoint,OuterScenePoint};

	MvQMagnifier(MgQPlotScene*,MvQPlotView*,QGraphicsItem *parent=0);
	~MvQMagnifier();

	void paint(QPainter *, const QStyleOptionGraphicsItem*, QWidget*);
	QRectF boundingRect() const;
	bool contains ( const QPointF & ) const; 

	void render(QPainter *painter);	

	void setActivated(bool);
	void prepareForReset();
	void reset();
	//void operationBegin();
	//void operationEnd();
	MagnifierAction magnifierAction() {return magnifierAction_;}
	float zoomFactor() {return actSlider_->actFactorValue();}
	bool checkPointInMagnifier(const QPointF&);
	ScenePointType identifyScenePoint(const QPointF&);
	QPointF	sceneToMagnifiedPos(const QPointF&);
	QPointF	magnifiedToScenePos(const QPointF&);
	
	void mousePressEventFromView(QMouseEvent*);
	void mouseMoveEventFromView(QMouseEvent*);	
	void mouseReleaseEventFromView(QMouseEvent*);

signals:
	void factorChanged();   
	void positionChanged();    
	
private:
	enum MagnifierPointType {LensPoint,FramePoint,SliderHandlerPoint,SliderCellPoint,OuterPoint};
	enum MagnifierMode {TextMode, DataMode };

	bool checkPointInWindow(const float,const float) const;	
	bool checkCircleInWindow(const float,const float,const float) const;
	
	bool checkPointInMagnifier(const int, const int);
	MagnifierPointType identifyPoint(const QPointF&);

	void renderFrame(QPainter *);
	void renderSlider(QPainter*);

	void createRing(QPainterPath&,float,float);
	void createRingSlice(QPainterPath&,float,float,float,float);

	void changeMagnifierMode();
	void updateMagnifierState();
	//bool calcPowerScaleForData();

	float radius_;
	float minRadius_;

	MagnifierMode magnifierMode_;
	MagnifierAction magnifierAction_;
	MvQMagnifierSlider* actSlider_;
	QMap<MagnifierMode,MvQMagnifierSlider*> sliders_;
	int actCellIndexAtHandlerActionStart_;

	int actFrameIndex_;
	vector<MagnifierFrameData> frames_;
	
	QPointF dragPos_;
	
	float centreX_;
	float centreY_;
		
	int minX_;
	int maxX_;
	int minY_;
	int maxY_;
	
	int refX_;
	int refY_;
	
	int prevX_;
	int prevY_;
	
	float innerFrameWidth_;
	float outerFrameWidth_;
	float frameWidth_;

	bool pointInMagnifier_;	
	
	QGraphicsScene* dataScene_;
	MgQMagnifierLayoutItem* dataItem_;
	QImage* device_;
	QPainter *painter_;

	bool magnifierModeChanged_;

	QPixmap *handlerPixmap_;

	bool mouseInLens_;
};


#endif
