// Core
#include "Core/Asura.h"

#ifdef AVP_USE_INPUT_SIMULATOR

// File's header
#include "InputSimulator/Behaviours/AVP_InputSimulator_Behaviour_Alien_Hunt.h"

// Asura
#include "Core/Asura_UserInput.h"

// AVP
#include "Core/AVP_Game_Core.h"
#include "Entity/PhysicalObject/Actor/AVP_ClientEntity_Actor.h"
#include "Entity/PhysicalObject/Actor/AVP_ServerEntity_Actor.h"
#include "Entity/PlayerInfo/AVP_ClientEntity_PlayerInfo.h"
#include "Entity/PlayerInfo/AVP_ServerEntity_PlayerInfo.h"
#include "InputSimulator/AVP_InputSimulator_System.h"
#include "Network/AVP_Player.h"

AVP_InputSimulator_Behaviour_Alien_Hunt::AVP_InputSimulator_Behaviour_Alien_Hunt()
: m_eUpdateState( SPOT_AND_ATTACK_TARGET )
, m_uTargetGuid( ASURA_GUID_UNREGISTERED )
{
}

DEBUGVAR float dbg_fMeleeRange				= 20.0f;
	
// Gets the local player puppet. Returns NULL if no player is found.
AVP_ClientEntity_Actor* AVP_InputSimulator_Behaviour_Alien_Hunt::GetPlayer()
{
	if( !AVP_Game_Core::GetPlayer() )
	{
		return NULL;
	}

	// We have a player.
	Asura_Guid uLocalPlayerGuid = AVP_Game_Core::GetPlayerGuid();
	// Try to get player information. 
	AVP_ClientEntity_PlayerInfo* pxLocalPlayerInfo = AVP_ClientEntity_PlayerInfo::FindEntity( uLocalPlayerGuid );
	if( pxLocalPlayerInfo )
	{
		// Does our player have a puppet?
		Asura_Guid uCurrentPlayerPuppetGuid = pxLocalPlayerInfo->GetPuppetGuid();
		AVP_ClientEntity_Actor* pxCurrentPlayerPuppet = AVP_ClientEntity_Actor::FindEntity( uCurrentPlayerPuppetGuid ); 
		if( pxCurrentPlayerPuppet )
		{
			// Found a puppet, from this puppet we can retrieve position information, orientation etc.
			return pxCurrentPlayerPuppet;
		}
	}
	return NULL;
}

void AVP_InputSimulator_Behaviour_Alien_Hunt::Update( u_char* ucCurrentInput, float* pfAxisValue ) 
{
	switch( m_eUpdateState )
	{
		case SPOT_AND_ATTACK_TARGET:
		{
			// If we cant spot a target, we are done here.
			if( !SpotAndAttackTarget( ucCurrentInput, pfAxisValue ) )
			{
				SetFinished();
			}
			break;
		}

		default:
		{
			SetFinished();
			break; 
		}
	}
}

// Search for a hostile target. If we find a target, attack it.
bool AVP_InputSimulator_Behaviour_Alien_Hunt::SpotAndAttackTarget( u_char* ucCurrentInput, float* pfAxisValue )
{
	for( Asura_Hashed_List_ConstIt<AVP_ClientEntity_Actor> xIt( AVP_ClientEntity_Actor::GetList() ); !xIt.Done(); xIt.Next() )
	{
		const AVP_ClientEntity_Actor* pxActor = xIt.GetCurrent();
		// Are we dead or we found ourself, continue.
		if( !pxActor->IsDead() && AVP_Game_Core::GetPlayer()->GetGuid() != pxActor->GetPlayerInfoGuid() ) 
		{	
			Asura_Vector_3	xCenter( 0.0f, 0.0f, 0.0f );
			float			fRadius = 0.0f;

			pxActor->GetBoundingSphere( xCenter, fRadius );
			// Is the target inside our frustum we have a target.
			if( Asura_Camera::IsSphereInFrustum( xCenter, fRadius ) )
			{
				AVP_ClientEntity_Actor* pxPlayer		= GetPlayer();
				if( pxPlayer )
				{
					// Are we close enough to hit the target?
					if( (pxActor->GetCurrentPosition() - pxPlayer->GetCurrentPosition()).Magnitude() < dbg_fMeleeRange )
					{
						m_uTargetGuid = pxActor->GetGuid();
						bool bShouldAttack = Asura_Random::GetInt(0, 1) ? true : false;
						AVP_InputSimulator_System::Platform_SetFireButton( bShouldAttack, ucCurrentInput );
					}
				}
			}
		}
	}

	return true;
}

#endif // AVP_USE_INPUT_SIMULATOR
