#ifndef STCRATE_H
#define STCRATE_H

//#if ISDEV()
//#define CRATEMSG
//#endif

#define CRATE_SOLDIER	1
#define CRATE_VEHICLE	2

// Forward
class gzCrateBase;


/***************/
/* Percentages */
/***************/
struct gzCratePercentStruct {
	gzCratePercentStruct();
	void Reset(int Type);

	// Soldier crates
	int Weapon, Money, Points, Vehicle, Death, Ammo, Armor, Health,
		Character, ButterFingers, Refill, Beacon, Spy, Thief, WeaponPack,
		Donation, ChemSuit, ExplosiveSuit, Medic, EnemyThief, MetalGear, 
		Veteran, Hover, StealthMine, Visceroid, BaseDefensePower;

	// Vehicle crates
	int vMaxArmor, vMaxHealth, vAutoRepair, vAntiEnemy, vRepair, vSpy, vDemoTruck, vSteal;
};


/******************/
/* Crate settings */
/******************/
class gzSettingsCrateClass : public stSettingsBase {
public:
	const char *GetName()
	{
		return "gzSettingsCrateClass";
	};
	gzSettingsCrateClass();
	void Delete();
	void Load();

	bool m_enable;
	bool m_enableYellowCrate;
	float m_existCheckTime;
	int m_existCheckVariationMin;
	int m_existCheckVariationMax;
	float m_liveTime;
	float m_vehFacing[2];
	float m_vehPFacing[2];
	nc_Vector3 m_vehSpawn[2];
	nc_Vector3 m_vehPSpawn[2];
	gzCratePercentStruct *m_percent;
	aVector<nc_Vector3> m_posList;
};


/****************/
/* Data storage */
/****************/
struct gzCrateStealthMineStruct {
	nc_cPlayer *owner;
	int count;
	aVector<unsigned int> activeList;
};
struct gzCrateVehicleAutoRepairStruct {
	unsigned int vehId;
	float counter;
};
struct gzCrateBasePowerStruct {
	gzCrateBasePowerStruct()
	{
		this->enable   = false;
		this->team     = -1;
		this->counter  = 0.0f;
		this->building = NULL;
		this->powered  = true;
	};
	bool                enable;
	int                 team;
	float               counter;
	nc_BuildingGameObj* building;
	bool                powered;
};
struct gzCrateDataStruct {
	~gzCrateDataStruct()
	{
		this->MetalGear.Clear();
		this->ExplosiveSuit.Clear();
		this->ChemSuit.Clear();
		this->Hover.Clear();
		for (unsigned int i = 0; i < this->StealthMine.Count(); i++)
		{
			this->StealthMine[i]->activeList.Clear();
			delete this->StealthMine[i];
		}
		this->Spy.Clear();
		this->StealthMine.Clear();
		this->VehicleAutoRepair.Clear();
		this->DemoTruck.Clear();
		this->VehicleAntiEnemy.Clear();
	};
	aVector<unsigned int> Spy;
	aVector<unsigned int> MetalGear;
	aVector<unsigned int> ExplosiveSuit;
	aVector<unsigned int> ChemSuit;
	aVector<unsigned int> Hover;
	aVector<gzCrateStealthMineStruct *> StealthMine;
	gzCrateBasePowerStruct BasePower;

	// Vehicle stuff
	aVector<gzCrateVehicleAutoRepairStruct> VehicleAutoRepair;
	aVector<unsigned int> DemoTruck;
	aVector<unsigned int> VehicleAntiEnemy;
};


/*****************/
/* Crate manager */
/*****************/
class gzManagerCrateClass : public EventHandler, public gzSettingsEvent {
	friend class gzCrateBase;

	float m_nextCheckCounter;
	float m_liveCounter;
	int m_lastSpawnIndex;
	//static aVector<gzCrateBase *> m_list;
	static aList<gzCrateBase> m_list;
public:
	const char *GetName()
	{
		return "gzCrateManager";
	};
	gzManagerCrateClass();
	void Delete();
	void Level_Loaded();
	void Think();
	void Player_Joined(gzEventPlayerBase &);
	void Player_Chat(gzEventPlayerChat &);
	void Player_Purchase(gzEventPlayerPurchase &);
	void Object_Damaged(gzEventObjectDamage &);
	void Object_Killed(gzEventObjectKill &);
	void Object_Transition(gzEventObjectTransition &);
	void Object_SoldierSquished(gzEventObjectKill &);
	void Object_C4Creation(gzEventObjectC4Creation &);
	void Object_C4Detonate(gzEventObjectC4Detonation &);
	void Object_PowerupGrant(gzEventObjectPowerupGrant &);
	void Settings_Loaded();

	unsigned int m_crateId;
	gzSettingsCrateClass *m_settings;
	gzCrateDataStruct *m_data;
};
extern gzManagerCrateClass *gzCrateMgr;


/**************/
/* Crate base */
/**************/
class gzCrateBase {
	friend class gzManagerCrateClass;
protected:
	static const gzCratePercentStruct *m_percent;
public:
	gzCrateBase()
	{
		this->m_hitCount	= 0;
		this->m_selected	= false;
		gzManagerCrateClass::m_list.AddTail(this);
	};
	virtual const char *GetName() = 0;
	virtual int GetType() = 0;
	virtual unsigned int GetPercent() = 0;
	virtual bool SkipDefaultOutput()
	{
		return true;
	};
	virtual bool Pick(nc_SmartGameObj *) = 0;
	int m_hitCount;
	bool m_selected;
};


/*************************/
/* Yellow crate override */
/*************************/
class M00_CNC_Crate : public nc_ScriptImpClass {
public:
	void Custom(nc_ScriptableGameObj *obj, int message, int param, nc_ScriptableGameObj *sender);
};

#endif
