class CoverCommandParams extends IScriptable
{
	const editable var exposureMethods : array< AICoverExposureMethod >;
}

class UseCoverCommandTask extends AIbehaviortaskScript
{
	protected editable inlined var m_inCommand : AIArgumentMapping;
	protected var m_currentCommand : weak< AIUseCoverCommand >;

	protected export override function Activate( context : ScriptExecutionContext )
	{
		SetUpdateInterval( context, RandomizeOffsetForUpdateInterval( 1.0 ) );
	}

	protected export override function Update( context : ScriptExecutionContext ) : AIbehaviorUpdateOutcome
	{
		var rawCommand : IScriptable;
		var typedCommand : AIUseCoverCommand;
		var coverID : Uint64;
		var cm : CoverManager;
		var aiComponent : AIHumanComponent;
		var tmpID : Uint64;
		var coverDemandHolder : CoverDemandHolder;
		rawCommand = ScriptExecutionContext.GetScriptableMappingValue( context, m_inCommand );
		typedCommand = ( ( AIUseCoverCommand )( rawCommand ) );
		aiComponent = GetPuppet( context ).GetAIControllerComponent();
		if( !( typedCommand ) )
		{
			if( m_currentCommand )
			{
				CancelCommand( context, typedCommand, aiComponent );
			}
			return AIbehaviorUpdateOutcome.IN_PROGRESS;
		}
		if( typedCommand == m_currentCommand )
		{
			if( ( typedCommand.oneTimeSelection && AIActionTarget.GetCurrentCoverID( context, coverID ) ) && ( coverID == ScriptExecutionContext.GetArgumentUint64( context, 'CommandCoverID' ) ) )
			{
				CancelCommand( context, typedCommand, aiComponent );
				if( typedCommand && typedCommand.state == AICommandState.Executing )
				{
					aiComponent.StopExecutingCommand( typedCommand, true );
				}
			}
			return AIbehaviorUpdateOutcome.IN_PROGRESS;
		}
		cm = GameInstance.GetCoverManager( GetGame( context ) );
		if( !( cm ) )
		{
		}
		else
		{
			coverDemandHolder = cm.GetDemandCoverHolder( typedCommand.coverNodeRef );
			if( coverDemandHolder )
			{
				coverID = coverDemandHolder.GetCoverID();
			}
		}
		if( ( coverID == ( ( Uint64 )( 0 ) ) ) || !( cm.IsCoverValid( coverID ) ) )
		{
			ScriptExecutionContext.DebugLog( context, 'AIUseCoverCommand', "Trying to select invalid cover or cover with ID == 0!" );
			CancelCommand( context, typedCommand, aiComponent );
			if( typedCommand && typedCommand.state == AICommandState.Executing )
			{
				aiComponent.StopExecutingCommand( typedCommand, true );
			}
			return AIbehaviorUpdateOutcome.FAILURE;
		}
		tmpID = ScriptExecutionContext.GetArgumentUint64( context, 'CommandCoverID' );
		if( tmpID != coverID )
		{
			ScriptExecutionContext.SetArgumentUint64( context, 'CommandCoverID', coverID );
			AICoverHelper.RegisterNewCover( GetPuppet( context ), coverID );
		}
		GetPuppet( context ).GetAIControllerComponent().GetCoverBlackboard().SetVariant( GetAllBlackboardDefs().AICover.commandExposureMethods, ( ( CoverCommandParams )( typedCommand.limitToTheseExposureMethods ) ) );
		ScriptExecutionContext.SetArgumentBool( context, 'StopCover', false );
		ScriptExecutionContext.SetArgumentName( context, 'ForcedEntryAnimation', typedCommand.forcedEntryAnimation );
		m_currentCommand = typedCommand;
		return AIbehaviorUpdateOutcome.IN_PROGRESS;
	}

	private export override final function Deactivate( context : ScriptExecutionContext )
	{
		var rawCommand : IScriptable;
		var typedCommand : AIUseCoverCommand;
		var aiComponent : AIHumanComponent;
		if( !( m_currentCommand ) )
		{
			return;
		}
		rawCommand = ScriptExecutionContext.GetScriptableMappingValue( context, m_inCommand );
		typedCommand = ( ( AIUseCoverCommand )( rawCommand ) );
		AIHumanComponent.Get( ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) ), aiComponent );
		if( !( typedCommand ) )
		{
			CancelCommand( context, typedCommand, aiComponent );
		}
		else if( ScriptExecutionContext.GetArgumentBool( context, 'StopCover' ) )
		{
			if( ( typedCommand && typedCommand.state == AICommandState.Executing ) && aiComponent )
			{
				aiComponent.StopExecutingCommand( typedCommand, true );
			}
			CancelCommand( context, typedCommand, aiComponent );
		}
	}

	protected final function CancelCommand( context : ScriptExecutionContext, typedCommand : AIUseCoverCommand, aiComponent : AIHumanComponent )
	{
		var tmpID : Uint64;
		tmpID = ScriptExecutionContext.GetArgumentUint64( context, 'CommandCoverID' );
		if( tmpID != ( ( Uint64 )( 0 ) ) )
		{
			ScriptExecutionContext.SetArgumentUint64( context, 'CommandCoverID', ( ( Uint64 )( 0 ) ) );
		}
		ScriptExecutionContext.SetMappingValue( context, m_inCommand, NULL );
		if( m_currentCommand )
		{
			m_currentCommand = NULL;
		}
		if( aiComponent )
		{
			aiComponent.GetCoverBlackboard().SetVariant( GetAllBlackboardDefs().AICover.commandExposureMethods, ( ( CoverCommandParams )( NULL ) ) );
		}
	}

}

class UseCoverCommandCleanup extends AIbehaviortaskScript
{
	protected editable inlined var m_inCommand : AIArgumentMapping;

	private export override final function Deactivate( context : ScriptExecutionContext )
	{
		var coverID : Uint64;
		coverID = GameInstance.GetCoverManager( GetPuppet( context ).GetGame() ).GetCurrentCover( GetPuppet( context ) );
		if( coverID == ( ( Uint64 )( 0 ) ) )
		{
			AICoverHelper.UnregisterLastCover( GetPuppet( context ) );
		}
		ScriptExecutionContext.SetMappingValue( context, m_inCommand, NULL );
	}

}

class UseCoverCommandHandler extends AIbehaviortaskScript
{
	protected editable inlined var m_inCommand : AIArgumentMapping;
	protected var m_currentCommand : weak< AIUseCoverCommand >;

	private override final function Activate( context : ScriptExecutionContext )
	{
		var rawCommand : IScriptable;
		var typedCommand : AIUseCoverCommand;
		m_currentCommand = NULL;
		rawCommand = ScriptExecutionContext.GetScriptableMappingValue( context, m_inCommand );
		typedCommand = ( ( AIUseCoverCommand )( rawCommand ) );
		if( typedCommand )
		{
			m_currentCommand = typedCommand;
		}
		SetUpdateInterval( context, RandomizeOffsetForUpdateInterval( 0.2 ) );
	}

	protected override function Update( context : ScriptExecutionContext ) : AIbehaviorUpdateOutcome
	{
		var rawCommand : IScriptable;
		var typedCommand : AIUseCoverCommand;
		var aiComponent : AIHumanComponent;
		var waitBeforeExit : Bool;
		rawCommand = ScriptExecutionContext.GetScriptableMappingValue( context, m_inCommand );
		typedCommand = ( ( AIUseCoverCommand )( rawCommand ) );
		if( !( typedCommand ) )
		{
			return AIbehaviorUpdateOutcome.IN_PROGRESS;
		}
		if( m_currentCommand )
		{
			waitBeforeExit = GameInstance.GetCoverManager( GetGame( context ) ).IsEnteringOrLeavingCover( ScriptExecutionContext.GetOwner( context ) );
			if( typedCommand == m_currentCommand )
			{
				aiComponent = GetPuppet( context ).GetAIControllerComponent();
				if( aiComponent.GetCoverBlackboard().GetBool( GetAllBlackboardDefs().AICover.commandCoverOverride ) && !( waitBeforeExit ) )
				{
					aiComponent.GetCoverBlackboard().SetBool( GetAllBlackboardDefs().AICover.commandCoverOverride, false );
					return AIbehaviorUpdateOutcome.SUCCESS;
				}
				return AIbehaviorUpdateOutcome.IN_PROGRESS;
			}
			else if( !( waitBeforeExit ) )
			{
				return AIbehaviorUpdateOutcome.SUCCESS;
			}
			aiComponent = GetPuppet( context ).GetAIControllerComponent();
			aiComponent.GetCoverBlackboard().SetBool( GetAllBlackboardDefs().AICover.commandCoverOverride, true );
			return AIbehaviorUpdateOutcome.IN_PROGRESS;
		}
		m_currentCommand = typedCommand;
		return AIbehaviorUpdateOutcome.SUCCESS;
	}

	private function WaitBeforeExit( context : ScriptExecutionContext ) : Bool
	{
		var aiComponent : AIHumanComponent;
		aiComponent = GetPuppet( context ).GetAIControllerComponent();
		if( GameInstance.GetCoverManager( GetGame( context ) ).IsEnteringOrLeavingCover( ScriptExecutionContext.GetOwner( context ) ) )
		{
			return true;
		}
		if( aiComponent.GetCoverBlackboard().GetBool( GetAllBlackboardDefs().AICover.currentlyExposed ) )
		{
			return true;
		}
		return false;
	}

}

