//========= Copyright © 1996-2005, Sander Corporation, All rights reserved. ============//
//
// Purpose: 
//
//=============================================================================//

#include "cbase.h"
#include "hl2wars/rts_order_trigger.h"
#include "hl2_shareddefs.h"
#include "player.h"
#include "EntityList.h"
#include "filters.h"
#include "hl2wars/hl2wars_player.h"
#include "hl2wars/rts_point_order.h"
#include "hl2wars/util_hl2wars.h"

LINK_ENTITY_TO_CLASS( rts_order_trigger, COrderRTSTrigger );

BEGIN_DATADESC( COrderRTSTrigger )
	DEFINE_KEYFIELD( m_pOwner, FIELD_STRING, "owner" ),
	DEFINE_FIELD( m_hOwner, FIELD_EHANDLE ),
	DEFINE_KEYFIELD( m_pOrderPositions, FIELD_STRING, "orderPositions" ),
	DEFINE_KEYFIELD( m_pDefaultPosition, FIELD_STRING, "defaultPosition" ),
	DEFINE_KEYFIELD( m_iOrderType, FIELD_INTEGER, "orderType" ),
	DEFINE_KEYFIELD( m_iFilterName,	FIELD_STRING,	"filtername" ),
	DEFINE_FIELD( m_hFilter,	FIELD_EHANDLE ),
	DEFINE_KEYFIELD( m_fSearchRadius, FIELD_FLOAT, "searchRadius" ),
END_DATADESC()

//server data table describing networked member variables (SendProps)
IMPLEMENT_SERVERCLASS_ST( COrderRTSTrigger, DT_OrderRTSTrigger )
	SendPropEHandle		( SENDINFO( m_hOwner)),
END_SEND_TABLE()

//-----------------------------------------------------------------------------
// Purpose: Construct the slots for covering
//-----------------------------------------------------------------------------
COrderRTSTrigger::COrderRTSTrigger() 
{
}

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

//------------------------------------------------------------------------------
// Purpose :
//------------------------------------------------------------------------------
void COrderRTSTrigger::Activate( void ) 
{ 
	// Get a handle to my filter entity if there is one
	if (m_iFilterName != NULL_STRING)
	{
		m_hFilter = dynamic_cast<CBaseFilter *>(gEntList.FindEntityByName( NULL, m_iFilterName ));
	}

	m_hOwner.Set( dynamic_cast<CBaseEntity *>(gEntList.FindEntityByName( NULL, STRING( m_pOwner ) ) ) );

	BaseClass::Activate();
}

//-----------------------------------------------------------------------------
// Purpose: Being called on right click
//-----------------------------------------------------------------------------
void COrderRTSTrigger::OnClickRight( CBasePlayer *pActivator ) 
{
	BaseClass::OnClickRight( pActivator );

	FindOrderPositions( true );
}

//-----------------------------------------------------------------------------
// Purpose: Being called on right double click
//-----------------------------------------------------------------------------
void COrderRTSTrigger::OnClickRightDouble( CBasePlayer *pActivator ) 
{
	BaseClass::OnClickRight( pActivator );

	FindOrderPositions( true );
}

//-----------------------------------------------------------------------------
// Purpose: Find cover!
//-----------------------------------------------------------------------------
void COrderRTSTrigger::FindOrderPositions( bool bRun ) 
{
	CHL2Wars_Player *pPlayer = NULL;
	if ( m_hActivator && m_hActivator->IsPlayer() )
	{
		pPlayer = (CHL2Wars_Player *)m_hActivator.Get();
	}

	if( !pPlayer )
		return;

	// get the first cover position
	CBaseEntity *pPos = NULL;
	pPos = gEntList.FindEntityByNameWithin( NULL, STRING( m_pOrderPositions ), GetAbsOrigin(), 1024.0f );
	
	// get the default pos
	CBaseEntity *pDefaultPos = NULL;
	pDefaultPos = gEntList.FindEntityByNameWithin( NULL, STRING( m_pDefaultPosition ), GetAbsOrigin(), 1024.0f );

	// get the filter
	CBaseFilter *pFilter = m_hFilter.Get();
	bool passesFilter = false;


	// loop through all selected npc's
	for( int i = 0; i < pPlayer->CountUnits(); i++ ) {
		if( pPlayer->GetUnit(i) && pPlayer->GetUnit(i)->IsAlive() ) {
			CRTSPointOrder *pTarget = (CRTSPointOrder *)CreateEntityByName( "rts_point_order" );

			// do we have and pass the filter?
			passesFilter = !pFilter ? true : pFilter->PassesFilter( this, pPlayer->GetUnit(i) );

			// do we got an available cover position?
			if( pPos && !( UTIL_CheckForOrderInSphere( pPos->GetAbsOrigin(), 4.0f ) ) &&
					passesFilter) {		
				pTarget->SetAbsOrigin( pPos->GetAbsOrigin() );  
				pTarget->SetAbsAngles( pPos->GetAbsAngles() );
				pTarget->SetNPC( pPlayer->GetUnit(i) );
				pTarget->SetOrderType( m_iOrderType, bRun );
				pTarget->Spawn(); 	
				pTarget->Start();
				pPlayer->GetUnit(i)->ClearAllOrders();
				pPlayer->GetUnit(i)->QueueNewOrder(pTarget);
			}
			// default to default position
			else if( pDefaultPos ) {
				pTarget->SetAbsOrigin( pDefaultPos->GetAbsOrigin() );  
				pTarget->SetNPC( pPlayer->GetUnit(i) );
				pTarget->SetOrderType( ORDER_MOVE, bRun );
				pTarget->Spawn(); 	
				pTarget->Start();
				pPlayer->GetUnit(i)->ClearAllOrders();
				pPlayer->GetUnit(i)->QueueNewOrder(pTarget);
					
			}
			// error
			else {
				DevMsg("No order spots and no default spot available! \n");
				break;
			}
		}

		// get the next pos
		pPos = gEntList.FindEntityByNameWithin( pPos, STRING( m_pOrderPositions ), GetAbsOrigin(), 1024.0f );
	}
}

//-----------------------------------------------------------------------------
// Purpose: Left click
//-----------------------------------------------------------------------------
void COrderRTSTrigger::OnClickLeft( CBasePlayer *pActivator ) 
{
	BaseClass::OnClickLeft( pActivator );

	GoToDefault( true );
}

//-----------------------------------------------------------------------------
// Purpose: Left click double
//-----------------------------------------------------------------------------
void COrderRTSTrigger::OnClickLeftDouble( CBasePlayer *pActivator ) 
{
	BaseClass::OnClickLeftDouble( pActivator );

	GoToDefault( true );
}

//-----------------------------------------------------------------------------
// Purpose: Go to default position
//-----------------------------------------------------------------------------
void COrderRTSTrigger::GoToDefault( bool bRun ) 
{
	CHL2Wars_Player *pPlayer = NULL;
	if ( m_hActivator && m_hActivator->IsPlayer() )
	{
		pPlayer = (CHL2Wars_Player *)m_hActivator.Get();
	}

	if( !pPlayer )
		return;

	// get the default pos
	CBaseEntity *pDefaultPos = NULL;
	pDefaultPos = gEntList.FindEntityByNameWithin( NULL, STRING( m_pDefaultPosition ), GetAbsOrigin(), 1024.0f );

	// loop through all selected npc's
	for( int i = 0; i < pPlayer->CountUnits(); i++ ) {
		if( pPlayer->GetUnit(i) && pPlayer->GetUnit(i)->IsAlive() ) {
			CRTSPointOrder *pTarget = (CRTSPointOrder *)CreateEntityByName( "rts_point_order" );
			if( pDefaultPos ) {
				pTarget->SetAbsOrigin( pDefaultPos->GetAbsOrigin() );  
				pTarget->SetNPC( pPlayer->GetUnit(i) );
				pTarget->SetOrderType( ORDER_MOVE, bRun );
				pTarget->Spawn(); 	
				pTarget->Start();
				pPlayer->GetUnit(i)->ClearAllOrders();
				pPlayer->GetUnit(i)->QueueNewOrder(pTarget);
					
			}
			else {
				DevMsg("No order spots and no default spot available! \n");
				break;
			}
		}
	}
}