//////////////////////////////////////////////////////////////////////////////
//
// AVP_Brain_Squad_Marine.cpp
//
// Copyright (C) 2007 Rebellion. All Rights Reserved.
//
//////////////////////////////////////////////////////////////////////////////

// I N C L U D E S ///////////////////////////////////////////////////////////

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

// header
#include "Core/BrainTypes/AVP_Brain_Squad_Marine.h"

// asura
#include "ChunkSystem/Asura_Chunk_Stream.h"

// avp
#include "Entity/Controller/AVP_ServerEntity_Squad_Marine.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/Human/AVP_ServerActor_Human.h"

// axon
#include "Behaviour/BehaviourTypes/AVP_Behaviour_Types.h"
#include "Core/BrainTypes/AVP_Brain_Actor_Marine.h"
#include "Knowledge/AVP_Knowledge_System_Actor.h"


//////////////////////////////////////////////////////////////////////////////
//
// AVP_Brain_Squad_Marine
//
//////////////////////////////////////////////////////////////////////////////

//---------------------------------------------------------------------------
// AVP_Brain_Squad_Marine :: ReadFromChunkStream
//---------------------------------------------------------------------------
AVP_Brain_Squad_Marine::AVP_Brain_Squad_Marine( AVP_ServerEntity_Squad_Marine* pxMarineSquad )
: PARENT( pxMarineSquad->GetGuid() )
, m_uNumThreats( 0 )
, m_uNumAssaultWeapons( 0 )
, m_uNumSupportWeapons( 0 )
, m_uManuallyAssignedAssaulters( 0 )
{
	m_pxMarineSquad = pxMarineSquad;
}

//---------------------------------------------------------------------------
// AVP_Brain_Squad_Marine :: ReadFromChunkStream
//---------------------------------------------------------------------------
void AVP_Brain_Squad_Marine::ReadFromChunkStream( Asura_Chunk_Stream& xStream )
{
	int iVersion;
	xStream >> iVersion;

	PARENT::ReadFromChunkStream( xStream );

	if ( iVersion == CURRENT_CHUNK_VERSION )
	{

	}
	else
	{
		Asura_Assertf( false, ( "AVP_Brain_Squad_Marine::ReadFromChunkStream - unhandled version (%d)", iVersion ) );
	}
}

//---------------------------------------------------------------------------
// AVP_Brain_Squad_Marine :: WriteToChunkStream
//---------------------------------------------------------------------------
void AVP_Brain_Squad_Marine::WriteToChunkStream( Asura_Chunk_Stream& xStream ) const
{
	xStream << CURRENT_CHUNK_VERSION;

	PARENT::WriteToChunkStream( xStream );
}

//---------------------------------------------------------------------------
// AVP_Brain_Squad_Marine :: DoPerFrameUpdate
//---------------------------------------------------------------------------
void AVP_Brain_Squad_Marine::DoPerFrameUpdate( const float fTimeslice )
{
	PARENT::DoPerFrameUpdate( fTimeslice );

	// I want to update how many threats we have!
	UpdateNumSquadThreats();

	UpdateOurFormation();
}

//---------------------------------------------------------------------------
// AVP_Brain_Squad_Marine :: UpdateNumSquadThreats
//---------------------------------------------------------------------------
void AVP_Brain_Squad_Marine::UpdateNumSquadThreats( void )
{
	AVP_ServerEntity_Squad_Marine*	pxSquad			= GetMarineSquad(); // verified every frame
	u_int							uNumMembers		= pxSquad->GetNumSquadMembers();
	AVP_ServerActor_Human**			pxSquadMembers	= new AVP_ServerActor_Human*[ uNumMembers ];
	u_int							uNumProcessed	= 0;

	for ( u_int u = 0; u < uNumMembers; ++u )
	{
		AVP_ServerActor_Human* pxHuman = AVP_ServerActor_Human::FindEntity( pxSquad->GetMemberGuid( u ) );

		if ( pxHuman )
		{
			pxSquadMembers[ uNumProcessed ] = pxHuman;
			++uNumProcessed;
		}
	}

	m_uNumThreats = 0;

	for ( u_int u = 0; u < uNumProcessed; ++u )
	{
		AVP_Brain_Actor_Marine* pxMarineBrain = ( AVP_Brain_Actor_Marine* )pxSquadMembers[u]->GetActorBrain();
		
		if ( pxMarineBrain )
		{
			m_uNumThreats += pxMarineBrain->GetKnowledgeSystem()->GetNumSecondaryThreats();

			if ( pxMarineBrain->GetKnowledgeSystem()->GetBestThreatKnowledge().GetGuid() != ASURA_GUID_UNREGISTERED )
			{
				++m_uNumThreats;
			}
		}
	}

	if (m_uNumThreats > 0)
	{
		m_uNumThreats /= pxSquad->GetNumSquadMembers();
	}

	delete [] pxSquadMembers;
}

//---------------------------------------------------------------------------
// AVP_Brain_Squad_Marine :: UpdateOurFormation
//---------------------------------------------------------------------------
void AVP_Brain_Squad_Marine::UpdateOurFormation()
{
	AVP_ServerEntity_Squad_Marine*	pxSquad			= GetMarineSquad(); // verified every frame
	u_int							uNumMembers		= pxSquad->GetNumSquadMembers();
	AVP_ServerActor_Human**			pxSquadMembers	= new AVP_ServerActor_Human*[ uNumMembers ];
	u_int							uNumProcessed	= 0;

	for ( u_int u = 0; u < uNumMembers; ++u )
	{
		AVP_ServerActor_Human* pxHuman = AVP_ServerActor_Human::FindEntity( pxSquad->GetMemberGuid( u ) );

		if ( pxHuman )
		{
			pxSquadMembers[ uNumProcessed ] = pxHuman;
			++uNumProcessed;
		}
	}

	m_uNumAssaultWeapons = 0;
	m_uNumSupportWeapons = 0;

	for ( u_int u = 0; u < uNumProcessed; ++u )
	{
		AVP_Brain_Actor_Marine* pxMarineBrain = ( AVP_Brain_Actor_Marine* )pxSquadMembers[ u ]->GetActorBrain();
		
		if ( pxMarineBrain )
		{
			if ( pxMarineBrain->GetCurrentWeaponType() == AVP_WEAPON_BEHAVIOUR_TYPE_FLAMETHROWER || pxMarineBrain->GetCurrentWeaponType() == AVP_WEAPON_BEHAVIOUR_TYPE_SHOTGUN )
			{
				++m_uNumAssaultWeapons;
			}
			else
			{
				++m_uNumSupportWeapons;
			}
		}
	}

	m_uNumAssaultWeapons += m_uManuallyAssignedAssaulters;
	m_uNumSupportWeapons -= m_uManuallyAssignedAssaulters;



	delete [] pxSquadMembers;
}

//---------------------------------------------------------------------------
// AVP_Brain_Squad_Marine :: AssignAssaulter
//---------------------------------------------------------------------------
void AVP_Brain_Squad_Marine::AssignAssaulter( void )
{
	++m_uManuallyAssignedAssaulters;

	++m_uNumAssaultWeapons;

	if ( m_uNumSupportWeapons > 0)
	{
		--m_uNumSupportWeapons;
	}
}

//---------------------------------------------------------------------------
// AVP_Brain_Squad_Marine :: DealocateAssaulter
//---------------------------------------------------------------------------
void AVP_Brain_Squad_Marine::DealocateAssaulter( void )
{
	if ( m_uManuallyAssignedAssaulters > 0)
	{
		--m_uManuallyAssignedAssaulters;
	}
	
	if ( m_uNumAssaultWeapons > 0 )
	{
		--m_uNumAssaultWeapons;
	}

	++m_uNumSupportWeapons;
}

//---------------------------------------------------------------------------
// AVP_Brain_Squad_Marine :: GetMarineSquad
//---------------------------------------------------------------------------
AVP_ServerEntity_Squad_Marine* AVP_Brain_Squad_Marine::GetMarineSquad( void ) const
{
	return m_pxMarineSquad;
}

//---------------------------------------------------------------------------
// AVP_Brain_Squad_Marine :: GetLargestBehaviourSize
//---------------------------------------------------------------------------
u_int AVP_Brain_Squad_Marine::GetLargestBehaviourSize( void )
{
    return 0;
}

//------------------------------------------------------------------------
// AVP_Brain_Squad_Marine :: Verify
//------------------------------------------------------------------------
#ifndef ASURA_NO_DEBUG_OUTPUT
bool AVP_Brain_Squad_Marine::Verify()
{
	Asura_Assert( GetMarineSquad(), "AVP_Brain_Actor_Squad_Marine::Verify - No Squad Entity" );
	return ( PARENT::Verify() && GetMarineSquad() );
}
#endif

//////////////////////////////////////////////////////////////////////////////
//
// 
//
//////////////////////////////////////////////////////////////////////////////
