class W3AnimationInteractionEntity extends CGameplayEntity
{
	editable var animationForAllInteractions 	: bool;							default animationForAllInteractions = true;
	editable var interactionName				: string;						default interactionName = "Examine";
	editable var holsterWeaponAtTheBeginning	: bool;							default holsterWeaponAtTheBeginning = true;
	editable var interactionAnim				: EPlayerExplorationAction;		default interactionAnim	= PEA_None;
	editable var slotAnimName 					: name;							default slotAnimName = '';
	editable var interactionAnimTime			: float;						default interactionAnimTime	= 4.0f;
	
	//private for now
	editable var desiredPlayerToEntityDistance	: float;						default desiredPlayerToEntityDistance = -1;
	editable var matchPlayerHeadingWithHeadingOfTheEntity	: bool;				default matchPlayerHeadingWithHeadingOfTheEntity = true;
	
	editable var attachThisObjectOnAnimEvent	: bool;							default attachThisObjectOnAnimEvent = false;
	editable var attachSlotName					: name; 						default attachSlotName = 'r_weapon';
	editable var attachAnimName 				: name; 						default attachAnimName = 'attach_item';
	editable var detachAnimName 				: name; 						default detachAnimName = 'detach_item';
	
	protected var isPlayingInteractionAnim : bool; default isPlayingInteractionAnim = false;
	
	//hints
	hint interactionAnim = "Name of the animation played on interaction.";
	hint interactionAnimTime = "Duration of the animation played on interaction.";
	hint animationForAllInteractions = "Should the animation be played only for interaction with Examine action assigned.";
	hint attachThisObjectOnAnimEvent = "";
	hint desiredPlayerToEntityDistance = "if set to < 0 palyer will stay in position where interaction was pressed";
	
	event OnDetaching()
	{
		if ( isPlayingInteractionAnim )
		{
			OnPlayerActionEnd();
		}		
	}	
	
	event OnInteraction( actionName : string, activator : CEntity  )
	{
		if ( activator == thePlayer && thePlayer.IsActionAllowed( EIAB_InteractionAction ) && thePlayer.CanPerformPlayerAction() )
		{
			if( animationForAllInteractions == true || actionName == interactionName )
			{
				PlayInteractionAnimation();
			}
		}
	}
	
	//this function should ba latent. In order to do it we need to create state in this class and call this function from entry function
	function PlayInteractionAnimation()
	{
		if ( interactionAnim == PEA_SlotAnimation && !IsNameValid(slotAnimName) )
			return;
		
		if ( interactionAnim != PEA_None )
		{
			if ( this.attachThisObjectOnAnimEvent )
			{
				thePlayer.AddAnimEventChildCallback(this,attachAnimName,'OnAnimEvent_Custom');
				thePlayer.AddAnimEventChildCallback(this,detachAnimName,'OnAnimEvent_Custom');
			}
				
			thePlayer.RegisterForPlayerAction(this, false);
			
			if ( ShouldBlockGameplayActionsOnInteraction() )
			{
				BlockGameplayActions(true);
			}
			
			if ( !GetToPointAndStartAction() )
				OnPlayerActionEnd();
			
			isPlayingInteractionAnim = true;
			
			if ( interactionAnim == PEA_SlotAnimation )
				return;
			
			if ( interactionAnimTime < 1.0f )
			{
				interactionAnimTime = 1.0f;
			}
			AddTimer( 'TimerDeactivateAnimation', interactionAnimTime, false );	
		}
	}
	
	function BlockGameplayActions( lock : bool )
	{
		var exceptions : array< EInputActionBlock >;		
		exceptions.PushBack( EIAB_ExplorationFocus );
	
		if ( lock && holsterWeaponAtTheBeginning )
			thePlayer.OnEquipMeleeWeapon(PW_None,true);
		thePlayer.BlockAllActions('W3AnimationInteractionEntity', lock, exceptions);
	}
	
	function ShouldBlockGameplayActionsOnInteraction() : bool
	{
		return true;
	}
	
	function GetToPointAndStartAction() : bool
	{
		var movementAdjustor 				: CMovementAdjustor = thePlayer.GetMovingAgentComponent().GetMovementAdjustor();
		var ticket 							: SMovementAdjustmentRequestTicket = movementAdjustor.CreateNewRequest( 'InteractionEntity' );
		
		movementAdjustor.AdjustmentDuration( ticket, 0.5 );
		
		if ( matchPlayerHeadingWithHeadingOfTheEntity )
			movementAdjustor.RotateTowards( ticket, this );
		if ( desiredPlayerToEntityDistance >= 0 )
			movementAdjustor.SlideTowards( ticket, this, desiredPlayerToEntityDistance );
		
		return thePlayer.PlayerStartAction( interactionAnim, slotAnimName );
	}
	
	private var objectAttached : bool;
	private var objectCachedPos : Vector;
	private var objectCachedRot	: EulerAngles;
	
	private function AttachObject()
	{
		if ( objectAttached )
			return;
			
		objectCachedPos = this.GetWorldPosition();
		objectCachedRot = this.GetWorldRotation();
		this.CreateAttachment(thePlayer,attachSlotName);
		objectAttached = true;
	}
	
	private function DetachObject()
	{
		if ( !objectAttached )
			return;
			
		this.BreakAttachment();
		this.TeleportWithRotation(objectCachedPos,objectCachedRot);
		objectAttached = false;
	}
	
	//-------------------------------------------------------
	// Events
	
	// this will be called when player stops playing anim. If animation ends or he gets HIT etc.
	event OnPlayerActionEnd()
	{
		isPlayingInteractionAnim = false;
		thePlayer.UnregisterForPlayerAction(this, false);
		
		thePlayer.RemoveAnimEventChildCallback(this,attachAnimName);
		thePlayer.RemoveAnimEventChildCallback(this,detachAnimName);
		
		if ( ShouldBlockGameplayActionsOnInteraction() )
		{
			BlockGameplayActions(false);
		}
		DetachObject();
	}
	
	event OnAnimEvent_Custom( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
	{
		if ( animEventName == attachAnimName && attachThisObjectOnAnimEvent )
		{
			AttachObject();
		}
		if ( animEventName == detachAnimName )
		{
			DetachObject();
		}
	}
	
	//-------------------------------------------------------
	// Timers
	
	timer function TimerDeactivateAnimation( td : float , id : int)
	{
		thePlayer.PlayerStopAction( interactionAnim );		
	}
}



