/*********************************************************************//**
*	\brief BaseEntity
*	Abstraktni trida definuji spolecne vlastnosti vsech entit. je jejich
*	spolecnym zakladem.
*	
*	\author Michal Jirous
*	\date 10.03.2009
*	\file ent_baseentity.h
**********************************************************************/

#ifndef __ENT_BASEENTITIY_H__
#define __ENT_BASEENTITIY_H__

#include "algebraic.h"
#include <string>
#include <map>

typedef std::map<std::string, std::string> parameters_t;
std::string getParameterValue(parameters_t &parametersMap, std::string key );

#define ENT_PARM_RUNNABLE				0x01
#define ENT_PARM_BLENDING_CARE			0x02
#define ENT_PARM_RENDER					0x04
#define ENT_PARM_COLLIDING				0x08
#define ENT_PARM_FORCE_MOVING			0x10
#define ENT_PARM_SHOOTABLE				0x20
#define ENT_PARM_DYNAMIC_MODEL_USAGE	0x40
#define ENT_PARM_INTERACTIVE			0x80
#define ENT_PARM_POINTING				0x100
#define ENT_PARM_MONSTER				0x200

#include "attack_info.h"

struct FrameTime
{
	float period_percentage;
	float elapsed_seconds;
	bool texturesAnim;
};

#include "game_frustum.h"
struct RenderData
{
	Frustum *frustum;
	Point *cameraPosition;
	bool alpha;
	FrameTime frameTimes;
	bool backfacecull;
};



const unsigned int BACK_TIME_MS = 3000;
const unsigned int BACK_TIME_MS_REAL = BACK_TIME_MS + 1000;

enum
{
	EVENT_POSITION = 0,
	EVENT_FRAME,
	EVENT_FORCED_EVENT,
	EVENT_TRIGGER,
	EVENT_BORDER,
	EVENT_TURN_ON,
	EVENT_TURN_OFF,
	EVENT_ITEM_TAKEN,
	EVENT_TEXTURE_SWITCH,
	EVENT_ANGLES,
	EVENT_VELOCITY,
	EVENT_STATUS,
	EVENT_TARGET,
	EVENT_OPEN,
	EVENT_CLOSE,
	EVENT_SEQUENCE,
	EVENT_DEATH,
	EVENT_HEALTH,
	EVENT_RAISE_FROM_DEATH,
	EVENT_DUCK,
	EVENT_DUCK_UP
};

union BackTimeValues
{
	float position[3];
	float frame;
	int event;
	void *pointer;
};

#include <SDL/SDL.h>

struct BackTimeData
{
	Uint32 event_time;
	int type;
	BackTimeValues values;
};

#include "level_structs.h"
const int TRIGGER_INFINITE = 0xFFFFFFFF;
#define MATERIAL_FACE_BASED -1

#define RENDER_MODE_NORMAL 0
#define RENDER_MODE_SOLID 4
#define RENDER_MODE_COLOR 1

typedef std::list<CBaseEntity*> entityList_t;	/*!< @brief Pojmenovani spojoveho seznamu entit. */

class CBaseEntity
{
protected:
	Face *m_pNearestFace;
	std::string m_sClassName;
	int m_iProperties;
	std::list<BackTimeData> m_BackTimeData;
	virtual void removeOldBackEvents();
	BackTimeData *getLastStoredEvent();
	void deleteLastStoredEvent();
	virtual void passStoredEvent( BackTimeData &backData ){}
	
	entityList_t *m_TargetList;

	int m_SolidModel;	//cislo modelu (nektere objekty ho mit nemuseji)

	bool basicSolidCollisionDetection( CollisionData &collData );	//done
	bool basicSolidRayTracing(  RayTraceData &rayData );//done

	virtual void passFlags( int flags ){}

	void setRenderMode();
	void unsetRenderMode();

	
	void insertBorder();
	bool m_bIsBlending;
	int m_iMaterial;
public:
	BoundingBox *m_pSortBoundingBox;
	bool isBlending()	{ return m_bIsBlending; }
	std::string m_sName;
	std::string m_sTarget;
	Point origin;
	Point angles;
	Point direction;
	unsigned char rendermode;
	Color rendercolor;
	float  renderamt;
	CBaseEntity();
	
	virtual void goBackInTime();
	virtual void updateBackTime(){}
	virtual void compile();
	virtual void decompile(){}
	virtual void restart();
	virtual void render( RenderData &renderData ){}
	virtual bool renderCullTest( RenderData &renderData ){return true;}
	virtual void update( float seconds );
	virtual void onTarget( int target_type ) {}
	virtual void setParameters( parameters_t &parametersMap );

	std::string getClassName() { return m_sClassName; }
	
	int getProperties()	{ return m_iProperties; }

	size_t getSolidModel();
	void setSolidModel( int model ) { m_SolidModel = model; }

	virtual bool collisionDetection( CollisionData &collData );
	virtual bool rayTrace( RayTraceData &rayData );

	virtual void onAttack( const AttackInfo &attackInfo ){}
	virtual void onUsage( const RayTraceData &rayData ) {}
	virtual void onPointing( const RayTraceData &rayData ) {}
	virtual void onCollide( CollisionData &collData ) {}	//v pripade kolize nekoho s touto entitou 

	int getMaterial()	{ return m_iMaterial; }
};






typedef CBaseEntity* (*entityCreatorFunc)();


template <typename T>
CBaseEntity *createEntity()
{
	return new T();
}

struct EntityMaker
{
	EntityMaker( std::string name, entityCreatorFunc func ); 
};

CBaseEntity* getNewEntity( std::string name );


#define LINK_ENTITY_TO_CLASS(name,class_t) const EntityMaker creator##name(#name, createEntity<class_t>)




#endif /*__ENT_BASEENTITIY_H__*/

