//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
// $NoKeywords: $
//=============================================================================//

#ifndef AI_STRATEGIC_H
#define AI_STRATEGIC_H
#ifdef _WIN32
#pragma once
#endif

//#include "shareddefs.h"
#include "hl2wars/rts_shareddefs.h"

// forward declaration
class CAI_BaseNPC;
class CRTSPointOrder;

#define GROUP_MAXSIZE 5

enum group_types
{
	GROUP_DEFENSIVE = 0,
	GROUP_OFFENSIVE,
};

enum group_states
{
	GROUP_IDLING = 0,
	GROUP_MOVING,
};

struct unit_group_t
{
	int m_iID;
	int m_iSize;
	int m_iDesiredSize;

	int m_iType;
	CHandle<CAI_BaseNPC> m_Group[GROUP_MAXSIZE];
	int m_iTargetType;
	EHANDLE pTarget;
	int m_iState;

	DECLARE_CLASS_NOBASE( unit_group_t );
	DECLARE_SIMPLE_DATADESC();
};

// ##################################################################################
//	>> Strategic ai entry
// ##################################################################################
class CAI_Strategic : public CBaseEntity
{
	DECLARE_CLASS( CAI_Strategic, CBaseEntity );
public:
	//DECLARE_SERVERCLASS();
	DECLARE_DATADESC();

	CAI_Strategic();
	// for save/restore
	virtual int						Restore( IRestore &restore );

	virtual void Spawn( void );
	virtual void Activate();
	virtual void SetTeamRTSID( int teamid ) { m_iTeamID = teamid; } 

	void ReconsiderCosts();

	void StrategicThink( void );

	void CheckAlive();
	void MaintainGroups();	// maintains current groups

	bool BuildGroupScheduleBrush();
	bool BuildGroupScheduleModel();
	void BuildGroups();		// creates new groups if our amount of resources permits us that.
	//void MaintainBuildGroups();		// Check if the group is ready, then put it over to the other group vector.

	void AddToGroup( CAI_BaseNPC *pNPC );
	void RemoveFromGroup( CAI_BaseNPC *pNPC, bool ai_ready );
	CBaseEntity *PickTarget( int element );
	bool IsValidTarget( int tid_target );

	void AIScheduleMoveOrder( int element );
	void MoveOrderNormal( CAI_BaseNPC *pNPC, Vector origin, float radius );

	void InputEnable();
	void InputDisable();

	int GetNewID() { return m_iID++; }

	bool IsEnabled() { return m_bEnabled; }
	int GetTeamID() { return m_iTeamID; }

private:
	bool m_bEnabled;

	int m_iTeamID;	// who are we?

	CUtlVector<unit_group_t> m_UnitGroups;
	CUtlVector<unit_group_t> m_UnitGroupsBuilding;
	int m_iNeededMoney;		// needed money for the groups that are being builded currently

	int m_iCheapestUnit;
	int m_iMostExpensiveUnit;

	bool m_bBuildPlan;
	int m_iDesiredSize;
	int m_iDesiredCost;
	int m_iDesiredCostTotal;

	int m_iUnitsQueued;		// the units we queued so far of our current build plan
	float m_fNextTryTime;	// when we couldn't queue all units yet, try again later

	int m_iID;		// id we give to a group
	int m_iLastID;
};

// ##################################################################################
//	>> Strategic manager. Enables/disables a strategic ai in a map
// ##################################################################################
class CAI_StrategicManager : public CLogicalEntity
{
	DECLARE_CLASS( CAI_StrategicManager, CLogicalEntity );
public:
	//DECLARE_SERVERCLASS();
	DECLARE_DATADESC();

	CAI_StrategicManager();
	virtual void Spawn( void );

	void InputEnableStrategicAI( inputdata_t &inputdata );
	void InputDisableStrategicAI( inputdata_t &inputdata );
};

extern CAI_Strategic *g_StrategicAI[MAX_TEAMS_ID_RTS];

#endif // AI_STRATEGIC_H