class UIInventoryItemGrenadeData
{
	var Type : GrenadeDamageType;
	var Range : Float;
	var DeliveryMethod : gamedataGrenadeDeliveryMethodType;
	var Duration : Float;
	var Delay : Float;
	var DetonationTimer : Float;
	var DamagePerTick : Float;
	var DamageType : gamedataStatType;
	var GrenadeType : EGrenadeType;
	var TotalDamage : Float;
	var m_Player : weak< PlayerPuppet >;

	private static function GetGrenadeContinousEffector( attackRecord : weak< Attack_Record > ) : weak< ContinuousAttackEffector_Record >
	{
		var i, j, k : Int32;
		var statusEffects : array< weak< StatusEffectAttackData_Record > >;
		var statusEffectPackages : array< weak< GameplayLogicPackage_Record > >;
		var statusEffectEffectors : array< weak< Effector_Record > >;
		var continuousAttackEffector : weak< ContinuousAttackEffector_Record >;
		attackRecord.StatusEffects( statusEffects );
		for( i = 0; i < statusEffects.Size(); i += 1 )
		{
			statusEffects[ i ].StatusEffect().Packages( statusEffectPackages );
			for( j = 0; j < statusEffectPackages.Size(); j += 1 )
			{
				statusEffectPackages[ j ].Effectors( statusEffectEffectors );
				for( k = 0; k < statusEffectEffectors.Size(); k += 1 )
				{
					if( statusEffectEffectors[ k ].EffectorClassName() == 'TriggerContinuousAttackEffector' )
					{
						continuousAttackEffector = ( ( weak< weak< ContinuousAttackEffector_Record > > )( statusEffectEffectors[ k ] ) );
						if( continuousAttackEffector )
						{
							return continuousAttackEffector;
						}
					}
				}
			}
		}
		return NULL;
	}

	private static function GetGrenadeTotalDamageFromStats( itemData : weak< gameItemData > ) : Float
	{
		var i : Int32;
		var result : Float;
		var damageData : array< InventoryTooltiData_GrenadeDamageData >;
		GetGrenadeDamageStats( itemData, damageData );
		for( i = 0; i < damageData.Size(); i += 1 )
		{
			result += damageData[ i ].value;
		}
		return result;
	}

	private static function GetGrenadeDamageStats( itemData : weak< gameItemData >, outputArray : ref< array< InventoryTooltiData_GrenadeDamageData > > )
	{
		var value : Float;
		var damageData : InventoryTooltiData_GrenadeDamageData;
		value = itemData.GetStatValueByType( gamedataStatType.BaseDamage );
		if( value > 0.0001 )
		{
			damageData = new InventoryTooltiData_GrenadeDamageData;
			damageData.statType = gamedataStatType.BaseDamage;
			damageData.value = value;
			outputArray.PushBack( damageData );
		}
		value = itemData.GetStatValueByType( gamedataStatType.PhysicalDamage );
		if( value > 0.0001 )
		{
			damageData = new InventoryTooltiData_GrenadeDamageData;
			damageData.statType = gamedataStatType.PhysicalDamage;
			damageData.value = value;
			outputArray.PushBack( damageData );
		}
		value = itemData.GetStatValueByType( gamedataStatType.ChemicalDamage );
		if( value > 0.0001 )
		{
			damageData = new InventoryTooltiData_GrenadeDamageData;
			damageData.statType = gamedataStatType.ChemicalDamage;
			damageData.value = value;
			outputArray.PushBack( damageData );
		}
		value = itemData.GetStatValueByType( gamedataStatType.ElectricDamage );
		if( value > 0.0001 )
		{
			damageData = new InventoryTooltiData_GrenadeDamageData;
			damageData.statType = gamedataStatType.ElectricDamage;
			damageData.value = value;
			outputArray.PushBack( damageData );
		}
		value = itemData.GetStatValueByType( gamedataStatType.ThermalDamage );
		if( value > 0.0001 )
		{
			damageData = new InventoryTooltiData_GrenadeDamageData;
			damageData.statType = gamedataStatType.ThermalDamage;
			damageData.value = value;
			outputArray.PushBack( damageData );
		}
	}

	private static function GetGrenadeDoTTickDamage( player : weak< PlayerPuppet >, continuousAttackEffector : weak< ContinuousAttackEffector_Record > ) : Float
	{
		var continuousAttackRecord : weak< Attack_Record >;
		var continuousAttackStatModifiers : array< weak< StatModifier_Record > >;
		if( continuousAttackEffector )
		{
			continuousAttackRecord = continuousAttackEffector.AttackRecord();
			continuousAttackRecord.StatModifiers( continuousAttackStatModifiers );
			return RPGManager.CalculateStatModifiers( continuousAttackStatModifiers, player.GetGame(), player, player.GetEntityID() );
		}
		return 0.0;
	}

	private static function GetGrenadeRange( grenadeRecord : weak< Grenade_Record >, player : weak< PlayerPuppet > ) : Float
	{
		var i : Int32;
		var result : Float;
		var statModifier : array< weak< StatModifier_Record > >;
		var rangeStatModifier : array< weak< StatModifier_Record > >;
		result = grenadeRecord.AttackRadius();
		grenadeRecord.StatModifiers( statModifier );
		for( i = statModifier.Size() - 1; i > 0; i -= 1 )
		{
			if( statModifier[ i ].StatType().StatType() == gamedataStatType.Range )
			{
				if( ( ( CombinedStatModifier_Record )( statModifier[ i ] ) ) || ( ( ConstantStatModifier_Record )( statModifier[ i ] ) ) )
				{
					rangeStatModifier.PushBack( statModifier[ i ] );
				}
			}
		}
		result = RPGManager.CalculateStatModifiers( rangeStatModifier, player.GetGame(), player, player.GetEntityID() );
		return result;
	}

	public static function GetGrenadeType( grenadeRecord : weak< Grenade_Record > ) : EGrenadeType
	{
		var tags : array< CName >;
		tags = grenadeRecord.Tags();
		if( tags.Contains( 'FragGrenade' ) )
		{
			return EGrenadeType.Frag;
		}
		if( tags.Contains( 'FlashGrenade' ) )
		{
			return EGrenadeType.Flash;
		}
		if( tags.Contains( 'SmokeGrenade' ) )
		{
			return EGrenadeType.Smoke;
		}
		if( tags.Contains( 'PiercingGrenade' ) )
		{
			return EGrenadeType.Piercing;
		}
		if( tags.Contains( 'EMPGrenade' ) )
		{
			return EGrenadeType.EMP;
		}
		if( tags.Contains( 'BiohazardGrenade' ) )
		{
			return EGrenadeType.Biohazard;
		}
		if( tags.Contains( 'IncendiaryGrenade' ) )
		{
			return EGrenadeType.Incendiary;
		}
		if( tags.Contains( 'ReconGrenade' ) )
		{
			return EGrenadeType.Recon;
		}
		if( tags.Contains( 'CuttingGrenade' ) )
		{
			return EGrenadeType.Cutting;
		}
		if( tags.Contains( 'SonicGrenade' ) )
		{
			return EGrenadeType.Sonic;
		}
		return EGrenadeType.Frag;
	}

	private static function GetGrenadeDuration( player : weak< PlayerPuppet >, attackRecord : weak< Attack_Record > ) : Float
	{
		var i : Int32;
		var statusEffects : array< weak< StatusEffectAttackData_Record > >;
		var durationModifiersRecord : weak< StatModifierGroup_Record >;
		var durationStatModifiers : array< weak< StatModifier_Record > >;
		attackRecord.StatusEffects( statusEffects );
		for( i = 0; i < statusEffects.Size(); i += 1 )
		{
			durationModifiersRecord = statusEffects[ i ].StatusEffect().Duration();
			if( durationModifiersRecord )
			{
				durationModifiersRecord.StatModifiers( durationStatModifiers );
				return RPGManager.CalculateStatModifiers( durationStatModifiers, player.GetGame(), player, player.GetEntityID() );
			}
		}
		return 0.0;
	}

	private static function GetGrenadeDelay( continuousAttackEffector : weak< ContinuousAttackEffector_Record > ) : Float
	{
		if( continuousAttackEffector )
		{
			return continuousAttackEffector.DelayTime();
		}
		return 0.0;
	}

	public static function Make( item : weak< UIInventoryItem >, player : weak< PlayerPuppet > ) : UIInventoryItemGrenadeData
	{
		var instance : UIInventoryItemGrenadeData;
		var grenadeRecord : weak< Grenade_Record >;
		var continousEffector : weak< ContinuousAttackEffector_Record >;
		var deliveryRecord : weak< GrenadeDeliveryMethod_Record >;
		instance = new UIInventoryItemGrenadeData;
		grenadeRecord = TweakDBInterface.GetGrenadeRecord( item.GetTweakDBID() );
		if( grenadeRecord )
		{
			continousEffector = GetGrenadeContinousEffector( grenadeRecord.Attack() );
			instance.Range = GetGrenadeRange( grenadeRecord, player );
			deliveryRecord = grenadeRecord.DeliveryMethod();
			instance.DeliveryMethod = deliveryRecord.Type().Type();
			instance.DetonationTimer = deliveryRecord.DetonationTimer();
			if( continousEffector )
			{
				instance.Duration = GetGrenadeDuration( player, grenadeRecord.Attack() );
				instance.Delay = GetGrenadeDelay( continousEffector );
				instance.DamagePerTick = GetGrenadeDoTTickDamage( player, continousEffector );
				instance.Type = GrenadeDamageType.DoT;
				instance.TotalDamage = instance.DamagePerTick * ( instance.Duration / instance.Delay );
				instance.GrenadeType = GetGrenadeType( grenadeRecord );
			}
			else
			{
				instance.Type = GrenadeDamageType.Normal;
				instance.TotalDamage = GetGrenadeTotalDamageFromStats( item.GetItemData() );
			}
		}
		return instance;
	}

}

