class PlayerWeaponHandlingModifiers
{
	private var m_player : weak< PlayerPuppet >;
	var m_opSymbol : CName;
	var recoilGroup : array< gameConstantStatModifierData >;
	var timeOutGroup : array< gameConstantStatModifierData >;
	var multSwayGroup : array< gameConstantStatModifierData >;
	var addSwayGroup : array< gameConstantStatModifierData >;
	var spreadGroup : array< gameConstantStatModifierData >;

	public static function Create( player : weak< PlayerPuppet > ) : PlayerWeaponHandlingModifiers
	{
		var instance : PlayerWeaponHandlingModifiers;
		instance = new PlayerWeaponHandlingModifiers;
		instance.m_player = player;
		return instance;
	}

	public function OnAttach()
	{
		var i, limit : Int32;
		var statsSystem : StatsSystem;
		statsSystem = GameInstance.GetStatsSystem( m_player.GetGame() );
		recoilGroup.PushBack( ( ( gameConstantStatModifierData )( RPGManager.CreateStatModifier( gamedataStatType.RecoilAngle, gameStatModifierType.Multiplier, 1.0 ) ) ) );
		recoilGroup.PushBack( ( ( gameConstantStatModifierData )( RPGManager.CreateStatModifier( gamedataStatType.RecoilKickMin, gameStatModifierType.Multiplier, 1.0 ) ) ) );
		recoilGroup.PushBack( ( ( gameConstantStatModifierData )( RPGManager.CreateStatModifier( gamedataStatType.RecoilKickMax, gameStatModifierType.Multiplier, 1.0 ) ) ) );
		recoilGroup.PushBack( ( ( gameConstantStatModifierData )( RPGManager.CreateStatModifier( gamedataStatType.RecoilDir, gameStatModifierType.Multiplier, 1.0 ) ) ) );
		recoilGroup.PushBack( ( ( gameConstantStatModifierData )( RPGManager.CreateStatModifier( gamedataStatType.RecoilAlternateDir, gameStatModifierType.Multiplier, 1.0 ) ) ) );
		for( i = 0, limit = recoilGroup.Size(); i < limit; i += 1 )
		{
			statsSystem.AddModifier( m_player.GetEntityID(), recoilGroup[ i ] );
		}
		timeOutGroup.PushBack( ( ( gameConstantStatModifierData )( RPGManager.CreateStatModifier( gamedataStatType.RecoilHoldDuration, gameStatModifierType.Multiplier, 1.0 ) ) ) );
		timeOutGroup.PushBack( ( ( gameConstantStatModifierData )( RPGManager.CreateStatModifier( gamedataStatType.SwayTraversalTime, gameStatModifierType.Multiplier, 1.0 ) ) ) );
		for( i = 0, limit = timeOutGroup.Size(); i < limit; i += 1 )
		{
			statsSystem.AddModifier( m_player.GetEntityID(), timeOutGroup[ i ] );
		}
		multSwayGroup.PushBack( ( ( gameConstantStatModifierData )( RPGManager.CreateStatModifier( gamedataStatType.SwaySideMaximumAngleDistance, gameStatModifierType.Multiplier, 1.0 ) ) ) );
		multSwayGroup.PushBack( ( ( gameConstantStatModifierData )( RPGManager.CreateStatModifier( gamedataStatType.SwaySideMinimumAngleDistance, gameStatModifierType.Multiplier, 1.0 ) ) ) );
		for( i = 0, limit = multSwayGroup.Size(); i < limit; i += 1 )
		{
			statsSystem.AddModifier( m_player.GetEntityID(), multSwayGroup[ i ] );
		}
		addSwayGroup.PushBack( ( ( gameConstantStatModifierData )( RPGManager.CreateStatModifier( gamedataStatType.SwaySideTopAngleLimit, gameStatModifierType.Additive, 1.0 ) ) ) );
		addSwayGroup.PushBack( ( ( gameConstantStatModifierData )( RPGManager.CreateStatModifier( gamedataStatType.SwaySideBottomAngleLimit, gameStatModifierType.Additive, 1.0 ) ) ) );
		for( i = 0, limit = addSwayGroup.Size(); i < limit; i += 1 )
		{
			statsSystem.AddModifier( m_player.GetEntityID(), addSwayGroup[ i ] );
		}
		spreadGroup.PushBack( ( ( gameConstantStatModifierData )( RPGManager.CreateStatModifier( gamedataStatType.SpreadDefaultX, gameStatModifierType.Multiplier, 1.0 ) ) ) );
		spreadGroup.PushBack( ( ( gameConstantStatModifierData )( RPGManager.CreateStatModifier( gamedataStatType.SpreadAdsDefaultX, gameStatModifierType.Multiplier, 1.0 ) ) ) );
		spreadGroup.PushBack( ( ( gameConstantStatModifierData )( RPGManager.CreateStatModifier( gamedataStatType.SpreadDefaultY, gameStatModifierType.Multiplier, 1.0 ) ) ) );
		spreadGroup.PushBack( ( ( gameConstantStatModifierData )( RPGManager.CreateStatModifier( gamedataStatType.SpreadAdsDefaultY, gameStatModifierType.Multiplier, 1.0 ) ) ) );
		for( i = 0, limit = spreadGroup.Size(); i < limit; i += 1 )
		{
			statsSystem.AddModifier( m_player.GetEntityID(), spreadGroup[ i ] );
		}
	}

	public function UpdateEquippedWeaponsHandling( evt : UpdateEquippedWeaponsHandlingEvent, equippedRightHandWeapon : weak< WeaponObject > )
	{
		var statsSystem : StatsSystem;
		var weaponId : EntityID;
		var statsDataSystem : StatsDataSystem;
		var curveValue : Float;
		var i, limit : Int32;
		statsSystem = GameInstance.GetStatsSystem( m_player.GetGame() );
		weaponId = equippedRightHandWeapon.GetEntityID();
		statsDataSystem = GameInstance.GetStatsDataSystem( m_player.GetGame() );
		curveValue = ModifyCurveValue( statsDataSystem.GetValueFromCurve( 'player_staminahandling', evt.currentStaminaValue, 'recoil_group' ) );
		for( i = 0, limit = recoilGroup.Size(); i < limit; i += 1 )
		{
			statsSystem.RemoveAndUncacheModifier( weaponId, recoilGroup[ i ] );
			recoilGroup[ i ].value = curveValue;
			statsSystem.AddModifier( weaponId, recoilGroup[ i ] );
		}
		curveValue = ModifyCurveValue( statsDataSystem.GetValueFromCurve( 'player_staminahandling', evt.currentStaminaValue, 'timeout_group' ) );
		for( i = 0, limit = timeOutGroup.Size(); i < limit; i += 1 )
		{
			statsSystem.RemoveAndUncacheModifier( weaponId, timeOutGroup[ i ] );
			timeOutGroup[ i ].value = curveValue;
			statsSystem.AddModifier( weaponId, timeOutGroup[ i ] );
		}
		curveValue = ModifyCurveValue( statsDataSystem.GetValueFromCurve( 'player_staminahandling', evt.currentStaminaValue, 'mult_sway_group' ) );
		for( i = 0, limit = multSwayGroup.Size(); i < limit; i += 1 )
		{
			statsSystem.RemoveAndUncacheModifier( weaponId, multSwayGroup[ i ] );
			multSwayGroup[ i ].value = curveValue;
			statsSystem.AddModifier( weaponId, multSwayGroup[ i ] );
		}
		curveValue = ModifyCurveValue( statsDataSystem.GetValueFromCurve( 'player_staminahandling', evt.currentStaminaValue, 'add_sway_group' ) );
		for( i = 0, limit = addSwayGroup.Size(); i < limit; i += 1 )
		{
			statsSystem.RemoveAndUncacheModifier( weaponId, addSwayGroup[ i ] );
			addSwayGroup[ i ].value = curveValue;
			statsSystem.AddModifier( weaponId, addSwayGroup[ i ] );
		}
		curveValue = ModifyCurveValue( statsDataSystem.GetValueFromCurve( 'player_staminahandling', evt.currentStaminaValue, 'spread_group' ) );
		for( i = 0, limit = spreadGroup.Size(); i < limit; i += 1 )
		{
			statsSystem.RemoveAndUncacheModifier( weaponId, spreadGroup[ i ] );
			spreadGroup[ i ].value = curveValue;
			statsSystem.AddModifier( weaponId, spreadGroup[ i ] );
		}
	}

	public function RemoveHandlingModifiersFromWeapon( equippedRightHandWeapon : weak< WeaponObject > )
	{
		var weaponId : EntityID;
		var statsSystem : StatsSystem;
		var i, limit : Int32;
		weaponId = equippedRightHandWeapon.GetEntityID();
		statsSystem = GameInstance.GetStatsSystem( m_player.GetGame() );
		for( i = 0, limit = recoilGroup.Size(); i < limit; i += 1 )
		{
			statsSystem.RemoveModifier( weaponId, recoilGroup[ i ] );
		}
		for( i = 0, limit = timeOutGroup.Size(); i < limit; i += 1 )
		{
			statsSystem.RemoveModifier( weaponId, timeOutGroup[ i ] );
		}
		for( i = 0, limit = multSwayGroup.Size(); i < limit; i += 1 )
		{
			statsSystem.RemoveModifier( weaponId, multSwayGroup[ i ] );
		}
		for( i = 0, limit = addSwayGroup.Size(); i < limit; i += 1 )
		{
			statsSystem.RemoveModifier( weaponId, addSwayGroup[ i ] );
		}
		for( i = 0, limit = spreadGroup.Size(); i < limit; i += 1 )
		{
			statsSystem.RemoveModifier( weaponId, spreadGroup[ i ] );
		}
	}

	public function ModifyOpSymbol( symbol : CName )
	{
		m_opSymbol = symbol;
	}

	private function ModifyCurveValue( value : Float ) : Float
	{
		if( m_opSymbol == 'inv' )
		{
			return 1.0 / value;
		}
		return value;
	}

}

