#ifndef BOT_COMBO_H
#define BOT_COMBO_H
#include "bot_types.h"

// Combo entry classes

class CBaseBotComboEntry
{
protected:
	EState m_eComboEntryState;
	CBot *m_pBot;
	float m_fStartTime; // Time when the combo entry actually starts(thus after the delay)
	float m_fCreateTime; // Time that this combo entry was send as the current entry
	friend class CBotCombo;

public:
	CBaseBotComboEntry(CBot *pB) : m_pBot(pB), m_eComboEntryState(NOT_STARTED) {};
	virtual ~CBaseBotComboEntry(void) {};
	virtual void Think(void) = 0;
	virtual void Activate(void) { m_fStartTime = gpGlobals->time; m_eComboEntryState = BUSY;};
	virtual float GetDelay(void) { return 0.0f; };
};

class CTeleportComboEntry: public CBaseBotComboEntry
{
	float m_fTeleDelay;
	int m_iTeleDir;
	bool m_bAimAtEnemy;
	bool m_bNeedEnemy;
	bool m_bStopWhenEnemySwoops;

public:
	CTeleportComboEntry(CBot *pB, float flTDelay, int TeleDir,
						bool AimEnemy = false, bool NeedEnemy = false,
						bool StopWhenEnemySwoops = false) : CBaseBotComboEntry(pB),
								 							m_fTeleDelay(flTDelay),
															m_iTeleDir(TeleDir),
															m_bAimAtEnemy(AimEnemy),
															m_bNeedEnemy(NeedEnemy),
															m_bStopWhenEnemySwoops(StopWhenEnemySwoops) {};
	virtual void Think(void);
	virtual void Activate() { CBaseBotComboEntry::Activate(); m_fTeleDelay += gpGlobals->time; };
};

class CStartSwoopComboEntry: public CBaseBotComboEntry
{
	bool m_bTappedOnce;
	float m_fLifeTime;
	int m_iSwoopDir;
	float m_fTapDelay;
	float m_fStartDelay;

public:
	CStartSwoopComboEntry(CBot *pB, bool Tapped, int SwoopDir);
	virtual void Think(void);
	virtual float GetDelay(void);
	virtual void Activate(void);
	virtual ~CStartSwoopComboEntry(void) {};
};

class CFallDownComboEntry: public CBaseBotComboEntry
{
	float m_fLifeTime;

public:
	CFallDownComboEntry(CBot *pB) : CBaseBotComboEntry(pB), m_fLifeTime(1.5f) {};
	virtual void Think(void);
	virtual float GetDelay(void) { return 0.0f; };
	virtual void Activate(void) { CBaseBotComboEntry::Activate(); m_fLifeTime += gpGlobals->time; };
	virtual ~CFallDownComboEntry(void) {};
};

class CPowerupComboEntry: public CBaseBotComboEntry
{

public:
	CPowerupComboEntry(CBot *pB) : CBaseBotComboEntry(pB) {};
	virtual void Think(void);
	virtual float GetDelay(void) { return 0.0f; };
	virtual ~CPowerupComboEntry(void) {};
};

class CAscendComboEntry: public CBaseBotComboEntry
{
	float m_fLifeTime;

public:
	CAscendComboEntry(CBot *pB) : CBaseBotComboEntry(pB), m_fLifeTime(1.5f) {};
	virtual void Think(void);
	virtual float GetDelay(void) { return 0.0f; };
	virtual void Activate(void) { CBaseBotComboEntry::Activate(); m_fLifeTime += gpGlobals->time; };
	virtual ~CAscendComboEntry(void) {};
};

class CCheckFOVForAimComboEntry: public CBaseBotComboEntry
{
	float m_fLifeTime;

public:
	CCheckFOVForAimComboEntry(CBot *pB) : CBaseBotComboEntry(pB), m_fLifeTime(0.25f) {};
	virtual void Think(void);
	virtual float GetDelay(void) { return 0.0f; };
	virtual void Activate(void) { CBaseBotComboEntry::Activate(); m_fLifeTime += gpGlobals->time; };
	virtual ~CCheckFOVForAimComboEntry(void) {};
};

class CChargeGenBallComboEntry: public CBaseBotComboEntry
{
public:
	CChargeGenBallComboEntry(CBot *pB) : CBaseBotComboEntry(pB) {};
	virtual void Think(void);
	virtual float GetDelay(void) { return 0.0f; };
	virtual ~CChargeGenBallComboEntry(void) {};
};

class CSwoopCloseToEnemyComboEntry: public CBaseBotComboEntry
{
public:
	CSwoopCloseToEnemyComboEntry(CBot *pB) : CBaseBotComboEntry(pB) {};
	virtual void Think(void);
	virtual float GetDelay(void) { return 0.0f; };
	virtual ~CSwoopCloseToEnemyComboEntry(void) {};
};

class CAvoidAttackWhileSwoopComboEntry: public CBaseBotComboEntry
{
public:
	CAvoidAttackWhileSwoopComboEntry(CBot *pB) : CBaseBotComboEntry(pB) {};
	virtual void Think(void);
	virtual float GetDelay(void) { return 0.0f; };
	virtual ~CAvoidAttackWhileSwoopComboEntry(void) {};
};

class CSwoopAWhileComboEntry: public CBaseBotComboEntry
{
	float m_fLifeTime;

public:
	CSwoopAWhileComboEntry(CBot *pB, float LT) : CBaseBotComboEntry(pB), m_fLifeTime(LT) {};
	virtual void Think(void);
	virtual float GetDelay(void) { return 0.0f; };
	virtual void Activate(void) { CBaseBotComboEntry::Activate(); m_fLifeTime += gpGlobals->time; };
	virtual ~CSwoopAWhileComboEntry(void) {};
};	

// Combo manager for bots
class CBotCombo
{
	TLinkedList<CBaseBotComboEntry*> m_ComboList;
	CBaseBotComboEntry *m_pCurrentComboEntry;
	CBot *m_pBot;

public:
	EState m_eComboState;
	ETaskCode m_eTaskAfterCombo;

	CBotCombo(CBot *pB, EComboType CT);
	~CBotCombo(void);

	void ExcuteCombo(void);
	bool MakeRandomTeleports(ETeleDir TeleDirLR, ETeleDir TeleDirBF, ETeleDir TeleDirUD);
	void MakePowerup(void);
	float GetSwoopLifeTime(short SDir);
	void Activate(void);
};

#endif