#ifndef _ENTITYBASE_H
#define _ENTITYBASE_H

#include "Engine.h"
#include "mathlib.h"

#include "EntityBaseTypes.h"

namespace coll2d {
	class Shape;
}

namespace Engine {

/** \brief Contains all the information for the physical simulation of the
 * Entity
 *
 * Every Engine::Entity that should be simulated in the Engine::Physics module
 * must have a Engine::EntityPhysicState counterpart. It represents the state
 * of the Entity in the physical world of the engine.
 *
 * The Copy-Constructor and Assignment Operator is defined in EntityPhysics.cc
 * as they require a call to coll2d::Shape::getCopy() which again requires the
 * inclusion of coll2d.h which should stay out of Entity.h for faster
 * compilation.
 */
struct EntityPhysicState {
	/** \brief Standard constructor */
	EntityPhysicState ():
		mId (0),
		mBaseType (EntityBaseTypeNone),
		mPosition (0., 0., 0.),
		mOrientation (0., 0., 0.),
		mVelocity (0., 0., 0.),
		mAngleVelocity (0.),
		mRadius (0.),
		mShape (NULL),
		mStatic (false),
		mAlive (true),
		mContactNormals() {};

	virtual ~EntityPhysicState() {};

	/** \brief Copy constructor */
	EntityPhysicState (const EntityPhysicState& state);

	/** \brief Assignment operator */
	EntityPhysicState& operator= (const EntityPhysicState& state);

	unsigned int mId;
	/** \brief The type from the game's perspective */
	int mType;
	/** \brief The type from the engine's perspective */
	EntityBaseType mBaseType;

	vector3d mPosition;
	vector3d mOrientation;
	vector3d mVelocity;
	float	mAngleVelocity;
	float mRadius;

	coll2d::Shape* mShape;
	bool mStatic;

	/** \brief If false, the entity will be removed at the end of the frame. */
	bool mAlive;

	vector3d &GetPosition ();
	vector3d &GetVelocity ();
	vector3d &GetOrientation ();
	float &GetAngleVelocity ();

	void SetPosition (const vector3d &position) { mPosition = position; }
	void SetVelocity (const vector3d &velocity) { mVelocity = velocity; }
	void SetOrientation (const vector3d &orientation) { mOrientation = orientation; }
	void SetAngleVelocity (const float &angle_velocity) { mAngleVelocity = angle_velocity; }

	/** \brief Transforms the given vector in local space to world coordinates */
	void Globalize (vector3d &vec);
	/** \brief Transforms the given vector from world coordinates to local
	 * coordinates */
	void Localize (vector3d &vec);
	/** \brief Performs only the rotational part of Globalize() */
	void GlobalizeRotation (vector3d &vec);
	/** \brief Performs only the rotational part of Localize() */
	void LocalizeRotation (vector3d &vec);

	/** \brief Updates the shape for collision detection */
	void UpdateShape ();

	/** \brief Contains all the normal vectors of the planes with which we are in contact. */
	std::map<unsigned int, vector3d> mContactNormals;
};

/** \brief Represents the current state of the Entity controller 
 *
 * This struct stores the current state for all EntityControllerKeyStates
 * (e.g. whether the keys are currently pressed or not).
 *
 * \todo [Low] The current design is very unflexible. Is there a better way?
 */
struct EntityControllerState {
	std::bitset<EntityControllerMaxKeyStates> mKeyState;

	bool GetKey (int state);
	void SetKey (int state);
	void UnsetKey (int state);
};

/** \brief Represents the base of everything that exists in the engine
 *
 * An Engine::Entity has different representations in the different
 * submodules. Engine::EntityPhysicState stores the physical representation of
 * the entity like its position, velocity, orientation, and shape.
 * Engine::EntityVisualState is used for drawing an Entity by Engine::View.
 */
struct EntityBase {
	unsigned int mId;
	/** \brief The type from the game's perspective */
	int mType;
	/** \brief The type from the engine's perspective */
	EntityBaseType mBaseType;

	EntityPhysicState *mPhysicState;
	EntityControllerState *mControllerState;

	/** \brief Applies the state of the EntityControllerState to the EntityPhysicState etc. */
	virtual void Update (float delta_sec) {};

	/** \brief Adds the given state to the current movement state of the Entity */
	virtual void SetControllerKeyState (int state);
	/** \brief Removes the given state to the current movement state of the Entity */
	virtual void UnsetControllerKeyState (int state);

	/** \brief Helper function to set the id to all substates */
	void SetId (unsigned int id) {
		mId = id;

		if (mPhysicState)
			mPhysicState->mId = id;
	}

	/** Executes game logic for the collision event
	 * \returns true  if it was able to react for this type of entity, false
	 *          false otherwise
	 */
	virtual bool CollisionEvent (EntityBase* entity_state, vector3d point, vector3d normal) {
		return false;
	}
};

typedef std::map<unsigned int, EntityBase*>::iterator EntityBaseIter;

}

#endif // _ENTITYBASE_H
