#ifndef STANTICHEAT_H
#define STANTICHEAT_H

class gzPlayer;

#ifdef DEVMSG
#define ROFMSG
#endif

struct gzSettingsRoFStruct {
	bool	Enable;
	float	VariationAllowance;
};
class gzSettingsAntiCheatClass : public stSettingsBase {
public:
	const char *GetName()
	{
		return "gzSettingsAntiCheatClass";
	};
	void Load();

	bool	m_enableSpectate;
	float	m_ammoLive;
	gzSettingsRoFStruct RoF;
};

class gzAntiCheatBaseClass : public EventHandler {
protected:
	gzPlayer*    m_owner;
	unsigned int m_soldierId;
public:
	gzAntiCheatBaseClass(gzPlayer *owner);
	virtual void WriteLog(const char *msg, ...);
};


#define ANTICHEAT_RGHSPEC_INTERVAL 1.0f

struct gzRGHSpecDataStruct {
	unsigned int objId;
	unsigned long lastSeen;
};
class gzAntiCheatSpec : public gzAntiCheatBaseClass {
	float m_checkTimeCounter;
public:
	const char *GetName()
	{
		return "gzAntiCheatSpec";
	};
	gzAntiCheatSpec(gzPlayer *);
	void Delete();
	void Level_Loaded();
	void Think();
	void Player_RawDamage(gzEventObjectDamage &);
	void Object_Created(gzEventObjectCreate &);
	aVector<gzRGHSpecDataStruct *> m_data;
};


struct gzRoFWeaponDataStruct;
struct gzRoFAmmoDataStruct {
	gzRoFWeaponDataStruct *Weapon;
	nc_AmmoDefinitionClass *AmmoDef;
	float counter;
	float cycleInterval;
	int hitCount;
	int maximumHit;
	float measureTime;
	int meansureCycle;
	int additionMaxHit;
	float DeleteCounter;

	// Ammo decrypted values. Save CPU resource to decrypt when we need it!
	float AmmoDamage;
	int   AmmoWarhead;
	int   AmmoSprayCount;
	int   WeapClipSize;
	float WeapReloadTime;
	
};
struct gzRoFWeaponDataStruct {
	aVector<gzRoFAmmoDataStruct *> ammoList;
	nc_WeaponDefinitionClass *WeaponDef;
	float lastSelectTime;
};
struct gzRoFHitDataStruct {
	int weaponId;
	int ammoId;
};
class gzAntiCheatWeapons : public gzAntiCheatBaseClass {
	aVector<gzRoFWeaponDataStruct *> m_data;
public:
	const char *GetName()
	{
		return "gzAntiCheatWeapons";
	};
	void Delete();
	gzAntiCheatWeapons(gzPlayer *);
	void Level_Loaded();
	void Think();
	void Player_RawDamage(gzEventObjectDamage &);
	void Object_Transition(gzEventObjectTransition &);
	void AddAmmo(nc_AmmoDefinitionClass *ammo, gzRoFWeaponDataStruct &weapon);
	bool IsAmmoExpired(gzRoFWeaponDataStruct *weapon);
	void AddHitCount(gzRoFAmmoDataStruct *, gzEventObjectDamage);
	float GetWeaponLastSelectTime(gzRoFWeaponDataStruct *weapon);
};


#define ANTICHEAT_HITLOG_LIVE 2
struct gzHitLogStruct {
	float m_damage;
	unsigned long m_time;
	unsigned int m_obj;
};
class gzAntiCheatHitLog : public gzAntiCheatBaseClass {
	aVector<gzHitLogStruct> m_data;
	float m_checkCounter;
public:
	const char *GetName()
	{
		return "gzAntiCheatHitLog";
	};
	gzAntiCheatHitLog(gzPlayer *);
	void Delete();
	void Level_Loaded();
	void Think();
	void Player_RawDamage(gzEventObjectDamage &);
	gzHitLogStruct *GetLast(unsigned int objId);
	int GetHitCount(unsigned int objId, unsigned long interval);
	void Remove(unsigned int objId);
};

class gzAntiCheatManager : public EventHandler {
public:
	const char *GetName()
	{
		return "gzAntiCheatManager";
	};
	gzAntiCheatManager();
	void Delete();

	gzSettingsAntiCheatClass *m_settings;
};
extern gzAntiCheatManager *gzAntiCheatMgr;

#endif
