abstract class ConsumableTransitions extends DefaultTransition
{

	protected function IsUsingFluffConsumable( stateContext : StateContext ) : Bool
	{
		var activeItem : ItemID;
		var itemType : gamedataItemType;
		activeItem = GetItemIDFromWrapperPermanentParameter( stateContext, 'consumable' );
		itemType = TweakDBInterface.GetItemRecord( ItemID.GetTDBID( activeItem ) ).ItemType().Type();
		if( itemType == gamedataItemType.Con_Edible )
		{
			return true;
		}
		return false;
	}

	protected function ChangeConsumableAnimFeature( stateContext : StateContext, scriptInterface : StateGameScriptInterface, newState : Bool )
	{
		var consumableAnimFeature : AnimFeature_ConsumableAnimation;
		var activeItem : ItemID;
		var itemType : gamedataItemType;
		var inCombat : Bool;
		var isPerkFasterHealingUnlocked : Bool;
		activeItem = GetItemIDFromWrapperPermanentParameter( stateContext, 'consumable' );
		itemType = TweakDBInterface.GetItemRecord( ItemID.GetTDBID( activeItem ) ).ItemType().Type();
		inCombat = ( ( PlayerPuppet )( scriptInterface.GetPlayerSystem().GetLocalPlayerMainGameObject() ) ).IsInCombat();
		isPerkFasterHealingUnlocked = PlayerDevelopmentSystem.GetData( scriptInterface.executionOwner ).IsNewPerkBought( gamedataNewPerkType.Tech_Left_Perk_2_3 ) > 0;
		consumableAnimFeature = new AnimFeature_ConsumableAnimation;
		consumableAnimFeature.useConsumable = newState;
		switch( itemType )
		{
			case gamedataItemType.Con_Injector:
				consumableAnimFeature.consumableType = 0;
			if( inCombat && isPerkFasterHealingUnlocked )
			{
				consumableAnimFeature.animationScale = 1.64999998;
			}
			else
			{
				consumableAnimFeature.animationScale = 1.14999998;
			}
			break;
			case gamedataItemType.Con_Inhaler:
				consumableAnimFeature.consumableType = 1;
			if( inCombat && isPerkFasterHealingUnlocked )
			{
				consumableAnimFeature.animationScale = 1.5;
			}
			else
			{
				consumableAnimFeature.animationScale = 1.14999998;
			}
			break;
		}
		scriptInterface.SetAnimationParameterFeature( 'ConsumableFeature', consumableAnimFeature, scriptInterface.executionOwner );
	}

	protected function SetItemInLeftHand( scriptInterface : StateGameScriptInterface, newState : Bool )
	{
		var animFeature : AnimFeature_LeftHandItem;
		animFeature = new AnimFeature_LeftHandItem;
		animFeature.itemInLeftHand = newState;
		scriptInterface.SetAnimationParameterFeature( 'LeftHandItem', animFeature, scriptInterface.executionOwner );
	}

	protected const function GetConsumableCastPoint( consumableItem : ItemID ) : Float
	{
		var castPoint : Float;
		castPoint = TweakDBInterface.GetConsumableItemRecord( ItemID.GetTDBID( consumableItem ) ).CastPoint();
		return castPoint;
	}

	protected const function GetConsumableCycleDuration( consumableItem : ItemID ) : Float
	{
		var cycleDuration : Float;
		cycleDuration = TweakDBInterface.GetConsumableItemRecord( ItemID.GetTDBID( consumableItem ) ).CycleDuration();
		return cycleDuration;
	}

	protected const function GetConsumableInitBlendDuration( consumableItem : ItemID ) : Float
	{
		return TweakDBInterface.GetConsumableItemRecord( ItemID.GetTDBID( consumableItem ) ).InitBlendDuration();
	}

	protected const function GetConsumableRemovePoint( consumableItem : ItemID ) : Float
	{
		return TweakDBInterface.GetConsumableItemRecord( ItemID.GetTDBID( consumableItem ) ).RemovePoint();
	}

	protected const function ForceUnequipEvent( scriptInterface : StateGameScriptInterface )
	{
		var unequipEndEvent : UnequipEnd;
		unequipEndEvent = new UnequipEnd;
		unequipEndEvent.SetSlotID( T"AttachmentSlots.WeaponLeft" );
		scriptInterface.executionOwner.QueueEvent( unequipEndEvent );
	}

	protected function SetLeftHandAnimationAnimFeature( scriptInterface : StateGameScriptInterface, newState : Bool )
	{
		var animFeature : AnimFeature_LeftHandAnimation;
		animFeature = new AnimFeature_LeftHandAnimation;
		animFeature.lockLeftHandAnimation = newState;
		scriptInterface.SetAnimationParameterFeature( 'LeftHandAnimation', animFeature, scriptInterface.executionOwner );
	}

}

class ConsumableStartupDecisions extends ConsumableTransitions
{

	protected const function ToConsumableUse( stateContext : StateContext, scriptInterface : StateGameScriptInterface ) : Bool
	{
		return GetInStateTime() > GetConsumableInitBlendDuration( GetItemIDFromWrapperPermanentParameter( stateContext, 'consumable' ) );
	}

}

class ConsumableStartupEvents extends ConsumableTransitions
{

	protected function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		var blackboard : IBlackboard;
		var containerConsumable : ItemID;
		var isBloodPumpEquipped : Bool;
		var isHealingUninterruptable : Bool;
		var ts : TransactionSystem;
		var healingItem : gameItemData;
		var weapon : ItemObject;
		ts = scriptInterface.GetTransactionSystem();
		healingItem = ts.GetItemData( scriptInterface.owner, EquipmentSystem.GetData( scriptInterface.owner ).GetActiveConsumable() );
		isBloodPumpEquipped = 'BloodPump' == TweakDBInterface.GetCName( ItemID.GetTDBID( healingItem.GetID() ) + T".cyberwareType", '' );
		isHealingUninterruptable = !( isBloodPumpEquipped );
		if( GetPlayerPuppet( scriptInterface ).GetIsInWorkspotFinisher() && !( isBloodPumpEquipped ) )
		{
			return;
		}
		if( isHealingUninterruptable )
		{
			stateContext.SetPermanentBoolParameter( 'UninterruptableHealing', true, true );
		}
		blackboard = scriptInterface.GetBlackboardSystem().Get( GetAllBlackboardDefs().UI_QuickSlotsData );
		containerConsumable = ( ( ItemID )( blackboard.GetVariant( GetAllBlackboardDefs().UI_QuickSlotsData.containerConsumable ) ) );
		if( ItemID.IsValid( containerConsumable ) )
		{
			SetItemIDWrapperPermanentParameter( stateContext, 'consumable', containerConsumable );
			blackboard.SetVariant( GetAllBlackboardDefs().UI_QuickSlotsData.containerConsumable, ItemID.None() );
			blackboard.SetVariant( GetAllBlackboardDefs().UI_QuickSlotsData.consumableBeingUsed, containerConsumable );
		}
		else
		{
			SetItemIDWrapperPermanentParameter( stateContext, 'consumable', EquipmentSystem.GetData( scriptInterface.executionOwner ).GetActiveConsumable() );
			blackboard.SetVariant( GetAllBlackboardDefs().UI_QuickSlotsData.consumableBeingUsed, EquipmentSystem.GetData( scriptInterface.executionOwner ).GetActiveConsumable() );
		}
		if( !( IsUsingFluffConsumable( stateContext ) ) )
		{
			ForceDisableVisionMode( stateContext );
			ChangeConsumableAnimFeature( stateContext, scriptInterface, true );
			SetItemInLeftHand( scriptInterface, true );
			scriptInterface.PushAnimationEvent( 'UseConsumable' );
			scriptInterface.GetBlackboardSystem().Get( GetAllBlackboardDefs().PlayerPerkData ).SetUint( GetAllBlackboardDefs().PlayerPerkData.StartedUsingHealingItemOrCyberware, scriptInterface.GetBlackboardSystem().Get( GetAllBlackboardDefs().PlayerPerkData ).GetUint( GetAllBlackboardDefs().PlayerPerkData.StartedUsingHealingItemOrCyberware ) + 1 );
			weapon = scriptInterface.GetTransactionSystem().GetItemInSlot( scriptInterface.executionOwner, T"AttachmentSlots.WeaponRight" );
			if( weapon )
			{
				StateGameScriptInterface.PushAnimationEventToItem( weapon, 'UseConsumable' );
			}
		}
		SetLeftHandAnimationAnimFeature( scriptInterface, true );
		stateContext.SetTemporaryBoolParameter( 'CameraContext_ConsumableStartup', true, true );
		UpdateCameraParams( stateContext, scriptInterface );
		GameInstance.GetRazerChromaEffectsSystem( scriptInterface.executionOwner.GetGame() ).PlayAnimation( 'Booster', false );
	}

}

class ConsumableUseDecisions extends ConsumableTransitions
{

	protected const function ToConsumableCleanup( stateContext : StateContext, scriptInterface : StateGameScriptInterface ) : Bool
	{
		var hasConsumable : Bool;
		hasConsumable = scriptInterface.GetTransactionSystem().HasItem( scriptInterface.executionOwner, GetItemIDFromWrapperPermanentParameter( stateContext, 'consumable' ) );
		if( GetInStateTime() > GetConsumableCycleDuration( GetItemIDFromWrapperPermanentParameter( stateContext, 'consumable' ) ) )
		{
			return true;
		}
		else if( ( ( ( IsInLadderState( stateContext ) || IsInLocomotionState( stateContext, 'climb' ) ) || IsInHighLevelState( stateContext, 'swimming' ) ) || scriptInterface.executionOwner.IsDead() ) || !( hasConsumable ) )
		{
			stateContext.SetTemporaryBoolParameter( 'forceExit', true, true );
			return true;
		}
		return false;
	}

}

class ConsumableUseEvents extends ConsumableTransitions
{
	var effectsApplied : Bool;
	var modelRemoved : Bool;
	var activeConsumable : ItemID;

	protected function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		effectsApplied = false;
		modelRemoved = false;
		activeConsumable = GetItemIDFromWrapperPermanentParameter( stateContext, 'consumable' );
		SetLeftHandAnimationAnimFeature( scriptInterface, true );
		UpdateCameraParams( stateContext, scriptInterface );
	}

	protected function OnUpdate( timeDelta : Float, stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		var transactionSystem : TransactionSystem;
		if( !( effectsApplied ) && ( GetInStateTime() >= GetConsumableCastPoint( activeConsumable ) ) )
		{
			transactionSystem = scriptInterface.GetTransactionSystem();
			if( transactionSystem.HasItem( scriptInterface.executionOwner, activeConsumable ) )
			{
				if( ItemID.IsOfTDBID( activeConsumable, T"Items.Old_Inhaler" ) || ItemID.IsOfTDBID( activeConsumable, T"Items.Old_Injector" ) )
				{
					ItemActionsHelper.ConsumeItem( scriptInterface.executionOwner, activeConsumable, false );
				}
				else
				{
					ItemActionsHelper.UseHealCharge( scriptInterface.executionOwner, activeConsumable );
				}
				effectsApplied = true;
				GameInstance.GetTelemetrySystem( scriptInterface.executionOwner.GetGame() ).LogConsumableUsed( scriptInterface.executionOwner, activeConsumable );
			}
		}
		if( ( effectsApplied && !( modelRemoved ) ) && ( GetInStateTime() > GetConsumableRemovePoint( GetItemIDFromWrapperPermanentParameter( stateContext, 'consumable' ) ) ) )
		{
			ForceUnequipEvent( scriptInterface );
			modelRemoved = true;
		}
	}

}

class ConsumableCleanupDecisions extends ConsumableTransitions
{
}

class ConsumableCleanupEvents extends ConsumableTransitions
{

	protected function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		var psmRemove : PSMRemoveOnDemandStateMachine;
		var psmIdent : StateMachineIdentifier;
		var unequipType : gameEquipAnimationType;
		psmRemove = new PSMRemoveOnDemandStateMachine;
		SetLeftHandAnimationAnimFeature( scriptInterface, false );
		psmIdent.definitionName = 'Consumable';
		psmRemove.stateMachineIdentifier = psmIdent;
		scriptInterface.executionOwner.QueueEvent( psmRemove );
		if( stateContext.GetBoolParameter( 'forceExit' ) )
		{
			unequipType = gameEquipAnimationType.Instant;
		}
		else
		{
			unequipType = gameEquipAnimationType.Default;
		}
		SendEquipmentSystemWeaponManipulationRequest( scriptInterface, EquipmentManipulationAction.UnequipConsumable, unequipType );
	}

	protected function OnForcedExit( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		var blackboardSystem : BlackboardSystem;
		var blackboard : IBlackboard;
		stateContext.SetPermanentBoolParameter( 'UninterruptableHealing', false, true );
		SetLeftHandAnimationAnimFeature( scriptInterface, false );
		ClearItemIDWrapperPermanentParameter( stateContext, 'consumable' );
		ChangeConsumableAnimFeature( stateContext, scriptInterface, false );
		SetItemInLeftHand( scriptInterface, false );
		blackboardSystem = scriptInterface.GetBlackboardSystem();
		blackboard = blackboardSystem.Get( GetAllBlackboardDefs().UI_QuickSlotsData );
		blackboard.SetBool( GetAllBlackboardDefs().UI_QuickSlotsData.dpadHintRefresh, true );
		blackboard.SignalBool( GetAllBlackboardDefs().UI_QuickSlotsData.dpadHintRefresh );
		SendEquipmentSystemWeaponManipulationRequest( scriptInterface, EquipmentManipulationAction.UnequipConsumable, gameEquipAnimationType.Instant );
	}

}

