abstract class AISignalCondition extends AIbehaviorconditionScript
{
	const editable var m_requiredFlags : array< AISignalFlags >;
	editable var m_consumesSignal : Bool;
	default m_consumesSignal = true;
	private var m_activated : Bool;
	protected var m_executingSignal : AIGateSignal;
	protected var m_executingSignalId : Uint32;

	protected virtual function GetSignalName() : CName
	{
		return '';
	}

	protected virtual function GetSignalEvaluationOutcome() : Bool
	{
		return false;
	}

	public virtual function GetEditorSubCaption() : String
	{
		return "Signal Name:  " + NameToString( GetSignalName() );
	}

	protected export override function Activate( context : ScriptExecutionContext )
	{
		m_activated = false;
	}

	protected export override function Deactivate( context : ScriptExecutionContext )
	{
		m_activated = false;
	}

	protected export override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		if( !( m_activated ) )
		{
			if( !( StartExecuting( context ) ) )
			{
				return false;
			}
			m_activated = true;
		}
		else
		{
			if( !( KeepExecuting( context ) ) )
			{
				return false;
			}
		}
		return true;
	}

	protected final function CheckFlagRequirements( gateSignal : ref< AIGateSignal >, checkAgainst : AISignalFlags ) : Bool
	{
		if( m_requiredFlags.Contains( checkAgainst ) )
		{
			if( !( AIGateSignal.IsEmpty( gateSignal ) ) && AIGateSignal.HasFlag( gateSignal, checkAgainst ) )
			{
				return true;
			}
		}
		return false;
	}

	protected final function IsActivated() : Bool
	{
		return m_activated;
	}

	protected final function GetSignalHandler( context : ScriptExecutionContext ) : AISignalHandlerComponent
	{
		return GetPuppet( context ).GetSignalHandlerComponent();
	}

	protected final function GetSignalTable( context : ScriptExecutionContext ) : gameBoolSignalTable
	{
		return GetPuppet( context ).GetAIControllerComponent().GetSignals();
	}

	private final function StartExecuting( context : ScriptExecutionContext ) : Bool
	{
		var signalHandler : AISignalHandlerComponent;
		var signalId : Uint32;
		if( !( GetSignalHandler( context ).IsHighestPriority( GetSignalName(), signalId ) ) )
		{
			return false;
		}
		signalHandler = GetSignalHandler( context );
		m_executingSignalId = signalId;
		signalHandler.GetSignal( m_executingSignalId, m_executingSignal );
		if( m_consumesSignal )
		{
			signalHandler.ConsumeSignal( GetSignalName() );
		}
		return true;
	}

	private final function KeepExecuting( context : ScriptExecutionContext ) : Bool
	{
		var signalId : Uint32;
		var signal : AIGateSignal;
		if( GetSignalHandler( context ).GetHighestPrioritySignal( signal, signalId ) )
		{
			if( signal.priority > m_executingSignal.priority )
			{
				return false;
			}
			else if( ( ( ( AIGateSignal.HasFlag( signal, AISignalFlags.OverridesSelf ) || AIGateSignal.HasFlag( signal, AISignalFlags.InterruptsSamePriorityTask ) ) && ( signalId != m_executingSignalId ) ) && ( signal.priority >= m_executingSignal.priority ) ) && AIGateSignal.HasTag( signal, GetSignalName() ) )
			{
				return false;
			}
		}
		return true;
	}

}

class CustomEventCondition extends AISignalCondition
{
	editable var m_eventName : CName;

	protected override function GetSignalName() : CName
	{
		return m_eventName;
	}

	public override function GetDescription( context : ScriptExecutionContext ) : String
	{
		if( !( IsActivated() ) )
		{
			return ( "GateSignal(" + ( ( String )( GetSignalName() ) ) ) + ")";
		}
		return ( ( ( ( ( "GateSignal(" + ( ( String )( GetSignalName() ) ) ) + ", activated=" ) + ( ( IsActivated() ) ? ( "true" ) : ( "false" ) ) ) + ", prio=" ) + ( ( String )( m_executingSignal.priority ) ) ) + ")";
	}

}

class PriorityCheckEventCondition extends AISignalCondition
{

	protected override function GetSignalEvaluationOutcome() : Bool
	{
		return true;
	}

}

class HighestPrioritySignalCondition extends AIbehaviorexpressionScript
{
	editable var m_signalName : CName;
	protected var m_cbId : Uint32;
	protected var m_lastValue : Bool;

	public export function Activate( context : ScriptExecutionContext )
	{
		m_cbId = ScriptExecutionContext.AddBehaviorCallback( context, 'OnHighestPrioritySignalBecameDirty', this );
		m_lastValue = false;
	}

	public export function Deactivate( context : ScriptExecutionContext )
	{
		ScriptExecutionContext.RemoveBehaviorCallback( context, m_cbId );
	}

	public export function CalculateValue( context : ScriptExecutionContext ) : Variant
	{
		var signalId : Uint32;
		var signal : AIGateSignal;
		if( GetSignalHandler( context ).GetHighestPrioritySignal( signal, signalId ) )
		{
			if( AIGateSignal.HasTag( signal, m_signalName ) )
			{
				m_lastValue = true;
				return true;
			}
			m_lastValue = false;
			return false;
		}
		else
		{
			return m_lastValue;
		}
	}

	protected final function GetSignalHandler( context : ScriptExecutionContext ) : AISignalHandlerComponent
	{
		return GetPuppet( context ).GetSignalHandlerComponent();
	}

	public function GetEditorSubCaption() : String
	{
		return ( "GateSignal(" + ( ( String )( m_signalName ) ) ) + ")";
	}

}

class CheckAbilityCanRetreat extends AIbehaviorconditionScript
{

	protected export override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		return GameInstance.GetStatsSystem( ScriptExecutionContext.GetOwner( context ).GetGame() ).GetStatBoolValue( ScriptExecutionContext.GetOwner( context ).GetEntityID(), gamedataStatType.CanRetreat );
	}

}

