//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: This thing doesn't counts correctly sometimes
//
//=============================================================================//

#include "cbase.h"
#include "hl2wars/rts_capture_point.h"
#include "ai_basenpc.h"
#include "hl2wars/rts_globalresource.h"
#include "hl2wars/util_hl2wars.h"
#include "hl2wars/util_hl2wars_shared.h"
#include "hl2wars/hl2wars_player.h"
#include "hl2wars/rts_shareddefs.h"

LINK_ENTITY_TO_CLASS( rts_capture_point, CCapturePoint );

#define CAPTURE_THINK_CONTEXT		"CaptureThinkContext"

BEGIN_DATADESC( CCapturePoint )
	DEFINE_FUNCTION( CaptureThink ),

	// fields
	//DEFINE_FIELD( m_flRemainingCaptureTime, FIELD_FLOAT ),
	DEFINE_FIELD( m_vIconTarget, FIELD_VECTOR ),
	DEFINE_FIELD( m_iTeamCapturing, FIELD_INTEGER ),
	DEFINE_FIELD( m_flNextCaptureTime, FIELD_TIME ),
	DEFINE_FIELD( m_flNextAddResourceTime, FIELD_TIME ),

	// keyfields
	DEFINE_KEYFIELD( m_iTeamOwnership, FIELD_INTEGER, "ownership" ),
	DEFINE_KEYFIELD( m_sCapturePointIcon, FIELD_STRING, "capturepointicon" ),

	// input
	DEFINE_INPUTFUNC(FIELD_INTEGER, "changeownership", InputChangeOwnerShip),

	// output
	DEFINE_OUTPUT( m_OnCapturedAll, "OnCaptured_all"),

	DEFINE_OUTPUT( m_OnCaptured[0], "OnCaptured_3"),
	DEFINE_OUTPUT( m_OnCaptured[1], "OnCaptured_4"),
	DEFINE_OUTPUT( m_OnCaptured[2], "OnCaptured_5"),
	DEFINE_OUTPUT( m_OnCaptured[3], "OnCaptured_6"),
	DEFINE_OUTPUT( m_OnCaptured[4], "OnCaptured_7"),
	DEFINE_OUTPUT( m_OnCaptured[5], "OnCaptured_8"),
	DEFINE_OUTPUT( m_OnCaptured[6], "OnCaptured_9"),
	DEFINE_OUTPUT( m_OnCaptured[7], "OnCaptured_10"),

	DEFINE_OUTPUT( m_OnLost[0], "OnLost_3"),
	DEFINE_OUTPUT( m_OnLost[1], "OnLost_4"),
	DEFINE_OUTPUT( m_OnLost[2], "OnLost_5"),
	DEFINE_OUTPUT( m_OnLost[3], "OnLost_6"),
	DEFINE_OUTPUT( m_OnLost[4], "OnLost_7"),
	DEFINE_OUTPUT( m_OnLost[5], "OnLost_8"),
	DEFINE_OUTPUT( m_OnLost[6], "OnLost_9"),
	DEFINE_OUTPUT( m_OnLost[7], "OnLost_10"),

END_DATADESC()

IMPLEMENT_SERVERCLASS_ST( CCapturePoint, DT_CapturePoint )
	//SendPropFloat	(SENDINFO(m_flRemainingCaptureTime), 0, SPROP_NOSCALE ),
	SendPropFloat	(SENDINFO(m_flNextCaptureTime), 0, SPROP_NOSCALE ),
	SendPropInt		(SENDINFO(m_iTeamOwnership), 4 ),
	SendPropInt		(SENDINFO(m_iTeamCapturing), 4 ),
	SendPropVector	(SENDINFO(m_vIconTarget), -1, SPROP_COORD ),
END_SEND_TABLE()

CCapturePoint::CCapturePoint()
{
}

void CCapturePoint::Precache( void )
{
	BaseClass::Precache();

	PrecacheModel( "vgui/icons/icon_capturepoint.vmt" );
}

void CCapturePoint::UpdateOnRemove()
{
	if( m_hSprite )
	{
		UTIL_Remove( m_hSprite );
		m_hSprite.Set( NULL );
	}

	BaseClass::UpdateOnRemove();
}

//-----------------------------------------------------------------------------
// Purpose: Called when spawning, after keyvalues have been handled.
//-----------------------------------------------------------------------------
void CCapturePoint::Spawn( void )
{
	Precache();

	BaseClass::Spawn();

	// register this point
	g_pRTSResource->m_pCapturePointList->AddToList( m_iTeamOwnership, this );

	// at spawn, no team is capturing this point
	m_iTeamCapturing = -1;

	// find out where we will render the capture point icon
	CBaseEntity	*pEntTarget = NULL;
	pEntTarget = gEntList.FindEntityByName( pEntTarget, m_sCapturePointIcon );
	if( pEntTarget ) {
		m_vIconTarget = pEntTarget->GetAbsOrigin();
	}
	else {
		DevMsg("A capture point has no capture point icon target! \n");
		m_vIconTarget = GetAbsOrigin();
	}

	// create a sprite
	m_hSprite = CSprite::SpriteCreate( "vgui/icons/icon_capturepoint.vmt", m_vIconTarget, false );
	CSprite *pSprite = (CSprite *)m_hSprite.Get();
	if ( pSprite )
	{
		pSprite->SetTransparency( kRenderTransAlpha, 255, 255, 255, 255, kRenderFxNoDissipation );
		pSprite->SetBrightness( 255, 0.5f );
		pSprite->SetScale( 0.5f, 0.0f );
		pSprite->TurnOn();
	}

	// ctriggermultiple parent has his own think function for multiple touches, so we create another think function
	SetContextThink( &CCapturePoint::CaptureThink, gpGlobals->curtime, CAPTURE_THINK_CONTEXT );
}

//-----------------------------------------------------------------------------
// Purpose: Find out if someone is capturing it, and if we need to change the 
//			ownership. Also check if we need to add some resources to a team.
//-----------------------------------------------------------------------------
void CCapturePoint::CaptureThink( void )
{
	// By default...
	SetContextThink( &CCapturePoint::CaptureThink, gpGlobals->curtime + 0.5, CAPTURE_THINK_CONTEXT );

	// update color ownership sprite
	Vector color = g_pRTSResource->GetColor255( GetOwnerShip() );
	CSprite *pSprite = (CSprite *)m_hSprite.Get();
	if ( pSprite )
	{
		pSprite->SetColor( color.x, color.y, color.z );
	}

	// get the teamid capturing, update if necessary
	int team_capturing = UpdateTeamCapturing();
	//Msg("\n");
	if( team_capturing != m_iTeamCapturing )
	{
		m_iTeamCapturing = team_capturing;
		m_flNextCaptureTime = gpGlobals->curtime + CAPTURE_TIME;
	}

	// if a teamid is capturing, check if captured
	if( m_iTeamCapturing != -1 )
	{
		//m_flRemainingCaptureTime = m_flNextCaptureTime - gpGlobals->curtime;
		if( m_flNextCaptureTime < gpGlobals->curtime ) {
			int team_lost = m_iTeamOwnership;
			ChangeOwnerShip( m_iTeamCapturing );
			m_iTeamCapturing = -1;
			m_OnCaptured[m_iTeamOwnership - DEFAULT_TEAMS].FireOutput( this, this );
			m_OnCapturedAll.FireOutput( this, this );
			m_OnLost[team_lost - DEFAULT_TEAMS].FireOutput(  this, this );

			UTIL_HudStrategyText( (CBasePlayer *)g_pRTSResource->GetPlayerTeamID(m_iTeamOwnership), "#HLW_POINTCAPTURED", S_GREEN );
			UTIL_HudStrategyText( (CBasePlayer *)g_pRTSResource->GetPlayerTeamID(team_lost), "#HLW_POINTLOST", S_RED );
		}
	}

	// add resources
	if( UTIL_IsValidTeam(m_iTeamOwnership, false) ) {
		if( m_flNextAddResourceTime < gpGlobals->curtime ) {
			g_pRTSResource->AddResources( m_iTeamOwnership, CAPTURE_ADDRESOURCES );
			m_flNextAddResourceTime = gpGlobals->curtime + CAPTURE_NEXTADDRES;
		}
	}
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
int CCapturePoint::UpdateTeamCapturing()
{
	int team_capturing = -1;
	CAI_BaseNPC *pNPC = NULL;
	for( int i = 0; i < m_hTouchingEntities.Count(); i++ )
	{
		if( m_hTouchingEntities.Element(i) && m_hTouchingEntities.Element(i)->IsNPC() )
		{
			pNPC = m_hTouchingEntities.Element(i)->MyNPCPointer();
			if( !pNPC || !pNPC->IsAlive() )
				continue;

			//Msg("NPC touching of teamid %d\n", pNPC->GetTeamRTSID() );
			// not a valid team
			if( !UTIL_IsValidTeam( pNPC->GetTeamRTSID(), false ) )
				continue;

			// we are already capturing it
			if( pNPC->GetTeamRTSID() == team_capturing )
				continue;

			// owners need to be removed before this point can be captured
			if( pNPC->GetTeamRTSID() == m_iTeamOwnership )
			{
				return -1;
			}

			// Nobody is capturing it, so we are going to capture it
			if( team_capturing == -1 )
			{
				team_capturing = pNPC->GetTeamRTSID();
			}

			// this means multiple npc's of different teamid's are on the point
			if( team_capturing != pNPC->GetTeamRTSID() )
			{
				return -1;
			}

		}
	}	

	return team_capturing;
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CCapturePoint::ChangeOwnerShip( int new_team )
{
	g_pRTSResource->m_pCapturePointList->RemoveFromList( m_iTeamOwnership, this );
	g_pRTSResource->m_pCapturePointList->AddToList( new_team, this );
	m_iTeamOwnership = new_team;	
}

//-----------------------------------------------------------------------------
// Purpose: 
// Input  : inputdata_t &inputdata
//-----------------------------------------------------------------------------
void CCapturePoint::InputChangeOwnerShip( inputdata_t &inputdata )
{
	ChangeOwnerShip( inputdata.value.Int() );
}

