#ifndef _MODELBASE_H
#define _MODELBASE_H

#include "Engine.h"
#include "EntityBase.h"
// #include "Timer.h"

namespace Engine {

class Module;
class PhysicsBase;
class Events;
class EntityFactoryBase;
class OverlayManager;

#ifdef max
#undef max
#endif

const unsigned int NullEntityId = std::numeric_limits<unsigned int>::max() - 1;

struct EntityBase;

/** \brief Represents the current state of the Engine
 *
 * Represents the State of the Engine and is unaware of anything except itself.
 * It manages all Entities, Physics, etc.
 *
 *	It has the following subsystems:
 *	- Events
 *	- Physics
 *	- Variables
 *
 * \note
 * To create an Entity one must call Engine::CreateEntity() which will
 * allocate the Entity and performs all the required registrations by calling
 * Model::RegisterEntity().
 */
class ModelBase : public Module {
	public:
		/** Performs simulation, gamelogic, etc */
		virtual void Process ();
		/** Updates the timer */
		void UpdateTimer () {
			static float last_frame = 0;
			float current_frame = static_cast<float> (SDL_GetTicks ()) * 1.0e-3;
			mDeltaSec = current_frame - last_frame;
			last_frame = current_frame;
		}
		float GetFrameDuration () {
			return mDeltaSec;
		}
	
		/** Adds the given Entity to the Model */
		void RegisterEntity (EntityBase *entity);
		/** Removes the Entity with the given id */
		void UnregisterEntity (const unsigned int id);
		/** Marks an Engine::Entity as killed so that it gets removed after the
		 * simulation */
		void KillEntity (const unsigned int id);

		/** Creates an Entity of the given type
		 *
		 * This calls the CreateEntity() function on the Model::mEntityFactory to
		 * create the proper Entity and registers it to the required submodules
		 * (so far only Model::mPhysics).
		 */
		EntityBase* CreateEntity (int type);
		/** Returns the Entity with the given id */
		EntityBase* GetEntity (const unsigned int id);

		/** Returns the Entity at the given world coordinates */
		EntityBase* GetEntityAt (const vector3d &pos);

		EntityBaseIter GetEntityIterBegin () {
			return mEntities.begin();
		}
		EntityBaseIter GetEntityIterEnd() {
			return mEntities.end();
		}

		/** Returns a unused id for an Entity */
		unsigned int CreateEntityId ();
		/** Removes all Entities */
		void ClearEntities ();
		
		/** Returns the id of the entity the player is currently controlling */
		unsigned int GetPlayerEntityId ();
		/** \brief Assigns the player to an Entity. All controls will be redirected to that player 
		 *
		 * This can be used to disable the controls of of the player by assinging
		 * the special entity id of NullEntityId */
		void SetPlayerEntityId(unsigned int entity_id);

		/** Notifies the gamelogic of a collision event */
		void SendEntityCollisionEvent (const unsigned int reference_entity_id,
				const unsigned int incidence_entity_id, float collision_time, vector3d point, vector3d normal);

		virtual void SetGameState (const unsigned int &state) {
			mLastGameState = mGameState;
			mGameState = state;
		};
		unsigned int GetGameState () { return mGameState; };

		/*
		void StartTimer(const std::string &id, float msec) {
			TimerIter cur_timer = mTimers.find(id);
			if (cur_timer != mTimers.end()) {
				cur_timer->second.Set(msec);
				cur_timer->second.Start();

				return;
			}

			mTimers[id] = Timer(id, msec);
			assert (mTimers.size() > 0);
			assert (mTimers[id].IsActive() == true);
		}
		bool CheckTimer(const std::string &id) {
			TimerIter cur_timer = mTimers.find(id);

			if (cur_timer == mTimers.end()) {
				return false;
			}

			return cur_timer->second.Query();
		}
		*/

	protected:
		/** \brief Initializes the system */
		virtual int OnInit (int argc, char* argv[]);
		/** \brief Destroys the system (must be called!) */
		virtual void OnDestroy ();

		/** \brief Gets called when an entity of the given type is being created */
		virtual void OnCreateEntity (const int type, const unsigned int id) {};
		/** \brief Gets called when an entity is marked to be killed */
		virtual void OnKillEntity (const EntityBase *entity) {};


		PhysicsBase *mPhysics;
		Events *mEvents;

		/** \brief Creates Entities */
		EntityFactoryBase *mEntityFactory;

		/** \brief contains all Engine::Entities */
		std::map<unsigned int, EntityBase *> mEntities;
		typedef std::map<unsigned int, EntityBase *>::iterator EntityIter;

		/** \brief contains all Engine::Entities that ceased to exist */
		std::vector<unsigned int> mKilledEntities;

		/*
		std::map<std::string, Timer> mTimers;
		typedef std::map<std::string, Timer>::iterator TimerIter;
		*/

		unsigned int mEntityIdCounter;
		unsigned int mPlayerEntityId;

		unsigned int mGameState;
		unsigned int mLastGameState;

		float mDeltaSec;

	friend class ViewBase;
	friend class OverlayManager;
	friend class Engine;
	friend class Controller;
};

/** \brief Creates an Entity of the given type and registers at the required modules *
 *
 * It allocates the memory needed to represent that specific type of Entity.
 * At also performs the required registrations at the various Modules.
 *
 * All Entities that are created with this function get also destroyed in
 * Model::Destroy () by calling DestroyEntity () for this Entity.
 *
 * \note All Entities must be created with this function if you intend to keep
 * the different Modules in sync!
 */
EntityBase * CreateEntity (int type);

/** \brief Frees the Memory required by the Entity and unregisters it 
 *
 * This function also frees the memory the Entity is using in its
 * different representitions such as EntityVisualState and EntityPhysicState.
 *
 * It also unregisters the Entity from the different Modules where it was
 * registered by CreateEntity.
 */
void DestroyEntity (unsigned int id);
/** \brief Tells the model that the entity is no more existant in the game
 * world */
void KillEntity (unsigned int id);
/** \brief Returns the Entity with the given id, NULL otherwise */
EntityBase * GetEntity (unsigned int id);
/** \brief Returns the physical state of the Entity with the given id, NULL otherwise */
EntityPhysicState * GetEntityPhysicState (unsigned int id);

}

#endif // _MODEL_H
