/*======================================================================================

	Program:		Range Imaging Toolkit (RITK)
	Module:			OpenGLSkeletonEntity.h
	Version:		$Revision: 1466 $
	Date:			$Date: 2011-09-02 15:54:12 +0100 (Fri, 02 Sep 2011) $

	Copyright (c) 2010-2011
	Pattern Recognition Lab, 
    University Erlangen-Nuremberg, Germany
    All rights reserved.

	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 RITKCopyright.txt for more information.

	http://www5.informatik.uni-erlangen.de/research/software/ritk

========================================================================================*/

#ifndef OPENGLSKELETONENTITY_H__
#define OPENGLSKELETONENTITY_H__

#include "RITKVisualization.h"
#include "Skeleton.h"

#include <QtOpenGL>

#include <itkObject.h>
#include <itkObjectFactory.h>
#include <itkSimpleFastMutexLock.h>

#include "ritkRImage.h"
#include "ritkGenericImportImageContainer.h"

#include "ritkOpenGLEntity.h"
#include "OpenGLSkeletonControlUnit.h"
#include "ritkImagePayloadVisualizationConfig.h"
#include "KinectSDKExport.h"


namespace ritk
{

/**	@ingroup	Visualization
 *	@class		OpenGLSkeletonEntity
 *	@author		Jakob Wasza
 *	@brief		OpenGL based visualization entity for range images
 *
 *	@details
 */
class KINECTSDK_EXPORT OpenGLSkeletonEntity : public OpenGLEntity, public itk::Object
{
	Q_OBJECT

public:
	/**	@name	Standard ITK typedefs */
	//@{
	typedef OpenGLSkeletonEntity							Self;
	typedef itk::Object										Superclass;
	typedef itk::SmartPointer<Self>							Pointer;
	typedef itk::SmartPointer<const Self>					ConstPointer;

	typedef Skeleton::ConstPointer							SkeletonConstPointer;
	//@}

	/// Object creation
	itkNewMacro(Self);

	/// RTTI
	itkTypeMacro(OpenGLSkeletonEntity, itk::Object);

	/**	@brief	Set the range data to render 
	 *	@param	Data	The data to render
	 *
	 *	@details
	 *	A call to this method will set the range data to render.
	 */
	void SetSkeletonData(SkeletonConstPointer Data);

	/// Render
	virtual void Render();

	/// Bounding box
	virtual BoundingBoxType GetBoundingBox() const;

	/// The controlunit of this entity
	virtual QDockWidget* GetControlUnit() const;

protected slots:
	/**	@brief	Update the primary payload to visualize
	 *	@param	Config	the payload configuration
	 *
	 *	@details
	 *	Calling this method will update the internal primary payload config
	 */

	void SetInferredJointsVisible(bool enable);
	void SetJointOutputStream(bool enable);
	void showSkeleton(bool enable);

//signals:
	/**	@name Signals connected to the control unit. !*/

protected:
	/// Copy of Skeleton
	Skeleton::ConstPointer m_Skeleton;

	/// Constructor
	OpenGLSkeletonEntity();
	/// Destructor
	virtual ~OpenGLSkeletonEntity();

	/// Print the camera to the given stream
	virtual void PrintSelf(std::ostream& os, itk::Indent indent) const;

	/// Initialize all OpenGL related members
	void InitGL();
	/// Release all OpenGL related members
	void CloseGL();

	/// Flag that indicates whether this entity (in particular the OpenGL extensions are initialized)
	bool m_InitFlag;
	bool m_drawInferredJoints;
	bool m_drawSkeleton;
	bool m_WriteOutputTXT;

	// for debug purpose
	std::ostringstream m_timestream;

	/// The control unit
	OpenGLSkeletonControlUnit* m_ControlUnit;
	
private:
	/// Render joint sphere
	void RenderJointSphere(Skeleton::JointTypes joint, int SkelIDX, GLUquadricObj *quadric, VF3 color, int radius);

	/// Render cylinder (connects the joint spheres)
	void RenderCylinder(Skeleton::JointTypes joint1, Skeleton::JointTypes joint2, int SkelIDX, GLUquadricObj *cylinder, VF3 color, int radius);
};

} // namespace ritk

#endif // OpenGLSkeletonEntity_H__