class StaminabarWidgetGameController extends inkHUDGameController
{
	private editable var m_staminaControllerRef : inkWidgetRef;
	private editable var m_staminaPercTextPath : inkTextRef;
	private editable var m_staminaStatusTextPath : inkTextRef;
	private var m_bbPSceneTierEventId : CallbackHandle;
	private var m_bbPStaminaPSMEventId : CallbackHandle;
	private var m_bbAreaZoneEventId : CallbackHandle;
	private var m_combatModeListener : CallbackHandle;
	private var m_staminaController : weak< NameplateBarLogicController >;
	private var m_RootWidget : weak< inkWidget >;
	private var m_currentBarValue : Float;
	default m_currentBarValue = 100.f;
	private var m_currentStatPool : gamedataStatPoolType;
	private var m_sceneTier : GameplayTier;
	default m_sceneTier = GameplayTier.Tier1_FullGameplay;
	private var m_staminaState : gamePSMStamina;
	default m_staminaState = gamePSMStamina.Rested;
	private var m_zoneState : gamePSMZones;
	private var m_staminaPoolListener : StaminaPoolListener;
	private var m_statsSystem : StatsSystem;
	private var m_forceHidden : Bool;
	default m_forceHidden = false;
	private var m_staminaRatioEnterCondition : Float;
	private var m_pulse : PulseAnimation;
	private var m_playerPuppet : weak< GameObject >;

	protected event OnInitialize()
	{
		m_RootWidget = GetRootWidget();
		m_RootWidget.SetVisible( false );
		m_staminaController = ( ( NameplateBarLogicController )( inkWidgetRef.GetController( m_staminaControllerRef ) ) );
		m_currentStatPool = gamedataStatPoolType.Stamina;
		m_staminaPoolListener = new StaminaPoolListener;
		m_staminaPoolListener.BindStaminaBar( this );
		m_staminaRatioEnterCondition = TDB.GetFloat( T"playerStateMachineStamina.exhausted.staminaRatioEnterCondition", 0.0 );
		CreateAnimations();
		EvaluateStaminaBarVisibility();
	}

	protected event OnUninitialize()
	{
		if( m_staminaPoolListener )
		{
			m_staminaPoolListener = NULL;
		}
	}

	protected event OnPlayerAttach( playerGameObject : GameObject )
	{
		m_playerPuppet = playerGameObject;
		RegisterPSMListeners( playerGameObject );
		m_statsSystem = GameInstance.GetStatsSystem( playerGameObject.GetGame() );
		m_staminaPoolListener = new StaminaPoolListener;
		m_staminaPoolListener.BindStaminaBar( this );
		GameInstance.GetStatPoolsSystem( playerGameObject.GetGame() ).RequestRegisteringListener( playerGameObject.GetEntityID(), gamedataStatPoolType.Stamina, m_staminaPoolListener );
		playerGameObject.RegisterInputListener( this, 'HolsterWeapon' );
	}

	protected event OnPlayerDetach( playerGameObject : GameObject )
	{
		if( m_staminaPoolListener )
		{
			GameInstance.GetStatPoolsSystem( playerGameObject.GetGame() ).RequestUnregisteringListener( playerGameObject.GetEntityID(), gamedataStatPoolType.Stamina, m_staminaPoolListener );
			m_staminaPoolListener = NULL;
		}
		UnregisterPSMListeners( playerGameObject );
		playerGameObject.UnregisterInputListener( this );
	}

	protected function RegisterPSMListeners( playerPuppet : GameObject )
	{
		var playerStateMachineBlackboard : IBlackboard;
		var playerSMDef : PlayerStateMachineDef;
		playerSMDef = GetAllBlackboardDefs().PlayerStateMachine;
		if( playerPuppet.IsControlledByLocalPeer() )
		{
			playerStateMachineBlackboard = GetPSMBlackboard( playerPuppet );
			if( playerStateMachineBlackboard )
			{
				m_sceneTier = ( ( GameplayTier )( playerStateMachineBlackboard.GetInt( playerSMDef.SceneTier ) ) );
				m_staminaState = ( ( gamePSMStamina )( playerStateMachineBlackboard.GetInt( playerSMDef.Stamina ) ) );
				m_bbPSceneTierEventId = playerStateMachineBlackboard.RegisterListenerInt( playerSMDef.SceneTier, this, 'OnSceneTierChange' );
				m_bbPStaminaPSMEventId = playerStateMachineBlackboard.RegisterListenerInt( playerSMDef.Stamina, this, 'OnStaminaPSMChange' );
				m_bbAreaZoneEventId = playerStateMachineBlackboard.RegisterListenerInt( playerSMDef.Zones, this, 'OnZoneChange' );
				m_combatModeListener = playerStateMachineBlackboard.RegisterListenerInt( playerSMDef.Combat, this, 'OnCombatStateChanged' );
			}
		}
	}

	protected function UnregisterPSMListeners( playerPuppet : GameObject )
	{
		var playerStateMachineBlackboard : IBlackboard;
		var playerSMDef : PlayerStateMachineDef;
		playerSMDef = GetAllBlackboardDefs().PlayerStateMachine;
		if( playerPuppet.IsControlledByLocalPeer() )
		{
			playerStateMachineBlackboard = GetPSMBlackboard( playerPuppet );
			if( playerStateMachineBlackboard )
			{
				playerStateMachineBlackboard.UnregisterDelayedListener( playerSMDef.SceneTier, m_bbPSceneTierEventId );
				playerStateMachineBlackboard.UnregisterDelayedListener( playerSMDef.Stamina, m_bbPStaminaPSMEventId );
				playerStateMachineBlackboard.UnregisterDelayedListener( playerSMDef.Zones, m_bbAreaZoneEventId );
				playerStateMachineBlackboard.UnregisterDelayedListener( playerSMDef.Combat, m_combatModeListener );
			}
		}
	}

	public function UpdateStaminaValue( oldValue : Float, newValue : Float, percToPoints : Float, statPoolType : gamedataStatPoolType )
	{
		m_currentBarValue = newValue / 100.0;
		if( m_currentBarValue <= m_staminaRatioEnterCondition )
		{
			if( m_currentBarValue < 0.2 )
			{
				m_pulse.Configure( inkWidgetRef.Get( m_staminaControllerRef ), 1.0, 0.1, 0.2 );
			}
			else
			{
				m_pulse.Configure( inkWidgetRef.Get( m_staminaControllerRef ), 1.0, 0.1, m_currentBarValue );
			}
			m_pulse.Start( false );
		}
		else if( m_currentBarValue >= 0.85000002 )
		{
			m_pulse.Stop();
		}
		else
		{
			m_pulse.Stop();
		}
		m_staminaController.SetNameplateBarProgress( m_currentBarValue, false );
		inkTextRef.SetTextFromParts( m_staminaPercTextPath, IntToString( ( ( Int32 )( newValue ) ) ), "Common-Characters-Percetage", "" );
		UpdateStaminaLevelWarningFluffTexts( m_staminaState );
		EvaluateStaminaBarVisibility();
	}

	protected event OnFocusedCoolPerkActive( evt : FocusPerkTriggerd )
	{
		var playbackOptions : inkAnimOptions;
		if( evt.isActive )
		{
			PlayLibraryAnimation( 'perk_intro' );
			m_RootWidget.SetState( 'Focused' );
			m_RootWidget.SetOpacity( 1.0 );
		}
		else
		{
			m_RootWidget.SetState( 'Default' );
			playbackOptions.playReversed = true;
			PlayLibraryAnimation( 'perk_intro', playbackOptions );
		}
	}

	public function UpdateStaminaLevelWarningFluffTexts( staminaState : gamePSMStamina )
	{
		if( staminaState == gamePSMStamina.Exhausted )
		{
			inkTextRef.SetText( m_staminaStatusTextPath, "LocKey#40314" );
		}
		else
		{
			inkTextRef.SetText( m_staminaStatusTextPath, "LocKey#40311" );
		}
	}

	public function EvaluateStaminaBarVisibility()
	{
		switch( m_sceneTier )
		{
			case GameplayTier.Tier1_FullGameplay:
				m_RootWidget.SetVisible( true );
			break;
			default:
				m_RootWidget.SetVisible( false );
			break;
		}
		if( ShouldHide() )
		{
			m_RootWidget.SetVisible( false );
		}
		else
		{
			m_RootWidget.SetVisible( true );
		}
		m_RootWidget.SetOpacity( 1.04999995 - m_currentBarValue );
	}

	private function ShouldHide() : Bool
	{
		var isMaxBar : Bool;
		var isMultiplayer : Bool;
		var isInCombat : Bool;
		var isInHostileArea : Bool;
		if( m_forceHidden )
		{
			return true;
		}
		isMaxBar = m_currentBarValue >= 1.0;
		isMultiplayer = IsPlayingMultiplayer();
		isInCombat = IsInCombat();
		isInHostileArea = m_zoneState == gamePSMZones.Restricted || m_zoneState == gamePSMZones.Dangerous;
		return ( ( ( !( isInHostileArea ) && !( isInCombat ) ) && isMaxBar ) && !( isMultiplayer ) ) || ( m_sceneTier == GameplayTier.Tier4_FPPCinematic || m_sceneTier == GameplayTier.Tier5_Cinematic );
	}

	private function IsInCombat() : Bool
	{
		var player : PlayerPuppet;
		player = ( ( PlayerPuppet )( GetOwnerEntity() ) );
		return player.IsInCombat();
	}

	protected event OnCombatStateChanged( value : Int32 )
	{
		EvaluateStaminaBarVisibility();
	}

	private function CreateAnimations()
	{
		m_pulse = new PulseAnimation;
	}

	protected event OnSceneTierChange( argTier : Int32 )
	{
		m_sceneTier = ( ( GameplayTier )( argTier ) );
		EvaluateStaminaBarVisibility();
	}

	protected event OnStaminaPSMChange( arg : Int32 )
	{
		m_staminaState = ( ( gamePSMStamina )( arg ) );
	}

	protected event OnZoneChange( arg : Int32 )
	{
		m_zoneState = ( ( gamePSMZones )( arg ) );
		EvaluateStaminaBarVisibility();
	}

	protected event OnForceHide()
	{
		EvaluateStaminaBarVisibility();
	}

	protected event OnForceTierVisibility( tierVisibility : Bool )
	{
		EvaluateStaminaBarVisibility();
	}

	protected event OnAction( action : ListenerAction, consumer : ListenerActionConsumer )
	{
		if( ListenerAction.GetName( action ) == 'HolsterWeapon' && ListenerAction.IsButtonJustPressed( action ) )
		{
			m_forceHidden = !( m_forceHidden );
		}
	}

	protected event OnReflexesMasterPerk3Triggerd( e : ReflexesMasterPerk3Triggerd )
	{
		if( !( FloatIsEqual( m_currentBarValue, 1.0 ) ) )
		{
			PlayLibraryAnimation( 'bonus_regen' );
		}
	}

}

class StaminaPoolListener extends ScriptStatPoolsListener
{
	private var m_staminaBar : weak< StaminabarWidgetGameController >;

	public function BindStaminaBar( bar : weak< StaminabarWidgetGameController > )
	{
		m_staminaBar = bar;
	}

	public export override function OnStatPoolValueChanged( oldValue : Float, newValue : Float, percToPoints : Float )
	{
		m_staminaBar.UpdateStaminaValue( oldValue, newValue, percToPoints, gamedataStatPoolType.Stamina );
	}

}

class ReflexesMasterPerk3Triggerd extends Event
{
}

class FocusPerkTriggerd extends Event
{
	var isActive : Bool;
}

