#ifndef RENDER_H
#define RENDER_H

#include "./../../lib/GLee/GLee.h"	


#include "./camera/Camera.h"
#include <QGLWidget>
 #include <QGLContext>

#include <vector>

#include "./geometry/ModelObject.h"
#include "./illumination/Light.h"
#include "./cgSupport/ShaderComposer.h"
#include "./phong/Phong.h"
#include "./renderer/AbstractRender.h"
#include "./math/Mathematics.h"
#include "./math/Matrix.h"
#include "./particles/particle.h"

using namespace ANALYTICAL_GEOMETRY;
using namespace GEOMETRY;

///Camera projection settings
struct Projection
{
	float zNear; /**<minimal camera-object distance */
	float zFar;	/**<maximal camera-object distance */
	float ratio;	/**<ratio of screen width and height */
	float FOV;	/**<field of view angle */
};

///Sprite object is always oriented to camera.
struct Billboard
{
	Point_3<float> position;	/**<positon of the billboard */
	CRgbw color;				/**<color of the billboard */
	unsigned int texID;			/**<texture id of the billboard */
	float size[2];				/**<width and height of the billboard */
};

///Font object is used for text drawing
struct Font
{
	CTriCol color;	/**<color of the font */
	float alpha;	/**<alpha of the font */
	unsigned int texID;	/**<font texture id (must be compatible with out font texture layout! ) */
	float size;	/**<size of the font */
};

/// Provides basic OpenGL render interface.
class Render : public AbstractRender
{
protected:
	Projection projection; /**<camera projection settings */
	Camera<double> camera;	/**<camera settings */

public:
	Camera<double> getCamera(void) const;	/**<returns camera position */
	void getCamera( Camera<double> &dstCamera) const;	/**<returns camera position */

	Projection& getProjection(void);	/**<returns projection settings */
	void setProjection(float ratio, float zNear, float zFar, float FOV);	/**<sets camera projection settings */
	void setFOV( float FOV);	/**<sets field of view for camera */

	Render( Context& context);

	virtual Point_3<double> unproject( int screenPos[2] );	/**< project point from screen space to world space and returns its positinon */
	virtual Point_3<float> project( Point_3<float> &point3D ); /**< Project point from camera space to screen space */

	virtual void bind(void);	/**< bind OpenGL - prepares OpenGL for new frame render */
	virtual void beginFrame(const Camera<double>& camera);	/**< clear and starts new frame render, from given camera position and orientation */
	virtual void beginFrame(void);	/**<clear and starts new frame render */

	virtual void renderModel( Model &model);	/**<render model into current frame and scene  */
	virtual void renderModels( vector<Model*> &models);	/**<render models into current frame and scene */

	virtual void renderParticles( vector<GraphicParticle*> &particles );	/**<render particles into current frame and scene */

	virtual void renderBillboard( const Billboard &billboard );		/**<render Billboard into current frame and scene */
	virtual void renderText( Point_3<float> pos, const string &text, const Font &font );	/**<render text into current frame and scene */

	virtual void renderImage2D( int leftDown[2], unsigned int texId );	/**<render 2D image into current frame and scene */
	virtual void renderImage2D( int leftDown[2], int upRight[2], unsigned int texId );	/**<render 2D image into current frame and scene */
	virtual void renderFullscreenImage2D( unsigned int texId );	/**<render full screen image into current frame and scene */

	virtual void renderLine( const Point_3<float> &from, const Point_3<float> &to, const CRgbw &color, float width=1.0f );
	virtual void renderCircle( const Point_3<float> &center, const Vector_3<float> &normalizeAxis, const CRgbw &color, float radius, int segmentCount, float width =1.0 );
	virtual void renderSphere( const Point_3<float> &center, const CRgbw &color, float radius, int segmentCount, unsigned int texId=0 );
	virtual void renderQuad( const Point_3<float> &point1, const Point_3<float> &point2, const Point_3<float> &point3, const Point_3<float> &point4, const CRgbw &color, unsigned int texId=0 );
};

const float SPOT_VRML=1.0;
const float SPOT_BASIC=2.0;
const float NO_SPOT=0.0;
const float NO_FILL_LIGHT=0.0;
const float FILL_LIGHT=1.0;

#endif