class ApplyStatGroupEffectorCallback extends AttachmentSlotsScriptCallback
{
	var m_effector : ApplyStatGroupEffector;

	public override function OnItemEquipped( slot : TweakDBID, item : ItemID )
	{
		m_effector.ApplyModifierGroup();
	}

	public override function OnItemUnequipped( slot : TweakDBID, item : ItemID )
	{
		m_effector.RemoveModifierGroup();
	}

}

class ApplyStatGroupEffector extends Effector
{
	var m_target : StatsObjectID;
	var m_record : TweakDBID;
	var m_applicationTarget : CName;
	var m_modGroupID : Uint64;
	var m_stackCount : Uint8;
	var m_removeWithEffector : Bool;
	var m_reapplyOnWeaponChange : Bool;
	default m_reapplyOnWeaponChange = false;
	var m_owner : weak< GameObject >;
	var m_ownerSlotCallback : ApplyStatGroupEffectorCallback;
	var m_ownerSlotListener : AttachmentSlotsScriptListener;

	protected export override function Initialize( record : TweakDBID, game : GameInstance, parentRecord : TweakDBID )
	{
		m_record = TweakDBInterface.GetApplyStatGroupEffectorRecord( record ).StatGroup().GetID();
		m_applicationTarget = TweakDBInterface.GetCName( record + T".applicationTarget", '' );
		m_removeWithEffector = TweakDBInterface.GetApplyStatGroupEffectorRecord( record ).RemoveWithEffector();
		if( m_applicationTarget == 'Weapon' )
		{
			m_reapplyOnWeaponChange = TweakDBInterface.GetBool( record + T".reapplyOnWeaponChange", false );
		}
		m_stackCount = 0;
	}

	protected export override function Uninitialize( game : GameInstance )
	{
		if( m_removeWithEffector )
		{
			RemoveModifierGroup();
		}
		if( m_reapplyOnWeaponChange && m_ownerSlotListener )
		{
			GameInstance.GetTransactionSystem( game ).UnregisterAttachmentSlotListener( m_owner, m_ownerSlotListener );
			m_ownerSlotCallback = NULL;
		}
	}

	protected override function RepeatedAction( owner : GameObject )
	{
		m_owner = owner;
		ProcessEffector();
	}

	protected export override function ActionOn( owner : GameObject )
	{
		m_owner = owner;
		ProcessEffector();
	}

	protected export override function ActionOff( owner : GameObject )
	{
		RemoveModifierGroup();
	}

	private function ProcessEffector()
	{
		if( m_reapplyOnWeaponChange && !( m_ownerSlotListener ) )
		{
			m_ownerSlotCallback = new ApplyStatGroupEffectorCallback;
			m_ownerSlotCallback.slotID = T"AttachmentSlots.WeaponRight";
			m_ownerSlotCallback.m_effector = this;
			m_ownerSlotListener = GameInstance.GetTransactionSystem( m_owner.GetGame() ).RegisterAttachmentSlotListener( m_owner, m_ownerSlotCallback );
		}
		ApplyModifierGroup();
	}

	public function ApplyModifierGroup()
	{
		var statsSystem : StatsSystem;
		statsSystem = GameInstance.GetStatsSystem( m_owner.GetGame() );
		if( !( GetApplicationTargetAsStatsObjectID( m_owner, m_applicationTarget, m_target ) ) )
		{
			return;
		}
		m_modGroupID = TDBID.ToNumber( m_record );
		statsSystem.DefineModifierGroupFromRecord( m_modGroupID, m_record );
		statsSystem.ApplyModifierGroup( m_target, m_modGroupID );
		m_stackCount += 1;
	}

	public function RemoveModifierGroup()
	{
		var statsSystem : StatsSystem;
		var i : Uint8;
		statsSystem = GameInstance.GetStatsSystem( m_owner.GetGame() );
		i = 0;
		if( StatsObjectID.IsDefined( m_target ) )
		{
			for( i; i < m_stackCount; i += 1 )
			{
				statsSystem.RemoveModifierGroup( m_target, m_modGroupID );
				statsSystem.UndefineModifierGroup( m_modGroupID );
			}
			m_stackCount = 0;
		}
	}

}

