class StatusEffectPrereqListener extends ScriptStatusEffectListener
{
	protected var m_state : weak< StatusEffectPrereqState >;

	public export virtual function OnStatusEffectApplied( statusEffect : weak< StatusEffect_Record > )
	{
		const var statusEffectPrereq : StatusEffectPrereq;
		if( m_state )
		{
			statusEffectPrereq = ( ( StatusEffectPrereq )( m_state.GetPrereq() ) );
			if( statusEffectPrereq && statusEffectPrereq.Evaluate( statusEffect ) )
			{
				m_state.StatusEffectUpdate( statusEffect, true );
			}
		}
	}

	public export virtual function OnStatusEffectRemoved( statusEffect : weak< StatusEffect_Record > )
	{
		const var statusEffectPrereq : StatusEffectPrereq;
		if( m_state )
		{
			statusEffectPrereq = ( ( StatusEffectPrereq )( m_state.GetPrereq() ) );
			if( statusEffectPrereq && statusEffectPrereq.Evaluate( statusEffect ) )
			{
				m_state.StatusEffectUpdate( statusEffect, false );
			}
		}
	}

	public function RegisterState( state : PrereqState )
	{
		m_state = ( ( StatusEffectPrereqState )( state ) );
	}

}

class StatusEffectPrereqState extends PrereqState
{
	var m_prereq : StatusEffectPrereq;
	var m_listener : StatusEffectPrereqListener;

	public virtual function StatusEffectUpdate( statusEffect : weak< StatusEffect_Record >, isApplied : Bool )
	{
		OnChanged( ( ( m_prereq.m_invert ) ? ( !( isApplied ) ) : ( isApplied ) ) );
	}

}

class StatusEffectPrereq extends IScriptablePrereq
{
	[ customEditor = "TweakDBGroupInheritance;StatusEffect" ]
	editable var m_statusEffectRecordID : TweakDBID;
	var m_tag : CName;
	var m_checkType : gamedataCheckType;
	var m_invert : Bool;
	var m_fireAndForget : Bool;
	var m_objectToCheck : CName;
	var m_evaluateOnRegister : Bool;
	default m_evaluateOnRegister = false;

	protected export const override function OnRegister( state : PrereqState, game : GameInstance, context : IScriptable ) : Bool
	{
		var owner : GameObject;
		var castedState : StatusEffectPrereqState;
		owner = ( ( GameObject )( context ) );
		castedState = ( ( StatusEffectPrereqState )( state ) );
		castedState.m_listener = new StatusEffectPrereqListener;
		castedState.m_listener.RegisterState( castedState );
		castedState.m_prereq = this;
		GameInstance.GetStatusEffectSystem( game ).RegisterListener( owner.GetEntityID(), castedState.m_listener );
		return ( ( m_evaluateOnRegister ) ? ( IsFulfilled( game, context ) ) : ( false ) );
	}

	protected export const override function OnUnregister( state : PrereqState, game : GameInstance, context : IScriptable )
	{
		var castedState : StatusEffectPrereqState;
		castedState = ( ( StatusEffectPrereqState )( state ) );
		castedState.m_listener = NULL;
	}

	protected export override function Initialize( recordID : TweakDBID )
	{
		var record : StatusEffectPrereq_Record;
		record = TweakDBInterface.GetStatusEffectPrereqRecord( recordID );
		m_statusEffectRecordID = record.StatusEffect().GetID();
		m_checkType = record.CheckType().Type();
		m_invert = record.Invert();
		m_tag = record.TagToCheck();
		m_objectToCheck = record.ObjectToCheck();
		m_evaluateOnRegister = record.EvaluateOnRegister();
		m_fireAndForget = TweakDBInterface.GetBool( recordID + T".fireAndForget", false );
	}

	public export const override function IsFulfilled( game : GameInstance, context : IScriptable ) : Bool
	{
		var object : GameObject;
		var statusEffectSystem : StatusEffectSystem;
		var result : Bool;
		statusEffectSystem = GameInstance.GetStatusEffectSystem( game );
		object = GetObjectToCheck( game, context );
		switch( m_checkType )
		{
			case gamedataCheckType.Tag:
				result = statusEffectSystem.HasStatusEffectWithTag( object.GetEntityID(), m_tag );
			break;
			case gamedataCheckType.Type:
				result = StatusEffectSystem.ObjectHasStatusEffectOfType( object, TweakDBInterface.GetStatusEffectRecord( m_statusEffectRecordID ).StatusEffectType().Type() );
			break;
			case gamedataCheckType.Record:
				result = statusEffectSystem.HasStatusEffect( object.GetEntityID(), m_statusEffectRecordID );
			break;
			default:
				result = statusEffectSystem.HasStatusEffect( object.GetEntityID(), m_statusEffectRecordID );
			break;
		}
		if( m_invert )
		{
			return !( result );
		}
		return result;
	}

	public const virtual function Evaluate( statusEffect : weak< StatusEffect_Record > ) : Bool
	{
		switch( m_checkType )
		{
			case gamedataCheckType.Tag:
				return StatusEffectHelper.HasTag( statusEffect, m_tag );
			case gamedataCheckType.Type:
				return TweakDBInterface.GetStatusEffectRecord( m_statusEffectRecordID ).StatusEffectType().Type() == statusEffect.StatusEffectType().Type();
			case gamedataCheckType.Record:
				return m_statusEffectRecordID == statusEffect.GetID();
			default:
				return m_statusEffectRecordID == statusEffect.GetID();
		}
	}

	protected export const override function OnApplied( state : PrereqState, game : GameInstance, context : IScriptable )
	{
		var result : Bool;
		result = IsFulfilled( game, context );
		state.OnChanged( result );
	}

	private const function GetObjectToCheck( game : GameInstance, context : IScriptable ) : GameObject
	{
		if( m_objectToCheck == 'Player' )
		{
			return GetPlayer( game );
		}
		return ( ( GameObject )( context ) );
	}

}

