//---------------------------------------------------------------------------
// File			: AVP_Behaviour_Civilian.cpp
// Created		: 
// Created By	: Gareth Thomas
// Copyright (C) 2007 Rebellion. All Rights Reserved.
//---------------------------------------------------------------------------

// INCLUDES ///////////////////////////////////////////////////////////

// core
#include "Core/Asura.h"
// header
#include "Behaviour/BehaviourTypes/Human/Civilian/AVP_Behaviour_Civilian.h"
// asura
#ifndef ASURA_NO_DEBUG_OUTPUT
#include "Rendering/Asura_Font_System.h"
#endif
// axon
// AVP
#include "Actor/Vertebrates/Human/AVP_Human_AIAnimStateMachine.h"
#include "Entity/AVP_Messages.h"
#include "Entity/GamePlayVolume/AVP_ServerEntity_GamePlayVolume.h"
#include "Entity/Locations/GuardZone/AVP_ServerNode_GuardZone.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/Human/Civilian/AVP_ServerActor_Civilian.h"
#include "Moves/AVP_Movement_System.h"
#include "Moves/AVP_Moves.h"
// AVP axon
#include "Behaviour/BehaviourTypes/AVP_Behaviour_Types.h"
#include "Behaviour/BehaviourTypes/Human/AVP_Behaviour_Human_Movement.h"
#include "Behaviour/BehaviourTypes/Human/AVP_Behaviour_Human_Movement.h"
#include "Behaviour/BehaviourTypes/Human/Civilian/AVP_Behaviour_Civilian_Alert.h"
#include "Core/BrainTypes/AVP_Brain_Actor_Civilian.h"
#include "Knowledge/AVP_Knowledge_System_Actor.h"

//---------------------------------------------------------------------------------
//*********************************************************************************
//---------------------------------------------------------------------------------
// Class		: AVP_Behaviour_Civilian
// Description	: 
//---------------------------------------------------------------------------------
//*********************************************************************************
//---------------------------------------------------------------------------------

//---------------------------------------------------------------------------
// AVP_Behaviour_Civilian :: Constructor
//---------------------------------------------------------------------------
AVP_Behaviour_Civilian::AVP_Behaviour_Civilian(AVP_Brain_Actor_Civilian* pxBrain)
: PARENT(pxBrain, AVP_BEHAVIOUR_TYPE_CIVILIAN)
, m_eUpdateState(IDLE)
, m_pxCivilianBrain(pxBrain)
{

}

//---------------------------------------------------------------------------
// AVP_Behaviour_Civilian :: Activate
//---------------------------------------------------------------------------
bool AVP_Behaviour_Civilian::Activate()
{
	const bool bParentOk = PARENT::Activate();

	return bParentOk;
}

//---------------------------------------------------------------------------
// AVP_Behaviour_Civilian :: Deactivate
//---------------------------------------------------------------------------
void AVP_Behaviour_Civilian::Deactivate()
{
	DestroyAllChildren();

	PARENT::Deactivate();
}

//---------------------------------------------------------------------------
// AVP_Behaviour_Civilian :: UpdateAlert
//---------------------------------------------------------------------------
void AVP_Behaviour_Civilian::UpdateAlert( void )
{


}

//---------------------------------------------------------------------------
// AVP_Behaviour_Civilian :: HandleMessage
//---------------------------------------------------------------------------
bool AVP_Behaviour_Civilian::HandleMessage(const Asura_Message* pxMessage)
{
	switch (pxMessage->GetMsgID())
	{
		case AVP_MSGID_MOUNT_LIFT:
		{
			if ( GetChild() )
			{
				u_int uChildType = GetChild()->GetType();

				if ( uChildType != AVP_BEHAVIOUR_TYPE_HUMAN_LIFT )
				{
					DestroyAllChildren();

					CreateChildWithType( AVP_BEHAVIOUR_TYPE_HUMAN_LIFT );

					SetUpdateState( ON_LIFT );
				}
			}
			
			return true;
		}

		case ASURA_MSG_MOVE_START:
		case AVP_MSGID_MOVESTART_SERVER:
		{
			const AVP_Msg_Move*	pxData = static_cast<const AVP_Msg_Move*>(pxMessage->GetData());

			if ( pxData && pxData->GetMoveID() == AVP_Move_Puppet::GetStaticHash() )
			{
				if ( GetChild() )
				{
					u_int uChildType = GetChild()->GetType();

					if ( uChildType != AVP_BEHAVIOUR_TYPE_HUMAN_GRAPPLE )
					{
						DestroyAllChildren();

						CreateChildWithType( AVP_BEHAVIOUR_TYPE_HUMAN_GRAPPLE );

						SetUpdateState( GRAPPLE );
					}
				}
			}
			return true;
		}

		case ASURA_MSG_MOVECHAINCOMPLETE:
		{
			if ( GetChild() )
			{
				u_int uChildType = GetChild()->GetType();

				if (uChildType == AVP_BEHAVIOUR_TYPE_HUMAN_GRAPPLE)
				{
					DestroyChildWithType( AVP_BEHAVIOUR_TYPE_HUMAN_GRAPPLE );
					SetUpdateState( IDLE );
				}
			}
			else
			{
				if ( GetUpdateState() != IDLE )
				{
					SetUpdateState( IDLE );
				}
			}
			return true;
		}

		default:
		{
			return PARENT::HandleMessage( pxMessage );
		}
	}

}

//---------------------------------------------------------------------------
// AVP_Behaviour_Civilian :: Update
//---------------------------------------------------------------------------
void AVP_Behaviour_Civilian::Update(const float fTimeslice)
{
	bool bHaveThreat	= (GetCivilianBrain()->GetKnowledgeSystem()->GetBestThreatKnowledge().GetGuid() != ASURA_GUID_UNREGISTERED) ? true : false;
	bool bHaveAlert		= (GetCivilianBrain()->GetKnowledgeSystem()->GetBestAlertKnowledge().GetGuid() != ASURA_GUID_UNREGISTERED) ? true : false;

	UpdateAlert();

	switch (GetUpdateState())
	{
		//---------------------------------

		case ON_LIFT:
		{
			if ( IsChildBeahviourFinished() )
			{
				DestroyChildWithType( AVP_BEHAVIOUR_TYPE_HUMAN_LIFT );
				SetUpdateState( IDLE );
			}

		}break;

		//---------------------------------

		case IDLE:
		{
			// If we DON'T have threat knowledge and we DO have alert knowledge
			if ( (!bHaveThreat) && (bHaveAlert) && (GetCivilianBrain()->GetKnowledgeSystem()->GetBestAlertKnowledge().GetGuid() != GetCivilianBrain()->GetOwnerGuid()))
			{
				// Go To Alert
				CreateChildWithType(AVP_BEHAVIOUR_TYPE_CIVILIAN_ALERT);
				SetUpdateState(ALERT);
			}
			else if (bHaveThreat)
			{
				u_int uWeapon = GetCivilianBrain()->GetCurrentWeaponType();

				if ( uWeapon == AVP_WEAPON_BEHAVIOUR_TYPE_PISTOL || uWeapon == AVP_WEAPON_BEHAVIOUR_TYPE_TASER )
				{
					// Do Attacking
					CreateChildWithType(AVP_BEHAVIOUR_TYPE_CIVILIAN_ATTACK);
					SetUpdateState(ATTACK);
				}
				else
				{
					// Do Panicking
					CreateChildWithType(AVP_BEHAVIOUR_TYPE_CIVILIAN_PANIC);
					SetUpdateState(PANIC);
				}
			}
			else
			{
				CheckForIdleAction();
			}

			GetCivilianBrain()->GetCivilianActor()->SetAiming( false );
		}break;
		//---------------------------------
		case ALERT:
		case PANIC:
		case PATROL:
		case WANDER:
		case ATTACK:
		case GRAPPLE:
		{
			if (IsChildBeahviourFinished())
			{
				switch (GetUpdateState())
				{
					case ALERT:		
					{
						if ( GetCivilianBrain()->DoesHaveThreat() )
						{
							if ( GetChildWithType(this, AVP_BEHAVIOUR_TYPE_CIVILIAN_ALERT))
							{
								AVP_Behaviour_Civilian_Alert* pxAlertBehaviour = static_cast<AVP_Behaviour_Civilian_Alert*>( GetChildWithType(this, AVP_BEHAVIOUR_TYPE_CIVILIAN_ALERT) );

								if ( pxAlertBehaviour )
								{
									if ( pxAlertBehaviour->GetChildWithType( pxAlertBehaviour, AVP_BEHAVIOUR_TYPE_HUMAN_MOVEMENT) )
									{
										AVP_Behaviour_Human_Movement* pxMoveBehaviour = static_cast<AVP_Behaviour_Human_Movement*>( pxAlertBehaviour->GetChildWithType(pxAlertBehaviour, AVP_BEHAVIOUR_TYPE_HUMAN_MOVEMENT) );

										pxMoveBehaviour->SetStopAtEnd( false );
									}
								}
							}
						}

						DestroyChildWithType(AVP_BEHAVIOUR_TYPE_CIVILIAN_ALERT);
					}break;
					case PANIC:		DestroyChildWithType(AVP_BEHAVIOUR_TYPE_CIVILIAN_PANIC);	break;
					case PATROL:	DestroyChildWithType(AVP_BEHAVIOUR_TYPE_CIVILIAN_PATROL);	break;
					case WANDER:	DestroyChildWithType(AVP_BEHAVIOUR_TYPE_CIVILIAN_WANDER);	break;
					case ATTACK:	DestroyChildWithType(AVP_BEHAVIOUR_TYPE_CIVILIAN_ATTACK);	break;
					case GRAPPLE:	DestroyChildWithType(AVP_BEHAVIOUR_TYPE_HUMAN_GRAPPLE);	break;
					default:break;
				}

				SetUpdateState(IDLE);
			}

			if ( GetUpdateState() != ATTACK )
			{
				GetCivilianBrain()->GetCivilianActor()->SetAiming( false );
			}

		}break;
		//---------------------------------
		case UNSET:
		default:
		{

		}break;
	}
}

//---------------------------------------------------------------------------
// AVP_Behaviour_Civilian :: PerFrameUpdate
//---------------------------------------------------------------------------
bool AVP_Behaviour_Civilian::IsChildBeahviourFinished()
{
	u_int uChildType = 0xffffffff;

	switch (GetUpdateState())
	{
		case ALERT:		uChildType = AVP_BEHAVIOUR_TYPE_CIVILIAN_ALERT;		break;
		case PANIC:		uChildType = AVP_BEHAVIOUR_TYPE_CIVILIAN_PANIC;		break;
		case PATROL:	uChildType = AVP_BEHAVIOUR_TYPE_CIVILIAN_PATROL;	break;
		case WANDER:	uChildType = AVP_BEHAVIOUR_TYPE_CIVILIAN_WANDER;	break;
		case ATTACK:	uChildType = AVP_BEHAVIOUR_TYPE_CIVILIAN_ATTACK;	break;
		case GRAPPLE:	uChildType = AVP_BEHAVIOUR_TYPE_HUMAN_GRAPPLE;	break;
		case ON_LIFT:	uChildType = AVP_BEHAVIOUR_TYPE_HUMAN_LIFT; break;
		case IDLE:
		default:
		break;
	}

	if (uChildType != 0xffffffff)
	{
		Axon_Behaviour* pxChildBehaviour = GetChildWithType(this, uChildType);

		if (pxChildBehaviour)
		{
			if (pxChildBehaviour->IsFinished())
			{
				return true;
			}
		}
	}
	
	return false;
}

//---------------------------------------------------------------------------
// AVP_Behaviour_Civilian :: PerFrameUpdate
//---------------------------------------------------------------------------
void AVP_Behaviour_Civilian::CheckForIdleAction(void)
{
	CreateChildWithType(AVP_BEHAVIOUR_TYPE_CIVILIAN_WANDER);
	SetUpdateState(WANDER);
}

//---------------------------------------------------------------------------
// AVP_Behaviour_Civilian :: RenderDebugInfo
//---------------------------------------------------------------------------
#ifndef ASURA_NO_DEBUG_OUTPUT
static const char* s_aszStateStrings[AVP_Behaviour_Civilian::MAX_STATES] =
{
	"CIVILIAN - UNSET",
	"CIVILIAN - IDLE",
	"CIVILIAN - ALERT",
	"CIVILIAN - PANIC",
	"CIVILIAN - PATROL",
	"CIVILIAN - WANDER",
	"CIVILIAN - ATTACK",
	"CIVILIAN - GRAPPLE",
};

void AVP_Behaviour_Civilian::RenderDebugInfo()
{
	PARENT::RenderDebugInfo();

	Asura_Font_System::Print
	(
		GetProjectBrain()->GetDebugOutputPos().x,
		GetProjectBrain()->GetDebugOutputPos().y,
		0.5f, 
		0xffffffff,
		ASURA_TEXTFORMAT_CENTREJUSTIFIED, 
		s_aszStateStrings[GetUpdateState()]
	);

	// Offset the debug output position for other behaviours to render there own text
	GetProjectBrain()->GetDebugOutputPos().y += 10.0f;
}
#endif

/// End Of File 'AVP_behaviour_Civilian.cpp'
