#ifndef CPHYSICS_CAMERA_H
#define CPHYSICS_CAMERA_H

#include "PhysicsGlobal.h"
#include "SPhysicsStructs.h"
#include "MPhysicsCallbacks.h"

class CPhysicsCamera
{
public:
	///Constructors and destructors of the camera class.
	CPhysicsCamera();
	~CPhysicsCamera();

	void init(IrrlichtDevice* dev, NewtonWorld* world, SPhysicsCamera* camera);
	
	/// A callback for events, this is called by irrlicht when
	/// there is a new event.
	void onEvent(SEvent event);

	/// Camera update function for updating camera movement.
	void update();

	/// Apply a material on the current mesh.
	void setMaterial(int material);

	/// Set the keymap for camera movement.
	void setKeyMap(SCameraKeyMap* kMap, s32 kMapSize);	

	/// Give a pointer to the ground, for stair detection system.
	void setGround(NewtonBody* grnd);

	/// Set camera position.
	void setPosition(vector3df position); 

	/// Set camera rotation.
	void setRotation(vector3df rotation); 

	/// Get camera position.
	vector3df getPosition(); 

	/// Get camera rotation.
	vector3df getRotation(); 

	/// Get a pointer to the camera's newton body.
	NewtonBody* getBody(); 

	/// Get a pointer to the camera scene node.
	ICameraSceneNode* getCameraNode();
	
private:
	/// Pointer to newton world.
	static NewtonWorld *m_world;

	/// Irrlicht objects.
	IrrlichtDevice* m_device;

	/// Pointer to the camera scene node and newton created body.
	static NewtonBody* m_body;
	ICameraSceneNode* m_node;

	/// The position of the center of the screen.
	position2d<f32> m_centerCursor;

	/// Pointer to the ground newton body.
	static NewtonBody* m_ground;

	/// This variable carries the force which the camera moves to the
	/// force and torque event.
	static vector3df m_camForce;

	/// A boolean to check if this is the first time the camera is
	/// being updated.
	bool m_firstUpdate;

	/// A variable to store the size of the body.
	static vector3df m_bodySize;

	/// Sensitivity of the camera.
	f32 m_sensitivity;

	/// Speed of movement of the camera.
	f32 m_moveSpeed;

	/// The start of the raycast.
	static vector3df m_rayStart;

	/// The end of the raycast.
	static vector3df m_rayEnd;

	/// The max stepping size of the camera, used for stairs.
	f32 m_maxStepSize;

	/// Key map for the cameras movement.
	array<SCameraKeyMap> m_keyMap;

	/// An array for checking key press easily.
	bool m_cursorKeys[4];

	/// Newton callbacks.
	static void _cdecl camSetTransform (const NewtonBody* body, const float* matrix);
	static void _cdecl camApplyForce (const NewtonBody* body);
	static void _cdecl destructor(const NewtonBody* body);
	static f32 OnRayCastPlacement (const NewtonBody* body, const dFloat* normal, int collisionID, void* userData, dFloat intersetParam);
	static f32 OnFloorCheckRayCast (const NewtonBody* body, const dFloat* normal, int collisionID, void* userData, dFloat intersetParam);
};

#endif
