//////////////////////////////////////////////////////////////////////////////
//
// AVP_ClientEntity_InteractPredator_Lock.h
//
// Created by AJK 22/10/2008
//
// Copyright (c) 2008 Rebellion. All rights reserved.
//
//////////////////////////////////////////////////////////////////////////////

#include "Core/Asura.h"

#include "Entity/PhysicalObject/Interact/PredatorLock/AVP_ClientEntity_InteractPredatorLock.h"

#include "Animation/Asura_AnimationController_Animation.h"
#include "Blueprint/Asura_Blueprint_System.h"
#include "Network/Asura_Message.h"

#include "Entity/AVP_Entity_Classification.h"
#include "Entity/PhysicalObject/Actor/AVP_Actor_Messages.h"
#include "Entity/PhysicalObject/Actor/AVP_ClientEntity_Actor.h"
#include "Entity/PhysicalObject/Interact/PredatorLock/AVP_Messages_InteractPredatorLock.h"
#include "Entity/AVP_Messages.h"
#include "Moves/AVP_Move_Interaction.h"

Asura_Hashed_List<AVP_ClientEntity_InteractPredator_Lock> AVP_ClientEntity_InteractPredator_Lock::s_xList;

AVP_ClientEntity_InteractPredator_Lock::AVP_ClientEntity_InteractPredator_Lock()
: m_uReachPosition1AnimID( ASURA_HASH_ID_UNSET )
, m_uReachPosition2AnimID( ASURA_HASH_ID_UNSET )
, m_uReachPosition3AnimID( ASURA_HASH_ID_UNSET )
, m_uReachPosition4AnimID( ASURA_HASH_ID_UNSET )
, m_uLeavePosition1AnimID( ASURA_HASH_ID_UNSET )
, m_uLeavePosition2AnimID( ASURA_HASH_ID_UNSET )
, m_uLeavePosition3AnimID( ASURA_HASH_ID_UNSET )
, m_uLeavePosition4AnimID( ASURA_HASH_ID_UNSET )
, m_uPlugKeyHUD( ASURA_HASH_ID_UNSET )
, m_uPlugKeyTP( ASURA_HASH_ID_UNSET )
, m_uStandStillHUD( ASURA_HASH_ID_UNSET )
, m_uStandStillTP( ASURA_HASH_ID_UNSET )
, m_uTurnLeftHUD( ASURA_HASH_ID_UNSET )
, m_uTurnLeftTP( ASURA_HASH_ID_UNSET )
, m_uTurnRightHUD( ASURA_HASH_ID_UNSET )
, m_uTurnRightTP( ASURA_HASH_ID_UNSET )
, m_uUnPlugKeyHUD( ASURA_HASH_ID_UNSET )
, m_uUnPlugKeyTP( ASURA_HASH_ID_UNSET ) 
, m_cLockCurrentPosition(1)
{
	Classification = AVP_ENTITYCLASS_INTERACT_PREDATOR_LOCK;

	s_xList.AddToList( this );
}

AVP_ClientEntity_InteractPredator_Lock::~AVP_ClientEntity_InteractPredator_Lock() 
{
	s_xList.RemoveFromList( this );
}

void AVP_ClientEntity_InteractPredator_Lock::Create( const Asura_Message* pxMsg )
{
	Asura_Assert( pxMsg->GetMsgID() == ASURA_MSG_CLIENTCREATE, "" );
	Asura_Assert( pxMsg->GetEntityClassification() == AVP_ENTITYCLASS_INTERACT_PREDATOR_LOCK, "" );

	const AVP_Message_InteractPredatorLock_ClientCreate* pxData = static_cast< const AVP_Message_InteractPredatorLock_ClientCreate* >( pxMsg->GetData() );

	AVP_ClientEntity_InteractPredator_Lock* pxNew = new AVP_ClientEntity_InteractPredator_Lock();
	pxNew->ProcessClientCreate(  pxData, pxMsg->GetSentTime(), true );
}

void AVP_ClientEntity_InteractPredator_Lock::ProcessClientCreate( const AVP_Message_InteractPredatorLock_ClientCreate* pxData, float fServerTime, bool bProcessPosAndOri )
{
	PARENT::ProcessClientCreate(pxData, fServerTime, bProcessPosAndOri);
	m_cLockCurrentPosition = pxData->GetCurrentPosition();
	OnInteraction(true);
}

bool AVP_ClientEntity_InteractPredator_Lock::HandleMessage( const Asura_Message* pxMsg )
{
	switch ( pxMsg->GetMsgID() )
	{
		case AVP_MSGID_REQUEST_INTERACTION:
		{
			// requesting interaction, do it
			const AVP_Message_Actor_RequestInteraction*	pxData = static_cast< const AVP_Message_Actor_RequestInteraction* >( pxMsg->GetData() );
			Asura_Assert( pxData, "No data" );
			if ( pxData )
			{
				if( pxData->GetInteractionMoveType() ==  AVP_Message_Actor_RequestInteraction::INTERACTION_RIGHT)
				{
				   ( m_cLockCurrentPosition < 4 ) ? ++m_cLockCurrentPosition : m_cLockCurrentPosition = 1;
					m_bOn = true;
					OnInteraction(m_bOn);
				}
				else if (pxData->GetInteractionMoveType() ==  AVP_Message_Actor_RequestInteraction::INTERACTION_LEFT)
				{
				   ( m_cLockCurrentPosition > 1 ) ? --m_cLockCurrentPosition : m_cLockCurrentPosition = 4;
					m_bOn = false;
					OnInteraction(m_bOn);
				}

				Asura_Assert( (m_cLockCurrentPosition >= 1 && m_cLockCurrentPosition <= 4), "No data" );

				if ( pxData->GetActorGuid() != ASURA_GUID_UNREGISTERED )
				{
					// start the move on our actor entity ( the move will already be in progress on the initiating client machine so we will ignore the request )
					AVP_ClientEntity_Actor* pxActor = AVP_ClientEntity_Actor::FindEntity( pxData->GetActorGuid() );
					Asura_Assert( pxActor, "No actor" );
					if ( pxActor != NULL )
					{
						Asura_Message* pxMoveMessage = Asura_Network::CreateMessage( ASURA_MSG_MOVE_START, sizeof( AVP_Message_InteractionMoveStart ) );
						Asura_Assert( pxMoveMessage , "unable to create message" );
						if ( pxMoveMessage  != NULL )
						{
							AVP_Message_InteractionMoveStart* pxMoveData = static_cast< AVP_Message_InteractionMoveStart* >( pxMoveMessage->GetData() );

							// Fill-in the message-body...
							pxMoveMessage->SetFromGuid( GetGuid() );
							pxMoveMessage->SetToGuid(  pxData->GetActorGuid() );

							pxMoveData->ClearFlags();
							pxMoveData->SetMoveID( pxData->GetMoveHash() );
							pxMoveData->SetIgnoredByOwner( false );
							pxMoveData->SetInteractionObject( GetGuid() );
							pxMoveData->SetOn( m_bOn );
							// Forward the message directly to the client... we will do this on each client on reciept of the interact message
							bool bOK = pxActor->HandleMessage( pxMoveMessage );
							Asura_Network::DestroyMessage( pxMoveMessage );
							return bOK;
						}
					}
					// no move message or no actor
					return false;
				}
				// We're probably on the initiating client so we don't want to start the interaction again. or there's no actor guid
				return true;
			}
			// no data
			return false;
		}
		case AVP_MSGID_PREDATOR_LOCK_POSITION_F:
		{
			m_cLockCurrentPosition = 1;
			OnInteraction(true);
			return true; 
		}
		case AVP_MSGID_PREDATOR_LOCK_POSITION_X:
		{
			m_cLockCurrentPosition = 4;
			OnInteraction(true);
			return true; 
		}
		case AVP_MSGID_PREDATOR_LOCK_POSITION_T:
		{
			m_cLockCurrentPosition = 3;
			OnInteraction(true);
			return true; 
		}
		case AVP_MSGID_PREDATOR_LOCK_POSITION_O:
		{
			m_cLockCurrentPosition = 2;
			OnInteraction(true);
			return true; 
		}

	default:
		return PARENT::HandleMessage(pxMsg);
	}
}

void AVP_ClientEntity_InteractPredator_Lock::OnInteraction( const bool bOn )
{
	Asura_Hash_ID uAnim = GetLockAnimHash();
	if ( uAnim != ASURA_HASH_ID_UNSET )
	{
		// Play animation
		Asura_Animation* pxAnimation = GetShapeInstance().GetAnimation();
		if ( pxAnimation )
		{
			Asura_AnimationBlend* pxBlend = new Asura_AnimationBlend_AnimatedTween( 0.0f, false );
			Asura_AnimationController_Animation* pxAACA = pxAnimation->CreateControllerAnimation( AAC_FLAG_ACTIVE | AAC_FLAG_ALLOW_DESTROY_FROM_MESSAGE, 0, uAnim, pxBlend );
			if ( pxAACA )
			{
				pxAACA->Play();
			}
			else
			{
				delete pxBlend;
			}
		}
	}
}

void AVP_ClientEntity_InteractPredator_Lock::GetPlugKeyAnimHashes( u_int uClassification, Asura_Hash_ID& uHUDAnimHash, Asura_Hash_ID& uTPAnimHash ) const
{
	Asura_Assert(uClassification == AVP_ENTITYCLASS_PREDATOR, "This lock is used by the predator only!");

	uHUDAnimHash = m_uPlugKeyHUD;
	uTPAnimHash  = m_uPlugKeyTP;

}

void AVP_ClientEntity_InteractPredator_Lock::GetUnPlugKeyAnimHashes( u_int uClassification, Asura_Hash_ID& uHUDAnimHash, Asura_Hash_ID& uTPAnimHash ) const
{
	Asura_Assert(uClassification == AVP_ENTITYCLASS_PREDATOR, "This lock is used by the predator only!");

	uHUDAnimHash = m_uUnPlugKeyHUD;
	uTPAnimHash  = m_uUnPlugKeyTP;
}

void AVP_ClientEntity_InteractPredator_Lock::GetTurnRightAnimHashes( u_int uClassification, Asura_Hash_ID& uHUDAnimHash, Asura_Hash_ID& uTPAnimHash ) const
{
	Asura_Assert(uClassification == AVP_ENTITYCLASS_PREDATOR, "This lock is used by the predator only!");

	uHUDAnimHash = m_uTurnRightHUD;
	uTPAnimHash  = m_uTurnRightTP;
}

void AVP_ClientEntity_InteractPredator_Lock::GetTurnLeftAnimHashes( u_int uClassification, Asura_Hash_ID& uHUDAnimHash, Asura_Hash_ID& uTPAnimHash ) const
{
	Asura_Assert(uClassification == AVP_ENTITYCLASS_PREDATOR, "This lock is used by the predator only!");

	uHUDAnimHash = m_uTurnLeftHUD;
	uTPAnimHash  = m_uTurnLeftTP;
}

void AVP_ClientEntity_InteractPredator_Lock::GetStandStillAnimHashes( u_int uClassification, Asura_Hash_ID& uHUDAnimHash, Asura_Hash_ID& uTPAnimHash ) const
{
	Asura_Assert(uClassification == AVP_ENTITYCLASS_PREDATOR, "This lock is used by the predator only!");

	uHUDAnimHash = m_uStandStillHUD;
	uTPAnimHash  = m_uStandStillTP;
}

Asura_Hash_ID AVP_ClientEntity_InteractPredator_Lock::GetLockAnimHash() const
{
	if(m_bOn)
	{
		switch(m_cLockCurrentPosition)
		{
			case 1:
			{
				return m_uReachPosition1AnimID;
			}
			case 2:
			{
				return m_uReachPosition2AnimID;
			}
			case 3:
			{
				return m_uReachPosition3AnimID;
			}
			case 4:
			{
				return m_uReachPosition4AnimID;
			}
			default:
			{
				Asura_Assert( false , "Invalid lock position!" );
				return ASURA_HASH_ID_UNSET;
			}
		}
	}
	else
	{
		switch(m_cLockCurrentPosition)
		{
			case 1:
			{
				return m_uLeavePosition1AnimID;
			}
			case 2:
			{
				return m_uLeavePosition2AnimID;
			}
			case 3:
			{
				return m_uLeavePosition3AnimID;
			}
			case 4:
			{
				return m_uLeavePosition4AnimID;
			}
			default:
			{
					Asura_Assert( false , "Invalid lock position!" );
					return ASURA_HASH_ID_UNSET;
			}
		}
	}
}

void AVP_ClientEntity_InteractPredator_Lock::InitialiseFromBlueprint( const Asura_Blueprint& xBlueprint )
{
	PARENT::InitialiseFromBlueprint( xBlueprint );

	Asura_Value xValue;
	// Puzzle Reach position
	if ( xBlueprint.GetParameterValueByHashID( 0xF196456E, xValue ) )	//Asura_GetHashID( "Anim.Interaction.ReachPosition1"); 
	{
		m_uReachPosition1AnimID = xValue.GetHashIDValue();
	}
	if ( xBlueprint.GetParameterValueByHashID( 0xF196456F, xValue ) )	//Asura_GetHashID( "Anim.Interaction.ReachPosition2"); 
	{
		m_uReachPosition2AnimID = xValue.GetHashIDValue();
	}
	if ( xBlueprint.GetParameterValueByHashID( 0xF1964570, xValue ) )	//Asura_GetHashID( "Anim.Interaction.ReachPosition3"); 
	{
		m_uReachPosition3AnimID = xValue.GetHashIDValue();
	}
	if ( xBlueprint.GetParameterValueByHashID( 0xF1964571, xValue ) )	//Asura_GetHashID( "Anim.Interaction.ReachPosition4"); 
	{
		m_uReachPosition4AnimID = xValue.GetHashIDValue();
	}

	// Puzzle Leave Position
	if ( xBlueprint.GetParameterValueByHashID( 0xD6807CAA, xValue ) )	//Asura_GetHashID( "Anim.Interaction.LeavePosition1"); 
	{
		m_uLeavePosition1AnimID = xValue.GetHashIDValue();
	}
	if ( xBlueprint.GetParameterValueByHashID( 0xD6807CAB, xValue ) )	//Asura_GetHashID( "Anim.Interaction.LeavePosition2"); 
	{
		m_uLeavePosition2AnimID = xValue.GetHashIDValue();
	}
	if ( xBlueprint.GetParameterValueByHashID( 0xD6807CAC, xValue ) )	//Asura_GetHashID( "Anim.Interaction.LeavePosition3"); 
	{
		m_uLeavePosition3AnimID = xValue.GetHashIDValue();
	}
	if ( xBlueprint.GetParameterValueByHashID( 0xD6807CAD, xValue ) )	//Asura_GetHashID( "Anim.Interaction.LeavePosition4"); 
	{
		m_uLeavePosition4AnimID = xValue.GetHashIDValue();
	}

	// Predator
	if ( xBlueprint.GetParameterValueByHashID( 0xA3A3F8D6, xValue ) )	//Asura_GetHashID( "Anim.Interaction.PlugKey.Predator.HUD"); 
	{
		m_uPlugKeyHUD = xValue.GetHashIDValue();
	}
	if ( xBlueprint.GetParameterValueByHashID( 0x70A232BD, xValue ) )	//Asura_GetHashID( "Anim.Interaction.PlugKey.Predator.TP"); 
	{
		m_uPlugKeyTP = xValue.GetHashIDValue();
	}
	if ( xBlueprint.GetParameterValueByHashID( 0x38A47523, xValue ) )	//Asura_GetHashID( "Anim.Interaction.StandStill.Predator.HUD"); 
	{
		m_uStandStillHUD = xValue.GetHashIDValue();
	}
	if ( xBlueprint.GetParameterValueByHashID( 0x5CAA78D0, xValue ) )	//Asura_GetHashID( "Anim.Interaction.StandStill.Predator.TP"); 
	{
		m_uStandStillTP = xValue.GetHashIDValue();
	}
	if ( xBlueprint.GetParameterValueByHashID( 0x8BCA7DB1, xValue ) )	//Asura_GetHashID( "Anim.Interaction.TurnLeft.Predator.HUD"); 
	{
		m_uTurnLeftHUD = xValue.GetHashIDValue();
	}
	if ( xBlueprint.GetParameterValueByHashID( 0xE37A2682, xValue ) )	//Asura_GetHashID( "Anim.Interaction.TurnLeft.Predator.TP"); 
	{
		m_uTurnLeftTP = xValue.GetHashIDValue();
	}
	if ( xBlueprint.GetParameterValueByHashID( 0x3E5CD7A8, xValue ) )	//Asura_GetHashID( "Anim.Interaction.TurnRight.Predator.HUD"); 
	{
		m_uTurnRightHUD = xValue.GetHashIDValue();
	}
	if ( xBlueprint.GetParameterValueByHashID( 0x1AC931AB, xValue ) )	//Asura_GetHashID( "Anim.Interaction.TurnRight.Predator.TP"); 
	{
		m_uTurnRightTP = xValue.GetHashIDValue();
	}
	if ( xBlueprint.GetParameterValueByHashID( 0x90877EAF, xValue ) )	//Asura_GetHashID( "Anim.Interaction.UnPlugKey.Predator.HUD"); 
	{
		m_uUnPlugKeyHUD = xValue.GetHashIDValue();
	}
	if ( xBlueprint.GetParameterValueByHashID( 0x46BA0DC4, xValue ) )	//Asura_GetHashID( "Anim.Interaction.UnPlugKey.Predator.TP"); 
	{
		m_uUnPlugKeyTP = xValue.GetHashIDValue();
	}
}

bool AVP_ClientEntity_InteractPredator_Lock::IsActorUsingRightInteractionItem(const AVP_ClientEntity_Actor& xActor) const
{
	return true;
}
