#ifndef STGAME_H
#define STGAME_H

#define GAMEMODE_AOW		1
#define GAMEMODE_CTF		2
#define GAMEMODE_INFONLY	3
#define GAMEMODE_SNIPER		4
#define GAMEMODE_500SNIP	5
#define GAMEMODE_DM			6
#define GAMEMODE_TDM		7

#define WEATHER_NONE		0
#define WEATHER_RAIN		1
#define WEATHER_SNOW		2
#define WEATHER_ASH			3

struct stObserverDataStruct {
	// Object type id
	unsigned long type;
	
	// Preset name
	const char *preset;

	// Observer name
	const char *name;
	
	// Observer parameter
	const char *param;
};

class gzSettingsGameClass : public stSettingsBase {
public:
	const char *GetName()
	{
		return "gzSettingsGameClass";
	};
	gzSettingsGameClass();
	void Delete();
	void Load();

	// Game settings
	int				m_GameMode;
	int				m_ForceTeam;
	bool			m_EnableVehicleWreckages;
	bool			m_EnableInvincibleBuildings;
	bool			m_EnableBeacon;
	bool			m_EnableWeaponDrop;
	bool			m_AllowRefill;
	bool			m_SuicideResetNegativeCredits;
	
	bool			m_EnableInfAmmo;
	bool			m_NoReload;
	aString			m_SpawnChar[2];
	aStringArray	m_DisablePreset;
	float			m_RefineryIncomeTick;
	float			m_RefineryIncomeDump;
	float			m_AllowAfkSeconds;
	bool			m_AllowHillAttack;
	bool			m_EnableWeather;
	int				m_WeatherType;
	bool			m_AlwaysStart;
	int				m_MinimumBandwidth;
	unsigned int	m_InvincibleSecs;

	// Log settings
	aString			m_LogRoot;
	bool			m_EnableGamelog;
	bool			m_LogSoldierPurchase;
	bool			m_LogSoldierDeath;
	bool			m_LogVehiclePurchase;
	bool			m_LogVehicleDeath;

	aVector<unsigned int> m_DisableSpawner;

#if VERC(1, 0, 1)
	aStringArray m_disableBuildings;
#endif
};


/****************/
/* Game manager */
/****************/
class gzGameModeBase;
class gzGameAow;
class gzGameCTF;
class gzGameInfOnly;
class gzGameSniper;
class gzGame500Snip;
class gzGameDM;
class gzWeatherManager;
class gzGameManager : public EventHandler, public gzSettingsEvent {
	gzGameModeBase		*m_gameMode;
	FILE				*m_gamelogFile;
	gzWeatherManager	*m_weatherMgr;
	bool				m_isWaitingNextMap;
	aVector<stObserverDataStruct> m_observerList;
public:
	const char *GetName()
	{
		return "gzGameManager";
	};
	gzGameManager();
	void Delete();
	void Settings_Loaded();
	void Level_Loaded();
	void Level_Ended();
	gzGameModeBase *GetGame() { return this->m_gameMode; };
	FILE *GetGamelogFileHandler() { return this->m_gamelogFile; };
	bool IsGameOver() { return this->m_isWaitingNextMap; };
	gzSettingsGameClass *GetSettings() { return this->m_settings; };
	void AddObserver(unsigned long type, const char *name, const char *param = NULL);
	void AddObserver(const char *preset, const char *name, const char *param = NULL);

	gzSettingsGameClass *m_settings;	
};
extern gzGameManager *gzGameMgr;


/*******************/
/* Weather manager */
/*******************/
class gzWeatherManager : public EventHandler {
	float m_timer;
	float m_range;
	float m_clouds;

	//float m_CloudCover;
	//float m_CoverRange;
	//float m_CloudGloom;
	//float m_GloomRange;
	//float m_Heading;
	//float m_HeadRange;
	//float m_WindVar;
	//float m_WindVarRange;
public:
	const char *GetName()
	{
		return "gzWeatherManager";
	};
	void Delete() { };
	gzWeatherManager();
	void Think();
};


/******************/
/* Game mode base */
/******************/
class gzGameModeBase : public EventHandler {
protected:
	gzSettingsGameClass *m_settings;
public:
	virtual const char *ModeName() = 0;
	virtual gzGameAow *As_GameAow()
	{
		return NULL;
	};
	virtual gzGameCTF *As_GameCTF()
	{
		return NULL;
	};
	virtual gzGameInfOnly *As_GameInfOnly()
	{
		return NULL;
	};
	virtual gzGameSniper *As_GameSniper()
	{
		return NULL;
	};
	virtual gzGame500Snip *As_Game500Snip()
	{
		return NULL;
	};
	virtual gzGameDM *As_GameDM()
	{
		return NULL;
	};
	virtual void Object_JumpStart(gzEventObjectJump &);
	virtual void Object_SoldierSquished(gzEventObjectKill &);
	gzGameModeBase();
	bool IsPresetDisabled(const char *);
};


/***********/
/* Gamelog */
/***********/
#define GAMELOG_BUILDING	1
#define GAMELOG_SOLDIER		2
#define GAMELOG_VEHICLE		3
#define GAMELOG_BEACON		4
#define GAMELOG_C4			5
#define GAMELOG_CRATE		6
#define GAMELOG_SCORE		7

#define GAMELOG_FILENAME	"gamelog.txt"

class gzGamelogBase : public nc_ScriptImpClass {
protected:
	gzGamelogBase();

	int m_objType;
	static const char *m_typeString[];
public:
	static void Log(const char *message, ...);
	static void RenameLog();
};

class gzGamelogObserver : public gzGamelogBase {
	void Created(nc_ScriptableGameObj *obj);
	void Custom(nc_ScriptableGameObj *obj, int message, int param, nc_ScriptableGameObj *sender);
	void Damaged(nc_ScriptableGameObj *obj, nc_ScriptableGameObj *damager, float damage);
	void Destroyed(nc_ScriptableGameObj *obj);
	void Killed(nc_ScriptableGameObj *obj, nc_ScriptableGameObj *shooter);
	void Timer_Expired(nc_ScriptableGameObj *obj, int number);
};


/*************/
/* Observers */
/*************/
class gzObserverBuilding : public nc_ScriptImpClass {
	void Created(nc_ScriptableGameObj *obj);
	void Damaged(nc_ScriptableGameObj *obj, nc_ScriptableGameObj *damager, float damage);
	void Killed(nc_ScriptableGameObj *obj, nc_ScriptableGameObj *shooter);
	void Timer_Expired(nc_ScriptableGameObj *obj, int number);
	nc_BuildingGameObj *m_Building;
	float PlayHealth;
};

/**********************/
/* Obelisk effect fix */
/**********************/
class gzObelisk_Powerup : public nc_ScriptImpClass {
	void Created(nc_ScriptableGameObj *obj);
	void Custom(nc_ScriptableGameObj *obj, int message, int param, nc_ScriptableGameObj *sender);
	void Timer_Expired(nc_ScriptableGameObj *obj, int number);
	int m_effectObjId;
	bool m_isCharging;
};

/*************/
/* Parachute */
/*************/
class gzObserver_Parachute : public nc_ScriptImpClass {
	void Created(nc_ScriptableGameObj *obj);
	void Destroyed(nc_ScriptableGameObj *);
	void Timer_Expired(nc_ScriptableGameObj *obj, int number);
	int m_floaterId, m_parachuteId;
	nc_Vector3 m_floaterPos;
};


#if ISDEV()
class gzObserver_Nod_Obelisk : public nc_ScriptImpClass {
	void Created(nc_ScriptableGameObj *obj);
	void Enemy_Seen(nc_ScriptableGameObj *obj, nc_ScriptableGameObj *seen);
	void Timer_Expired(nc_ScriptableGameObj *obj, int number);
	unsigned int m_currTarget;
};
#endif

#endif
