class hudTurretController extends inkHUDGameController
{
	private editable var healthStatus : inkTextRef;
	private editable var m_MessageText : inkTextRef;
	private editable var m_yawCounter : inkTextRef;
	private editable var m_pitchCounter : inkTextRef;
	private editable var m_pitch : inkCanvasRef;
	private editable var m_yaw : inkCanvasRef;
	private editable var m_turretIcon : inkCanvasRef;
	private var pitch_min : Float;
	default pitch_min = -360;
	private var pitch_max : Float;
	default pitch_max = 360;
	private var yaw_min : Float;
	default yaw_min = -640;
	private var yaw_max : Float;
	default yaw_max = 640;
	private editable var m_ZoomNumber : inkTextRef;
	private editable var m_DistanceNumber : inkTextRef;
	private editable var m_DistanceImageRuler : inkImageRef;
	private editable var m_ZoomMoveBracketL : inkImageRef;
	private editable var m_ZoomMoveBracketR : inkImageRef;
	private var m_bbPlayerStats : weak< IBlackboard >;
	private var m_bbPlayerEventId : CallbackHandle;
	private var m_currentHealth : Int32;
	private var m_previousHealth : Int32;
	private var m_maximumHealth : Int32;
	private var m_playerObject : weak< GameObject >;
	private var m_playerPuppet : weak< GameObject >;
	private var m_controlledObjectRef : weak< GameObject >;
	private var m_gameInstance : GameInstance;
	private var m_animationProxy : inkAnimProxy;
	private var m_psmBlackboard : weak< IBlackboard >;
	private var m_PSM_BBID : CallbackHandle;
	private var zoomDownAnim : inkAnimProxy;
	private var zoomUpAnim : inkAnimProxy;
	private var argZoomBuffered : Float;
	private var m_overclockListener : OverclockHudListener;
	private var m_isOverclockActive : Bool;

	protected event OnInitialize()
	{
		var delayInitialize : DelayedHUDInitializeEvent;
		var player : GameObject;
		player = GetPlayerControlledObject();
		delayInitialize = new DelayedHUDInitializeEvent;
		GameInstance.GetDelaySystem( player.GetGame() ).DelayEvent( player, delayInitialize, 0.1 );
		player.RegisterInputListener( this );
		UpdateRulers();
		m_overclockListener = new OverclockHudListener;
		m_overclockListener.BindHudController( this );
		GameInstance.GetStatusEffectSystem( player.GetGame() ).RegisterListener( player.GetEntityID(), m_overclockListener );
		m_isOverclockActive = QuickHackableHelper.IsOverclockedStateActive( player );
		OnOverclockHudEvent( NULL );
	}

	protected event OnUninitialize()
	{
		TakeOverControlSystem.CreateInputHint( GetPlayerControlledObject().GetGame(), false );
		SecurityTurret.CreateInputHint( GetPlayerControlledObject().GetGame(), false );
		m_overclockListener = NULL;
	}

	protected event OnPlayerAttach( playerPuppet : GameObject )
	{
		var optionIntro : inkAnimOptions;
		m_bbPlayerStats = GetBlackboardSystem().Get( GetAllBlackboardDefs().UI_PlayerBioMonitor );
		m_bbPlayerEventId = m_bbPlayerStats.RegisterListenerVariant( GetAllBlackboardDefs().UI_PlayerBioMonitor.PlayerStatsInfo, this, 'OnStatsChanged' );
		m_playerObject = ( ( GameObject )( playerPuppet ) );
		m_playerPuppet = playerPuppet;
		m_gameInstance = GetPlayerControlledObject().GetGame();
		PlayLibraryAnimation( 'Malfunction' );
		optionIntro.executionDelay = 1.5;
		PlaySound( 'MiniGame', 'AccessGranted' );
		PlayLibraryAnimation( 'intro', optionIntro );
		PlayAnim( 'intro2', 'OnIntroComplete' );
		optionIntro.executionDelay = 2.0;
		PlayLibraryAnimation( 'Malfunction_off', optionIntro );
		PlayAnim( 'Malfunction_timed', 'OnMalfunction' );
		UpdateJohnnyThemeOverride( true );
		m_psmBlackboard = GetPSMBlackboard( playerPuppet );
		if( m_psmBlackboard )
		{
			m_PSM_BBID = m_psmBlackboard.RegisterDelayedListenerFloat( GetAllBlackboardDefs().PlayerStateMachine.ZoomLevel, this, 'OnScannerZoom' );
		}
	}

	protected event OnPlayerDetach( playerPuppet : GameObject )
	{
		if( m_bbPlayerStats )
		{
			m_bbPlayerStats.UnregisterListenerVariant( GetAllBlackboardDefs().UI_PlayerBioMonitor.PlayerStatsInfo, m_bbPlayerEventId );
		}
		PlayLibraryAnimation( 'outro' );
		UpdateJohnnyThemeOverride( false );
	}

	protected event OnAction( action : ListenerAction, consumer : ListenerActionConsumer )
	{
		UpdateRulers();
	}

	protected event OnMalfunction( anim : inkAnimProxy )
	{
		var optionMalfunction : inkAnimOptions;
		var optionIntro : inkAnimOptions;
		if( ( GameInstance.GetQuestsSystem( m_gameInstance ).GetFact( 'q104_turret_broken' ) == 1 ) && ( GameInstance.GetQuestsSystem( m_gameInstance ).GetFact( 'q104_turret_fixed' ) == 0 ) )
		{
			PlaySound( 'MiniGame', 'AccessDenied' );
			inkTextRef.SetText( m_MessageText, "LocKey#11338" );
			optionMalfunction.fromMarker = 'intro';
			optionMalfunction.toMarker = 'loop_start';
			PlayAnim( 'Malfunction', 'OnMalfunctionLoop', optionMalfunction );
			optionIntro.executionDelay = 28.0;
			PlayLibraryAnimation( 'Malfunction_off', optionIntro );
		}
	}

	protected event OnMalfunctionLoop( anim : inkAnimProxy )
	{
		var optionMalfunctionLoop : inkAnimOptions;
		optionMalfunctionLoop.loopInfinite = false;
		optionMalfunctionLoop.loopType = inkanimLoopType.Cycle;
		optionMalfunctionLoop.loopCounter = 65;
		optionMalfunctionLoop.fromMarker = 'loop_start';
		optionMalfunctionLoop.toMarker = 'loop_end';
		PlayAnim( 'Malfunction', 'OnMalfunctionLoopEnd', optionMalfunctionLoop );
	}

	protected event OnMalfunctionLoopEnd( anim : inkAnimProxy )
	{
		var optionMalfunctionLoopEnd : inkAnimOptions;
		optionMalfunctionLoopEnd.fromMarker = 'loop_end';
		PlayAnim( 'Malfunction', '', optionMalfunctionLoopEnd );
	}

	protected event OnIntroComplete( anim : inkAnimProxy )
	{
		GameInstance.GetAudioSystem( GetPlayerControlledObject().GetGame() ).Play( 'ui_main_menu_cc_loading' );
	}

	protected event OnStatsChanged( value : Variant )
	{
		var incomingData : PlayerBioMonitor;
		incomingData = ( ( PlayerBioMonitor )value );
		m_previousHealth = m_currentHealth;
		m_maximumHealth = incomingData.maximumHealth;
		m_currentHealth = CeilF( GameInstance.GetStatPoolsSystem( m_playerObject.GetGame() ).GetStatPoolValue( GetPlayer( m_playerObject.GetGame() ).GetEntityID(), gamedataStatPoolType.Health, false ) );
		m_currentHealth = Clamp( m_currentHealth, 0, m_maximumHealth );
		inkTextRef.SetText( healthStatus, ( IntToString( RoundF( ( ( Float )( m_currentHealth ) ) ) ) + "/" ) + IntToString( RoundF( ( ( Float )( m_maximumHealth ) ) ) ) );
	}

	protected event OnOverclockHudEvent( overclockEvent : OverclockHudEvent )
	{
		if( overclockEvent )
		{
			m_isOverclockActive = overclockEvent.m_activated;
		}
		inkCanvasRef.SetVisible( m_turretIcon, !( m_isOverclockActive ) );
		UpdateRequired();
	}

	protected event OnDelayedHUDInitializeEvent( evt : DelayedHUDInitializeEvent )
	{
		TakeOverControlSystem.CreateInputHint( GetPlayerControlledObject().GetGame(), true );
		SecurityTurret.CreateInputHint( GetPlayerControlledObject().GetGame(), true );
	}

	protected event OnScannerZoom( argZoom : Float )
	{
		if( ( argZoom * 2.0 ) > 2.0 )
		{
			inkTextRef.SetText( m_ZoomNumber, FloatToStringPrec( MaxF( 1.0, argZoom * 2.0 ), 1 ) + "x" );
		}
		else
		{
			inkTextRef.SetText( m_ZoomNumber, FloatToStringPrec( MaxF( 1.0, ( argZoom * 2.0 ) - 1.0 ), 1 ) + "x" );
		}
		inkImageRef.SetMargin( m_ZoomMoveBracketL, inkMargin( 0.0, 0.0, 560.0 - ( argZoom * 60.0 ), 0.0 ) );
		inkImageRef.SetMargin( m_ZoomMoveBracketR, inkMargin( 560.0 - ( argZoom * 60.0 ), 0.0, 0.0, 0.0 ) );
		if( argZoom < argZoomBuffered )
		{
			if( ( !( zoomDownAnim ) || !( zoomDownAnim.IsPlaying() ) ) && ( !( zoomUpAnim ) || !( zoomUpAnim.IsPlaying() ) ) )
			{
				zoomDownAnim = PlayLibraryAnimation( 'zoomDown' );
			}
		}
		if( argZoom > argZoomBuffered )
		{
			if( ( !( zoomDownAnim ) || !( zoomDownAnim.IsPlaying() ) ) && ( !( zoomUpAnim ) || !( zoomUpAnim.IsPlaying() ) ) )
			{
				zoomUpAnim = PlayLibraryAnimation( 'zoomUp' );
			}
		}
		argZoomBuffered = argZoom;
	}

	public function PlayAnim( animName : CName, optional callBack : CName, optional animOptions : inkAnimOptions )
	{
		if( m_animationProxy && m_animationProxy.IsPlaying() )
		{
			m_animationProxy.Stop( true );
		}
		m_animationProxy = PlayLibraryAnimation( animName, animOptions );
		if( callBack != '' )
		{
			m_animationProxy.RegisterToCallback( inkanimEventType.OnFinish, this, callBack );
		}
	}

	private function UpdateJohnnyThemeOverride( value : Bool )
	{
		var controlledPuppet : weak< gamePuppetBase >;
		var uiSystem : UISystem;
		controlledPuppet = ( ( gamePuppetBase )( GetPlayer( m_gameInstance ) ) );
		if( controlledPuppet && controlledPuppet.IsJohnnyReplacer() )
		{
			uiSystem = GameInstance.GetUISystem( m_gameInstance );
			if( uiSystem )
			{
				if( value )
				{
					uiSystem.SetGlobalThemeOverride( 'Johnny' );
				}
				else
				{
					uiSystem.ClearGlobalThemeOverride();
				}
			}
		}
	}

	private function UpdateRulers()
	{
		var data : CameraRotationData;
		var euAngles : EulerAngles;
		var pitchPt : Float;
		var yawPt : Float;
		var m_yawMargin : Float;
		var m_pitchMargin : Float;
		m_controlledObjectRef = m_playerObject.GetTakeOverControlSystem().GetControlledObject();
		data = ( ( SensorDevice )( m_controlledObjectRef ) ).GetRotationData();
		euAngles = ( ( SensorDevice )( m_controlledObjectRef ) ).GetRotationFromSlotRotation();
		if( data.m_maxPitch == 0.0 )
		{
			data.m_maxPitch = 360.0;
		}
		pitchPt = euAngles.Pitch / AbsF( data.m_maxPitch - data.m_minPitch );
		m_pitchMargin = AbsF( pitch_max - pitch_min ) * pitchPt;
		inkCanvasRef.SetMargin( m_pitch, 0.0, m_pitchMargin, 0.0, 0.0 );
		if( data.m_maxYaw == 0.0 )
		{
			data.m_maxYaw = 360.0;
		}
		yawPt = -( euAngles.Yaw ) / AbsF( data.m_maxYaw - data.m_minYaw );
		m_yawMargin = AbsF( yaw_max - yaw_min ) * yawPt;
		inkCanvasRef.SetMargin( m_yaw, m_yawMargin, 0.0, 0.0, 0.0 );
		inkTextRef.SetText( m_yawCounter, ( ( String )( RoundF( -( euAngles.Yaw ) ) ) ) );
		inkTextRef.SetText( m_pitchCounter, ( ( String )( RoundF( -( euAngles.Pitch ) ) ) ) );
	}

	public function GetUIActiveWeaponBlackboard() : IBlackboard
	{
		return GetBlackboardSystem().Get( GetAllBlackboardDefs().UI_ActiveWeaponData );
	}

}

class DelayedHUDInitializeEvent extends Event
{
}

