#ifndef VisualizationKinectPLUGIN_H__
#define	VisualizationKinectPLUGIN_H__

#include "ritkApplicationPlugin.h"
#include "ritkRGBRImage.h"

#include "VisualizationKinectPlugin.h"
#include "VisualizationKinectWidget.h"

#include <itkImageRegionIterator.h>
#include <itkImageFileWriter.h>
#include <itkTriangleMeshToBinaryImageFilter.h>
#include <itkAntiAliasBinaryImageFilter.h>
#include <itkZeroCrossingImageFilter.h>
#include <itkRescaleIntensityImageFilter.h>

#include <itkMesh.h>
#include <itkTriangleCell.h>

class VisualizationKinectPlugin : public ritk::ApplicationPlugin
{
	Q_OBJECT

public:
	typedef ritk::RGBRImageUCF2					RImageType;
	typedef RImageType::Pointer					RImagePointer;
	typedef RImageType::ConstPointer			RImageConstPointer;	
	typedef vnl_vector_fixed<float,3> VF3;

	/// Constructor
	VisualizationKinectPlugin();
	/// Destructor
	~VisualizationKinectPlugin();

	/// Get the name @sa Plugin::GetName
	QString GetName();

	/// Get the plugins GUI @sa Plugin::GetPluginGUI
	QWidget *GetPluginGUI();

	/// Intercept the event.
	void ProcessEvent(ritk::Event::Pointer EventP);

signals:
	void UpdateGUI();

protected slots:
	void LoadConfigFromFile();

protected:

	// The current range data
	ritk::NewFrameEvent::RImageConstPointer m_CurrentFrame;

	VisualizationKinectWidget *m_Widget;	
	
	/// Update point picker GUI elements
	void UpdatePointPickerGUI();
	
	/// Update CylinderVisualizationKinect
	void UpdateCylinder();

	/// Check if something is inside/outside the defined sphere
	void IntraSphereCheck();

	/// Plot Line in between two points
	void PlotLine(double *point1, double *point2);

	void RenderCylinder(VF3 point1, VF3 point2, GLUquadricObj *cylinder, int radius);
	void MouseButton(int button, int state, int x, int y);
	void mousePressEvent(QMouseEvent *e);
	void keyPressEvent(QKeyEvent *e);
	
	/// Last mouse point
	QPoint m_LastMousePos;
	int m_LastKeyNumber;

	
	/// General purpose mutex to synchronize
	itk::SimpleFastMutexLock m_Mutex;

	// pick points, 3D positions
	VF3 m_PickPoint1;
	VF3 m_PickPoint2;

	int m_OffsetInnerCylHeight;
	int m_OffsetOuterCylHeight;

	bool m_Init;

	VF3 m_planePoint1;
	VF3 m_planePoint2;
	VF3 m_planePoint3;

	VF3 m_planeNormalVector;

	
	// Distance between picked points
	double m_Distance;

	double m_distPlaneH;
	double m_distPlaneV;

	// Inner/Outer Radius arround the line(pickpoint1,pickpoint2) where points were observed
	double m_RadiusInner;
	double m_RadiusOuter;

	// cloned image to change RGB values in the non-CONST iterator
	RImagePointer m_CopyOfCurrentFrame;
	RImageConstPointer m_tmpCopyOfCurrentFrame;
	
private:
	VF3 CrossProduct(VF3 vec1, VF3 vec2);
	VF3 VF3Minus(VF3 vec1, VF3 vec2);
	VF3 VF3Plus(VF3 vec1, VF3 vec2);
	double VF3ScalarProduct(VF3 vec1, VF3 vec2);
	double VF3Abs(VF3 vec);
	std::string Openfilename();
};


#endif // VisualizationKinectPLUGIN_H__
