class OnStatusEffectAppliedListener extends ScriptStatusEffectListener
{
	var m_effector : weak< ModifyStatusEffectDurationEffector >;
	var m_tags : array< CName >;
	var m_owner : weak< GameObject >;

	public virtual function OnStatusEffectApplied( statusEffect : weak< StatusEffect_Record > )
	{
		var j : Int32;
		for( j = 0; j < m_tags.Size(); j += 1 )
		{
			if( StatusEffectHelper.HasTag( statusEffect, m_tags[ j ] ) )
			{
				m_effector.ProcessAction( m_owner );
			}
		}
	}

}

class ModifyStatusEffectDurationEffector extends Effector
{
	private var m_statusEffectListener : OnStatusEffectAppliedListener;
	var m_tags : array< CName >;
	var m_change : Float;
	var m_isPercentage : Bool;
	var m_listenConstantly : Bool;
	var m_canGoOverInitialDuration : Bool;
	var m_gameInstance : GameInstance;

	protected export override function Initialize( record : TweakDBID, game : GameInstance, parentRecord : TweakDBID )
	{
		m_tags = TweakDBInterface.GetCNameArray( record + T".gameplayTags" );
		m_change = TweakDBInterface.GetFloat( record + T".change", 0.0 );
		m_isPercentage = TweakDBInterface.GetBool( record + T".isPercentage", false );
		m_listenConstantly = TweakDBInterface.GetBool( record + T".listenConstantly", false );
		m_canGoOverInitialDuration = TweakDBInterface.GetBool( record + T".canGoOverInitialDuration", true );
		m_gameInstance = game;
	}

	public function ProcessAction( owner : GameObject )
	{
		var appliedStatusEffects : array< StatusEffect >;
		var i, j : Int32;
		var remainingDuration : Float;
		var durationValue : Float;
		var finalChange : Float;
		var duration : weak< StatModifierGroup_Record >;
		var statModifiers : array< weak< StatModifier_Record > >;
		durationValue = 1.0;
		finalChange = m_change;
		for( j = 0; j < m_tags.Size(); j += 1 )
		{
			if( StatusEffectHelper.GetAppliedEffectsWithTag( owner, m_tags[ j ], appliedStatusEffects ) )
			{
				for( i = 0; i < appliedStatusEffects.Size(); i += 1 )
				{
					remainingDuration = appliedStatusEffects[ i ].GetRemainingDuration();
					if( remainingDuration <= 0.0 )
					{
						continue;
					}
					duration = appliedStatusEffects[ i ].GetRecord().Duration();
					duration.StatModifiers( statModifiers );
					durationValue = RPGManager.CalculateStatModifiers( statModifiers, m_gameInstance, owner, owner.GetEntityID() );
					if( m_isPercentage )
					{
						finalChange = durationValue * ( m_change / 100.0 );
					}
					remainingDuration = MaxF( 0.0, remainingDuration + finalChange );
					if( !( m_canGoOverInitialDuration ) && ( remainingDuration > durationValue ) )
					{
						remainingDuration = durationValue;
					}
					GameInstance.GetStatusEffectSystem( m_gameInstance ).SetStatusEffectRemainingDuration( owner.GetEntityID(), appliedStatusEffects[ i ].GetRecord().GetID(), remainingDuration );
				}
			}
		}
	}

	protected export override function ActionOn( owner : GameObject )
	{
		ProcessAction( owner );
		if( m_listenConstantly )
		{
			m_statusEffectListener = new OnStatusEffectAppliedListener;
			m_statusEffectListener.m_owner = owner;
			m_statusEffectListener.m_tags = m_tags;
			m_statusEffectListener.m_effector = this;
			GameInstance.GetStatusEffectSystem( m_gameInstance ).RegisterListener( owner.GetEntityID(), m_statusEffectListener );
		}
	}

	protected export override function RepeatedAction( owner : GameObject )
	{
		ProcessAction( owner );
	}

	protected export override function ActionOff( owner : GameObject )
	{
		m_statusEffectListener = NULL;
	}

}

class ModifyStatusEffectDurationOnAttackEffector extends ModifyAttackEffector
{
	var m_tags : array< CName >;
	var m_change : Float;
	var m_isPercentage : Bool;
	var m_listenConstantly : Bool;
	var m_gameInstance : GameInstance;

	protected export override function Initialize( record : TweakDBID, game : GameInstance, parentRecord : TweakDBID )
	{
		m_tags = TweakDBInterface.GetCNameArray( record + T".gameplayTags" );
		m_change = TweakDBInterface.GetFloat( record + T".change", 0.0 );
		m_isPercentage = TweakDBInterface.GetBool( record + T".isPercentage", false );
		m_gameInstance = game;
	}

	public function ProcessAction( owner : GameObject )
	{
		var hitEvent : gameHitEvent;
		var appliedStatusEffects : array< StatusEffect >;
		var i, j : Int32;
		var remainingDuration : Float;
		var durationValue : Float;
		var finalChange : Float;
		var duration : weak< StatModifierGroup_Record >;
		var statModifiers : array< weak< StatModifier_Record > >;
		hitEvent = GetHitEvent();
		durationValue = 1.0;
		finalChange = m_change;
		for( j = 0; j < m_tags.Size(); j += 1 )
		{
			if( StatusEffectHelper.GetAppliedEffectsWithTag( hitEvent.target, m_tags[ j ], appliedStatusEffects ) )
			{
				for( i = 0; i < appliedStatusEffects.Size(); i += 1 )
				{
					remainingDuration = appliedStatusEffects[ i ].GetRemainingDuration();
					if( remainingDuration <= 0.0 )
					{
						continue;
					}
					if( m_isPercentage )
					{
						duration = appliedStatusEffects[ i ].GetRecord().Duration();
						duration.StatModifiers( statModifiers );
						durationValue = RPGManager.CalculateStatModifiers( statModifiers, m_gameInstance, owner, owner.GetEntityID() );
						finalChange = durationValue * ( m_change / 100.0 );
					}
					remainingDuration = MaxF( 0.0, remainingDuration + finalChange );
					GameInstance.GetStatusEffectSystem( m_gameInstance ).SetStatusEffectRemainingDuration( hitEvent.target.GetEntityID(), appliedStatusEffects[ i ].GetRecord().GetID(), remainingDuration );
				}
			}
		}
	}

	protected export override function ActionOn( owner : GameObject )
	{
		ProcessAction( owner );
	}

	protected export override function RepeatedAction( owner : GameObject )
	{
		ProcessAction( owner );
	}

}

