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

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

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

// forward declaration
class CAI_BaseNPC;
class CRTSMapInfo;
class CBuildingBrush;
class CBaseBuildingModel;
class CHL2Wars_Player;

//typedef CUtlVector< CHandle<CAI_BaseNPC> > UnitInfoList;
//typedef CUtlVector<CBaseEntity *> InfoList;
struct UnitParams_t
{
	/*UnitParams_t( void )
	{
		for(int i = 0; i < MAX_TEAMS_ID_RTS; i++ )
			UnitInfoList[i].Purge();
	}*/

	CUtlVector< CHandle<CAI_BaseNPC> > UnitInfoList;

	DECLARE_SIMPLE_DATADESC();
};

// ##################################################################################
//	>> List
// ##################################################################################
struct infolistparams_t
{
	//DECLARE_CLASS_NOBASE( infolistparams_t );
	//DECLARE_DATADESC();

	CUtlVector<EHANDLE> InfoList;

	DECLARE_SIMPLE_DATADESC();
};

class CTeamIDList //: public CBaseEntity
{
	//DECLARE_CLASS( CTeamIDList, CBaseEntity );
	DECLARE_CLASS_NOBASE( CTeamIDList );
public:
	//DECLARE_DATADESC();
	DECLARE_SIMPLE_DATADESC();

	CTeamIDList() : m_bStoreDefaultTeams(false) 
	{
	}

	void SetStoreDefaultTeams( bool store ) { m_bStoreDefaultTeams = store; }

	int GetCount( int teamid );
	CBaseEntity *GetFromList( int teamid, int index );
	bool AddToList( int teamid, CBaseEntity *pEnt );
	bool RemoveFromList( int teamid, CBaseEntity *pEnt );
	void ChangeTeam( int oldteam, int newteam, CBaseEntity *pEnt );
	int GetTotal();

protected:
	bool m_bStoreDefaultTeams;
	infolistparams_t m_InfoList[MAX_TEAMS_ID_RTS + DEFAULT_TEAMS];
};

// ##################################################################################
//	>> Gameroom data, seperated entity, because we restore this on map transition
//  >> We get problems if we do this with the global resources.
// The data it stores: The object contains arrays of MAX_TEAMS_ID_RTS size. These
// are the player slots in the gameroom. The positions are the team id's ingame.
// ##################################################################################
/*class CRTSGRData : public CBaseEntity
{
	DECLARE_CLASS( CRTSGRData, CBaseEntity );
public:
	DECLARE_SERVERCLASS();
	DECLARE_DATADESC();

	CRTSGRData();
	virtual int  UpdateTransmitState(void);

	bool SaveGRData();
	bool RestoreGRData();

	void SetIndex( int slot, int index );
	void SetPosition( int slot, int pos );
	void SetColor( int slot, int color );
	void SetReady( int slot, bool state );
	void SetFaction( int slot, int faction );
	void SetType( int slot, int type );
	void SetGameMode( int gamemode ) { m_iGamemode = gamemode; }

	int GetIndex( int slot ) { return m_iIndex.Get(slot); }
	int GetPosition( int slot ) { return m_iPosition.Get(slot); }
	int GetColor( int slot ) { return m_iColor.Get(slot); }
	bool IsReady( int slot ) { return m_bReady.Get(slot); }
	int GetFaction( int slot ) { return m_iFaction.Get(slot); }
	int GetType( int slot ) { return m_iType.Get(slot); }
	int GetGameMode() { return m_iGamemode; }

public:
	bool m_bGRActive;
	char m_szName[MAX_TEAMS_ID_RTS][ MAX_PLAYER_NAME_LENGTH ];

private:
	CNetworkArray( int, m_iType, MAX_TEAMS_ID_RTS );
	CNetworkArray( int, m_iIndex, MAX_TEAMS_ID_RTS );
	CNetworkArray( int, m_iPosition, MAX_TEAMS_ID_RTS );
	CNetworkArray( int, m_iColor, MAX_TEAMS_ID_RTS );
	CNetworkArray( bool, m_bReady, MAX_TEAMS_ID_RTS );
	CNetworkArray( int, m_iFaction, MAX_TEAMS_ID_RTS );

	int			m_iGamemode;
};

extern CRTSGRData *g_pRTSGRData;*/

// ##################################################################################
//	>> Gameroom data struct. Will be saved globally between map exchange
// ##################################################################################
struct gameroom_data_t
{
public:
	bool	m_bGRActive;

	int		m_iGamemode;

	char	m_szName[MAX_TEAMS_ID_RTS][ MAX_PLAYER_NAME_LENGTH ];

	int		m_iType[MAX_TEAMS_ID_RTS];
	int		m_iPosition[MAX_TEAMS_ID_RTS];
	int		m_iColor[MAX_TEAMS_ID_RTS];
	int		m_iFaction[MAX_TEAMS_ID_RTS];
};

// ##################################################################################
//	>> MP Start point
// ##################################################################################
class CRTSStartPointMP : public CPointEntity
{
	DECLARE_CLASS( CRTSStartPointMP, CPointEntity );
public:
	//DECLARE_SERVERCLASS();
	DECLARE_DATADESC();

	int GetTeamID() { return m_iTeamID; }
private:
	int m_iTeamID;
};

// ##################################################################################
//	>> Global data
// ##################################################################################
class CRTSResource : public CBaseEntity
{
	DECLARE_CLASS( CRTSResource, CBaseEntity );
public:
	DECLARE_SERVERCLASS();
	DECLARE_DATADESC();

	CRTSResource();
	virtual void Spawn( void );
	virtual void Activate();
	virtual void PostClientActive( void );
	virtual void ResourceThink( void );

	void	UpdateOnRemove();

	void		RequestTeamRTSID( CBasePlayer *pRequestingPlayer );
	void		InvalidateTeamIDS();

	//virtual void UpdateAssignedTeamIDS( void );
	virtual int  UpdateTransmitState(void);

	// Get player, assumes only one player is controlling this team id
	CHL2Wars_Player *GetPlayerTeamID( int team_id );

	// unit list functions
	int			GetSize( int team_id );
	CAI_BaseNPC *GetUnit( int team_id, int index );
	void		AddUnit( int team_id, CAI_BaseNPC *pNPC  );
	void		RemoveUnit( int team_id, CAI_BaseNPC *pNPC );
	void		ChangeTeamUnit( int oldTeam_id, int newTeam_id, CAI_BaseNPC *pNPC ); 

	// resource related functions
	int			GetResources( int team_id );
	void		AddResources( int team_id, int resources );
	void		RemoveResources( int team_id, int resources );
	void		SetResources( int team_id, int resources );

	// building related
	void		RegisterBuilding( CBuildingBrush *pBuilding, int teamid );
	void		RegisterBuilding( CBaseBuildingModel *pBuilding, int teamid );
	void		RegisterBuildingFinal();
	void		UnRegisterBuilding( CBuildingBrush *pBuilding, int teamid );
	void		UnRegisterBuilding( CBaseBuildingModel *pBuilding, int teamid );
	int			GetModelBuildingCount( int teamid ) { return m_pBuildingModelList->GetCount(teamid); }
	int			GetBuildingCount( int teamid ) { return m_pBuildingList->GetCount(teamid); }

	// lookup tech tree, and check if the requirements are fullfilled.
	void		InitTechTree( int teamid );
	void		InitTreePlayer( CBasePlayer *client );
	void		UpdateTechTree( int teamid, const char *changed, int count );
	int			NewAbilityState( int teamid, bool state, bool overridable, int count, ABILITY_FILE_INFO_HANDLE handle );
	void		ModifyAbilityState( int teamid, bool state, ABILITY_FILE_INFO_HANDLE handle );
	void		SetAbilityOverridable( int teamid, bool state, ABILITY_FILE_INFO_HANDLE handle );
	int			GetAbilityCount( int teamid, ABILITY_FILE_INFO_HANDLE handle );
	bool		IsAbilityAvailable( int teamid, ABILITY_FILE_INFO_HANDLE handle );
	bool		IsUnitAvailable( int teamid, UNIT_FILE_INFO_HANDLE handle );

	Vector		GetColor( int team_id ) { return m_vTeamColorTable.Get( team_id ); };
	Vector		GetColor255( int team_id );

	// getter for unit index. Automatically adds the unit type to the list, if the unit doesn't exists yet.
	int			GetUnitIndex( const char *unit_type );
	string_t	GetUnitType( int unit_index );

	// for save/restore, link up the global resource again
	virtual int	Restore( IRestore &restore );

public:
	// update gameroom info. Possible use this system also ingame.
	void		UpdateGameRoomInfo();
	CBasePlayer *FindGameMaster();
	void		SendGRMapList( CBasePlayer *client );

	// updating slots
	virtual		void ManageSlots();
	virtual		void UpdateSlots();
	virtual		int FindFreeSlot();
	virtual		bool HasSlot( CBasePlayer *pPlayer );
	void		SlotOpen( int slot );
	void		SlotMovePlayer( int old_slot, int new_slot );
	void		SlotAddCPU( int slot  );
	void		SetGRReady( int slot, int state );
	bool		IsPositionFree( int position ) { return !m_bPositionInUse.Get(position); }
	bool		IsPositionAvailable( int position ) { return m_bPositionsAvailable[position]; }
	//int			FindFreePosition();
	void		SetGRPosition( int slot, int position );
	void		SetGRFaction( int slot, int faction );
	void		SetGRMap( const char *pMapName );
	void		SendMapInfoToPlayer( CBasePlayer *pPlayer );

	// color handling
	int			FindFreeColor();
	bool		IsColorFree( int color ) { return !m_bColorInUse.Get(color); }
	void		SetGRColor( int slot, int color );
	Vector		TranslateColor( int color );

	void		GRLaunchGame( CBasePlayer *pPlayer );	// save this entity and launch game

	// GR data
	bool SaveGRData();
	bool RestoreGRData();

	void SetIndex( int slot, int index );
	void SetPosition( int slot, int pos );
	void SetColor( int slot, int color );
	void SetReady( int slot, bool state );
	void SetFaction( int slot, int faction );
	void SetType( int slot, int type );
	void SetGameMode( int gamemode ) { m_iGamemode = gamemode; }

	int GetIndex( int slot ) { return m_iIndex.Get(slot); }
	int GetPosition( int slot ) { return m_iPosition.Get(slot); }
	int GetColorGR( int slot ) { return m_iColor.Get(slot); }
	bool IsReady( int slot ) { return m_bReady.Get(slot); }
	int GetFaction( int slot ) { return m_iFaction.Get(slot); }
	int GetType( int slot ) { return m_iType.Get(slot); }
	int GetGameMode() { return m_iGamemode; }

protected:
	// rts data of all available team id's
	UnitParams_t m_UnitInfoList[MAX_TEAMS_ID_RTS];

	int m_iResources[MAX_TEAMS_ID_RTS];

	CNetworkArray( Vector, m_vTeamColorTable, MAX_TEAMS_ID_RTS + DEFAULT_TEAMS );
	CNetworkArray( bool, m_bColorInUse, TOTAL_COLORS );
	CNetworkArray( bool, m_bPositionInUse, MAX_TEAMS_ID_RTS );
	CNetworkArray( int, m_iFaction, MAX_TEAMS_ID_RTS );

	// this info needs to be send in a message to the players (gamelobby)
	bool m_bPositionsAvailable[MAX_TEAMS_ID_RTS];
	Vector m_vPositionsOrigin[MAX_TEAMS_ID_RTS];
	char m_sNum_players[5];

	// -- gameroom info
	CHandle<CBasePlayer>m_pSlotPlayers[MAX_TEAMS_ID_RTS];
	char m_iszSelectedMap[32];
	CNetworkHandle(CBasePlayer, m_hGameMaster);

public:
	CTeamIDList *m_pBuildingList;
	CTeamIDList *m_pBuildingModelList;
	CTeamIDList *m_pCapturePointList;

	// this defines per teamid about the available abilities.
	CUtlMap < unsigned short, ability_state_t > m_AbilityStates[MAX_TEAMS_ID_RTS];

// gr data
public:
	bool m_bGRActive;
	char m_szName[MAX_TEAMS_ID_RTS][ MAX_PLAYER_NAME_LENGTH ];

private:
	CNetworkArray( int, m_iType, MAX_TEAMS_ID_RTS );
	CNetworkArray( int, m_iIndex, MAX_TEAMS_ID_RTS );
	CNetworkArray( int, m_iPosition, MAX_TEAMS_ID_RTS );
	CNetworkArray( int, m_iColor, MAX_TEAMS_ID_RTS );
	CNetworkArray( bool, m_bReady, MAX_TEAMS_ID_RTS );
	//CNetworkArray( int, m_iFaction, MAX_TEAMS_ID_RTS );

	int			m_iGamemode;

private:
	bool	m_bLevelInit;
};

extern CRTSResource *g_pRTSResource;
extern Disposition_t g_RelationshipsRTS[MAX_TEAMS_ID_RTS][MAX_TEAMS_ID_RTS];

#endif // RTS_RESOURCE_H
