#ifndef STPLAYER_H
#define STPLAYER_H

#define INFAMMO_CHECK 0.5f

class gzChatFloodClass;
class gzRadioFloodClass;
class gzWeaponPackClass;
class gzVehicleOwnerClass;
class gzAntiCheatSpec;
class gzAntiCheatWeapons;
class gzAntiCheatHitLog;
class gzVeteranClass;

#define NUMPAD_TAUNT		1
#define NUMPAD_PURCHASE		2

// Forward
class gzTiberiumCrystal;
class stRewardsClass;

class gzPlayer : public EventHandler {
	gzChatFloodClass*    m_chatFlood;
	gzRadioFloodClass*   m_radioFlood;
	gzAntiCheatSpec*     m_antiCheatSpec;
	gzAntiCheatWeapons*  m_antiCheatRoF;
	gzAntiCheatHitLog*   m_antiCheatHitLog;
	gzVehicleOwnerClass* m_vehOwnData;
	gzWeaponPackClass*   m_weaponPack;
	gzVeteranClass*      m_veteran;
	gzTiberiumCrystal*   m_tibCrystal;
#if VERC(1, 1, 0)
	stRewardsClass*      m_rewards;
#endif

	nc_cPlayer*   m_gameData;
	aWideString   m_name;
	bool          m_isActive;
	unsigned long m_lastPacketMs;
	float         m_ammoCheckInt;
	bool          m_primaryFire;
	int           m_numpadMode;
	float         m_afk_prevScore;
	float         m_afk_time;
	bool          m_afk_warnSent;
	float         m_afk_countDelay;
	bool          m_slowLoad;
	float         m_bhsVersion;
	bool          m_isSpectator;
	unsigned int  m_lastPokeProxy;
	unsigned int  m_pokeProxyCount;
	unsigned int  m_lastPokeTime;

#if VERC(1, 1, 0)
	int           m_stId;
#endif
public:
	const char *GetName()
	{
		return "gzPlayer";
	};
	void Delete() { };
	void SetDeletePending();
	gzPlayer(nc_cPlayer *);
	void Level_Loaded();
	void Think();
	void Player_Left(gzEventPlayerBase &);
	void Player_BandwidthChange(gzEventPlayerBandwidth &);
	void Player_Suicide(gzEventPlayerBase &);
	void Player_TeamChange(gzEventPlayerBase &);
	void Player_SerialHash(gzEventPlayerSerialHash &);
	void Player_Purchase(gzEventPlayerPurchase &);
	void Object_Damaged(gzEventObjectDamage &);
	void Object_Transition(gzEventObjectTransition &);
	void Object_JumpComplete(gzEventObjectJump &);
	void Object_Fire(gzEventObjectFire &);
	void Net_SerialAuth(gzEventNetSerialAuth &);
	void Bhs_Poke(gzEventBhsPoke &);

	inline gzChatFloodClass *GetChatCtrl() { return this->m_chatFlood; };
	inline gzRadioFloodClass *GetRadioCtrl() { return this->m_radioFlood; };
	inline gzAntiCheatHitLog *GetHitLog() { return this->m_antiCheatHitLog; };
	inline gzVehicleOwnerClass *GetVehicleData() { return this->m_vehOwnData; };
	inline gzWeaponPackClass *GetWeaponPack() { return this->m_weaponPack; };
	inline gzVeteranClass *GetVeteran() { return this->m_veteran; };
	inline gzTiberiumCrystal *GetTibCrystal() { return this->m_tibCrystal; };
	inline void SetTibCrystal(gzTiberiumCrystal *crystal) { this->m_tibCrystal = crystal; };
	inline nc_cPlayer *GetPlayerData() { return this->m_gameData; };
	inline bool IsActive() { return this->m_isActive; };
	inline void SetIsActive(bool isActive) { this->m_isActive = isActive; };
	inline bool IsLastPrimaryFire() { return this->m_primaryFire; };
	inline float GetAfkPrevScore() { return this->m_afk_prevScore; };
	inline void SetAfkPrevScore(float score) { this->m_afk_prevScore = score; };
	inline float GetAfkTime() { return this->m_afk_time; };
	inline void SetAfkTime(float second) { this->m_afk_time = second; };
	inline bool IsAfkWarnSent();
	inline void SetAfkIsWarnSent(bool value) { this->m_afk_warnSent = value; };
	inline float GetAfkDelay();
	inline void SetAfkDelay(float second) { this->m_afk_countDelay = second; };
	inline bool IsSlowLoading();
	inline void SetIsSlowLoading(bool value) { this->m_slowLoad = value; };
	inline float GetBHSVersion() { return this->m_bhsVersion; };
	inline void SetBHSVersion(float version) { this->m_bhsVersion = version; };
	inline bool IsSpectator() { return this->m_isSpectator; };
	inline void SetIsSpectator(bool value) { this->m_isSpectator = value; };
	inline nc_SoldierGameObj *GetSoldier();
	inline aWideString GetPlayerName() { return this->m_name; };

#if VERC(1, 1, 0)
	inline void SetStId(int id) { this->m_stId = id; };
	inline int GetStId() { return this->m_stId; };
#endif
};

class gzPlayerManager : public EventHandler, public gzManagerEvent {
	static aList<gzPlayer> m_list;
public:
	const char *GetName()
	{
		return "gzPlayerManager";
	};
	void Delete();
	void ChildObjCreation(gzBase *obj);
	void ChildObjDeletion(gzBase *obj);
	gzPlayerManager();
	void Level_Loaded();
	void Player_Joined(gzEventPlayerBase &);
	void Bhs_Version(gzEventBhsVersion &);
	static gzPlayer *Find(int);
	static gzPlayer *Find(nc_cPlayer *);
	static gzPlayer* Find(const aString&);
	static gzPlayer* FindByPartName(const aString&);
	static int FindByPartNameCount(const aString&);

	float m_bhsVersion[128];
};
extern gzPlayerManager *gzPlayerMgr;


/******************/
/* Serial manager */
/******************/
#define SERIALBAN_FILE "sBan.dat"

struct gzSerialBanStruct {
	aString hash;

#if VERC(1, 1, 0)
	aString reason;
#else
	aWideString reason;
#endif
};
class gzSerialManager : public EventHandler {
#if VERCL(1, 0, 1)
	aVector<gzSerialBanStruct *> m_banned;
#endif
public:
	const char *GetName()
	{
		return "gzSerialManager";
	};
	gzSerialManager();
	void Delete();
	void Player_SerialHash(gzEventPlayerSerialHash &);
	void Save();
	bool Hash_Ban(const char *hash, const char *reason);
	bool Hash_Unban(const aString& hash);
	void Hash_Search(const aString& hash, aVector<gzSerialBanStruct *> &);
};
extern gzSerialManager *gzSerialMgr;


/*************/
/* Observers */
/*************/
class gzObserverSoldier : public nc_ScriptImpClass {
	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);
	nc_SoldierGameObj *m_Soldier;
	bool m_tibDamage, m_fallDeath, m_squishDeath, m_killed;
	float m_lastDamage;
	nc_Vector3 m_fallPos;
	nc_cPlayer *m_killer;
};

class gzObserverSpectator : public nc_ScriptImpClass {
	void Created(nc_ScriptableGameObj *obj);
	void Custom(nc_ScriptableGameObj *obj, int message, int param, nc_ScriptableGameObj *sender);
	void Destroyed(nc_ScriptableGameObj *obj);
	void Timer_Expired(nc_ScriptableGameObj *obj, int number);
	gzPlayer *m_owner;
};

class gzFreeze_Player : 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);
	nc_Vector3 m_pos;
};

void PagePlayer(int pId, const char *msg, ...);

#endif
