import class PanzerHUDGameController extends inkHUDGameController
{
	private var m_vehicle : weak< VehicleObject >;
	private var m_vehiclePS : VehicleComponentPS;
	private editable var m_Date : inkTextRef;
	private editable var m_Timer : inkTextRef;
	private editable var healthStatus : inkTextRef;
	private editable var healthBar : inkWidgetRef;
	private var m_rightStickX : Float;
	private var m_rightStickY : Float;
	private editable var m_LeanAngleValue : inkCanvasRef;
	private editable var m_CoriRotation : inkCanvasRef;
	private editable var m_CompassRotation : inkCanvasRef;
	private editable var m_Cori_S : inkCanvasRef;
	private editable var m_Cori_M : inkCanvasRef;
	private editable var m_trimmerArrow : inkImageRef;
	private editable var m_SpeedValue : inkTextRef;
	private editable var m_RPMValue : inkTextRef;
	private var m_scanBlackboard : weak< IBlackboard >;
	private var m_psmBlackboard : weak< IBlackboard >;
	private var m_PSM_BBID : CallbackHandle;
	private var m_root : weak< inkCompoundWidget >;
	private var m_currentZoom : Float;
	private var currentTime : GameTime;
	private var m_vehicleBlackboard : weak< IBlackboard >;
	private var m_activeVehicleUIBlackboard : weak< IBlackboard >;
	private var m_vehicleBBStateConectionId : CallbackHandle;
	private var m_speedBBConnectionId : CallbackHandle;
	private var m_gearBBConnectionId : CallbackHandle;
	private var m_tppBBConnectionId : CallbackHandle;
	private var m_rpmValueBBConnectionId : CallbackHandle;
	private var m_leanAngleBBConnectionId : CallbackHandle;
	private var m_playerStateBBConnectionId : CallbackHandle;
	private var m_isTargetingFriendlyConnectionId : CallbackHandle;
	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_quickhacksMemoryPercent : Float;
	private var m_playerObject : weak< GameObject >;
	private var m_weaponBlackboard : weak< IBlackboard >;
	private var m_weaponParamsListenerId : CallbackHandle;
	private var m_targetIndicators : array< TargetIndicatorEntry >;
	private editable var m_targetHolder : inkCompoundRef;
	private editable var m_targetWidgetLibraryName : CName;
	default m_targetWidgetLibraryName = 'Marker';
	private editable var m_targetWidgetPoolSize : Int32;
	default m_targetWidgetPoolSize = 10;

	protected event OnInitialize()
	{
		var ownerObject : GameObject;
		var playerPuppet : weak< GameObject >;
		var bbSys : BlackboardSystem;
		var playerControlledObject : GameObject;
		ownerObject = ( ( GameObject )( GetOwnerEntity() ) );
		playerPuppet = ( ( PlayerPuppet )( GetOwnerEntity() ) );
		bbSys = GameInstance.GetBlackboardSystem( playerPuppet.GetGame() );
		m_psmBlackboard = GetPSMBlackboard( playerPuppet );
		m_playerObject = ( ( GameObject )( playerPuppet ) );
		playerControlledObject = GetPlayerControlledObject();
		playerControlledObject.RegisterInputListener( this, 'right_stick_x' );
		playerControlledObject.RegisterInputListener( this, 'right_stick_y' );
		m_scanBlackboard = bbSys.Get( GetAllBlackboardDefs().UI_Scanner );
		m_root = ( ( inkCompoundWidget )( GetRootWidget() ) );
		m_root.SetVisible( false );
		m_vehicle = GetMountedVehicle( playerPuppet );
		m_vehiclePS = m_vehicle.GetVehiclePS();
		m_vehicleBlackboard = m_vehicle.GetBlackboard();
		m_activeVehicleUIBlackboard = bbSys.Get( GetAllBlackboardDefs().UI_ActiveVehicleData );
		m_bbPlayerStats = GetBlackboardSystem().Get( GetAllBlackboardDefs().UI_PlayerBioMonitor );
		m_bbPlayerEventId = m_bbPlayerStats.RegisterListenerVariant( GetAllBlackboardDefs().UI_PlayerBioMonitor.PlayerStatsInfo, this, 'OnStatsChanged' );
		if( m_psmBlackboard )
		{
			m_PSM_BBID = m_psmBlackboard.RegisterDelayedListenerFloat( GetAllBlackboardDefs().PlayerStateMachine.ZoomLevel, this, 'OnZoomChange' );
			m_playerStateBBConnectionId = m_psmBlackboard.RegisterListenerInt( GetAllBlackboardDefs().PlayerStateMachine.Vehicle, this, 'OnPlayerVehicleStateChange', true );
		}
		if( m_vehicleBlackboard )
		{
			m_vehicleBBStateConectionId = m_vehicleBlackboard.RegisterListenerInt( GetAllBlackboardDefs().Vehicle.VehicleState, this, 'OnVehicleStateChanged' );
			m_speedBBConnectionId = m_vehicleBlackboard.RegisterListenerFloat( GetAllBlackboardDefs().Vehicle.SpeedValue, this, 'OnSpeedValueChanged' );
			m_gearBBConnectionId = m_vehicleBlackboard.RegisterListenerInt( GetAllBlackboardDefs().Vehicle.GearValue, this, 'OnGearValueChanged' );
			m_rpmValueBBConnectionId = m_vehicleBlackboard.RegisterListenerFloat( GetAllBlackboardDefs().Vehicle.RPMValue, this, 'OnRpmValueChanged' );
			m_leanAngleBBConnectionId = m_vehicleBlackboard.RegisterListenerFloat( GetAllBlackboardDefs().Vehicle.BikeTilt, this, 'OnLeanAngleChanged' );
			m_isTargetingFriendlyConnectionId = m_vehicleBlackboard.RegisterListenerBool( GetAllBlackboardDefs().Vehicle.IsTargetingFriendly, this, 'OnIsTargetingFriendly' );
		}
		currentTime = GameInstance.GetTimeSystem( ownerObject.GetGame() ).GetGameTime();
		inkTextRef.SetText( m_Timer, ( ( ( ( ( String )( GameTime.Hours( currentTime ) ) ) + ":" ) + ( ( String )( GameTime.Minutes( currentTime ) ) ) ) + ":" ) + ( ( String )( GameTime.Seconds( currentTime ) ) ) );
		inkTextRef.SetText( m_Date, "05-13-2077" );
		SpawnTargetIndicators();
		m_weaponBlackboard = bbSys.Get( GetAllBlackboardDefs().UI_ActiveWeaponData );
		if( m_weaponBlackboard )
		{
			m_weaponParamsListenerId = m_weaponBlackboard.RegisterDelayedListenerVariant( GetAllBlackboardDefs().UI_ActiveWeaponData.SmartGunParams, this, 'OnSmartGunParams' );
		}
	}

	protected event OnUninitialize()
	{
		if( m_vehicleBlackboard )
		{
			m_vehicleBlackboard.UnregisterListenerInt( GetAllBlackboardDefs().Vehicle.VehicleState, m_vehicleBBStateConectionId );
			m_vehicleBlackboard.UnregisterListenerFloat( GetAllBlackboardDefs().Vehicle.SpeedValue, m_speedBBConnectionId );
			m_vehicleBlackboard.UnregisterListenerInt( GetAllBlackboardDefs().Vehicle.GearValue, m_gearBBConnectionId );
			m_vehicleBlackboard.UnregisterListenerFloat( GetAllBlackboardDefs().Vehicle.RPMValue, m_rpmValueBBConnectionId );
			m_vehicleBlackboard.UnregisterListenerFloat( GetAllBlackboardDefs().Vehicle.BikeTilt, m_leanAngleBBConnectionId );
			m_vehicleBlackboard.UnregisterDelayedListener( GetAllBlackboardDefs().Vehicle.IsTargetingFriendly, m_isTargetingFriendlyConnectionId );
			m_activeVehicleUIBlackboard.UnregisterListenerVariant( GetAllBlackboardDefs().UI_ActiveVehicleData.VehPlayerStateData, m_playerStateBBConnectionId );
		}
		if( m_bbPlayerStats )
		{
			m_bbPlayerStats.UnregisterListenerVariant( GetAllBlackboardDefs().UI_PlayerBioMonitor.PlayerStatsInfo, m_bbPlayerEventId );
		}
		if( m_weaponBlackboard )
		{
			m_weaponBlackboard.UnregisterDelayedListener( GetAllBlackboardDefs().UI_ActiveWeaponData.SmartGunParams, m_weaponParamsListenerId );
		}
		if( m_psmBlackboard )
		{
			m_psmBlackboard.UnregisterDelayedListener( GetAllBlackboardDefs().PlayerStateMachine.ZoomLevel, m_PSM_BBID );
		}
		GetPlayerControlledObject().UnregisterInputListener( this, 'right_stick_x' );
		GetPlayerControlledObject().UnregisterInputListener( this, 'right_stick_y' );
	}

	protected event OnVehicleStateChanged( state : Int32 )
	{
		var vehicleState : vehicleEState;
		vehicleState = ( ( vehicleEState )( state ) );
		if( m_vehiclePS.GetIsUiQuestModified() )
		{
			return false;
		}
		if( vehicleState == vehicleEState.On )
		{
			EvaluateUIState();
		}
		if( vehicleState == vehicleEState.Default )
		{
			TurnOff();
		}
		if( vehicleState == vehicleEState.Disabled )
		{
			TurnOff();
		}
		if( vehicleState == vehicleEState.Destroyed )
		{
			TurnOff();
		}
	}

	protected event OnPlayerVehicleStateChange( value : Int32 )
	{
		EvaluateUIState();
	}

	private function EvaluateUIState()
	{
		var playerState : gamePSMVehicle;
		var vehicleState : vehicleEState;
		playerState = ( ( gamePSMVehicle )( m_psmBlackboard.GetInt( GetAllBlackboardDefs().PlayerStateMachine.Vehicle ) ) );
		vehicleState = ( ( vehicleEState )( m_vehicleBlackboard.GetInt( GetAllBlackboardDefs().Vehicle.VehicleState ) ) );
		if( playerState == gamePSMVehicle.Driving && vehicleState == vehicleEState.On )
		{
			if( m_vehiclePS.GetIsUiQuestModified() )
			{
				if( m_vehiclePS.GetUiQuestState() )
				{
					TurnOn();
				}
				return;
			}
			TurnOn();
		}
	}

	private function TurnOn()
	{
		PlayLibraryAnimation( 'intro' );
		TogglePanzerSpecificFX( true );
		m_root.SetVisible( true );
	}

	private function TurnOff()
	{
		TogglePanzerSpecificFX( false );
		m_root.SetVisible( false );
	}

	protected event OnForwardVehicleQuestEnableUIEvent( evt : ForwardVehicleQuestEnableUIEvent )
	{
		switch( evt.mode )
		{
			case vehicleQuestUIEnable.Gameplay:
				TurnOn();
			break;
			case vehicleQuestUIEnable.ForceEnable:
				TurnOn();
			break;
			case vehicleQuestUIEnable.ForceDisable:
				TurnOff();
			break;
		}
	}

	protected event OnAction( action : ListenerAction, consumer : ListenerActionConsumer )
	{
		if( ListenerAction.GetType( action ) == gameinputActionType.AXIS_CHANGE )
		{
			if( ListenerAction.GetName( action ) == 'right_stick_x' )
			{
				m_rightStickX = ListenerAction.GetValue( action );
			}
			else if( ListenerAction.GetName( action ) == 'right_stick_y' )
			{
				m_rightStickY = ListenerAction.GetValue( action );
			}
		}
		inkCanvasRef.SetTranslation( m_Cori_S, m_rightStickX * 100.0, m_rightStickY * 61.0 );
		inkCanvasRef.SetTranslation( m_Cori_M, m_rightStickX * 50.0, m_rightStickY * 30.5 );
		inkImageRef.SetTranslation( m_trimmerArrow, m_rightStickX * 100.0, 0.0 );
	}

	private function TogglePanzerSpecificFX( toggle : Bool )
	{
		if( m_vehicle == ( ( TankObject )( m_vehicle ) ) )
		{
			if( toggle )
			{
				GameObjectEffectHelper.StartEffectEvent( m_vehicle, 'terrain_scan', false );
			}
			else
			{
				GameObjectEffectHelper.BreakEffectLoopEvent( m_vehicle, 'terrain_scan' );
			}
		}
	}

	protected event OnPlayerAttach( playerPuppet : GameObject ) {}

	protected event OnPlayerDetach( playerPuppet : GameObject ) {}

	protected event OnZoomChange( evt : Float )
	{
		m_currentZoom = evt;
	}

	protected event OnRpmMaxChanged( rpmMax : Float )
	{
		inkTextRef.SetText( m_RPMValue, FloatToString( rpmMax ) );
	}

	protected event OnSpeedValueChanged( speedValue : Float )
	{
		var value : String;
		value = FloatToStringPrec( AbsF( speedValue ), 0 );
		while( StrLen( value ) < 3 )
		{
			value = "0" + value;
		}
		inkTextRef.SetText( m_SpeedValue, value );
	}

	protected event OnGearValueChanged( gearValue : Int32 )
	{
		if( gearValue == ( ( Int32 )( 0 ) ) )
		{
		}
		else
		{
		}
	}

	protected event OnRpmValueChanged( rpmValue : Float )
	{
		inkTextRef.SetText( m_RPMValue, FloatToString( rpmValue ) );
	}

	protected event OnLeanAngleChanged( leanAngle : Float )
	{
		var ownerObject : GameObject;
		var position : Vector4;
		var forward : Vector4;
		var rotation : Float;
		var coriSmooth : Float;
		coriSmooth = 0.15000001;
		ownerObject = ( ( GameObject )( GetOwnerEntity() ) );
		GameInstance.GetTargetingSystem( ownerObject.GetGame() ).GetDefaultCrosshairData( GameInstance.GetPlayerSystem( ownerObject.GetGame() ).GetLocalPlayerMainGameObject(), position, forward );
		rotation = Rad2Deg( AtanF( forward.X, forward.Y ) ) - 180.0;
		inkCanvasRef.SetRotation( m_CompassRotation, -( rotation ) );
		inkCanvasRef.SetRotation( m_LeanAngleValue, rotation );
		inkCanvasRef.SetRotation( m_CoriRotation, -( leanAngle ) * coriSmooth );
		inkCanvasRef.SetRotation( m_LeanAngleValue, leanAngle );
	}

	protected event OnCameraModeChanged( mode : Bool ) {}

	protected event OnStatsChanged( value : Variant )
	{
		var incomingData : PlayerBioMonitor;
		var newX : Int32;
		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 );
		newX = 670 - ( 670 - ( m_currentHealth * 67 ) );
		inkWidgetRef.SetSize( healthBar, Vector2( ( ( Float )( newX ) ), 100.0 ) );
		inkTextRef.SetText( healthStatus, ( IntToString( RoundF( ( ( Float )( m_currentHealth ) ) ) ) + "/" ) + IntToString( RoundF( ( ( Float )( m_maximumHealth ) ) ) ) );
	}

	protected event OnIsTargetingFriendly( isTargetingFriendly : Bool )
	{
		if( isTargetingFriendly )
		{
			PlayLibraryAnimation( 'friendlyHover' );
		}
		else
		{
			PlayLibraryAnimation( 'friendlyHoverOut' );
		}
	}

	private function SpawnTargetIndicators()
	{
		var newTarget : weak< inkWidget >;
		var newEntry : TargetIndicatorEntry;
		var i : Int32;
		for( i = 0; i < m_targetWidgetPoolSize; i += 1 )
		{
			newTarget = SpawnFromLocal( inkCompoundRef.Get( m_targetHolder ), m_targetWidgetLibraryName );
			newTarget.SetVisible( false );
			newEntry.indicator = newTarget;
			m_targetIndicators.PushBack( newEntry );
		}
	}

	private function EnableTargetIndicator( indicatorEntry : TargetIndicatorEntry, const targetData : ref< smartGunUITargetParameters > )
	{
		var indicator : weak< inkWidget >;
		var controller : weak< PanzerSmartWeaponTargetController >;
		indicator = indicatorEntry.indicator;
		indicator.SetVisible( true );
		indicator.SetMargin( inkMargin( targetData.pos.X * 0.5, targetData.pos.Y * 0.5, 0.0, 0.0 ) );
		controller = ( ( PanzerSmartWeaponTargetController )( indicator.GetController() ) );
		controller.SetData( targetData );
	}

	private function DisableTargetIndicator( indicatorEntry : TargetIndicatorEntry )
	{
		var indicator : weak< inkWidget >;
		var controller : weak< PanzerSmartWeaponTargetController >;
		indicator = indicatorEntry.indicator;
		indicator.SetVisible( false );
		controller = ( ( PanzerSmartWeaponTargetController )( indicator.GetController() ) );
		controller.StopAnimation();
	}

	protected event OnSmartGunParams( argParams : Variant )
	{
		var smartData : smartGunUIParameters;
		var targetList : array< smartGunUITargetParameters >;
		var servicedTargets : array< Int32 >;
		var freeIndicators : array< TargetIndicatorEntry >;
		var currIndicator : TargetIndicatorEntry;
		var currTargetData : smartGunUITargetParameters;
		var currTargetID : EntityID;
		var i, j, numTargets, numIndicators : Int32;
		smartData = ( ( smartGunUIParameters )argParams );
		targetList = smartData.targets;
		numTargets = targetList.Size();
		numIndicators = m_targetIndicators.Size();
		if( numTargets > numIndicators )
		{
			targetList.Resize( numIndicators );
			numTargets = numIndicators;
		}
		freeIndicators = m_targetIndicators;
		for( i = 0; i < numTargets; i += 1 )
		{
			currTargetData = targetList[ i ];
			currTargetID = currTargetData.entityID;
			for( j = 0; j < freeIndicators.Size(); j += 1 )
			{
				currIndicator = freeIndicators[ j ];
				if( currTargetID == currIndicator.targetID )
				{
					EnableTargetIndicator( currIndicator, currTargetData );
					servicedTargets.PushBack( i );
					freeIndicators.Remove( currIndicator );
					break;
				}
			}
		}
		for( i = 0; i < servicedTargets.Size(); i += 1 )
		{
			targetList.Erase( servicedTargets.PopBack() );
		}
		numTargets = targetList.Size();
		for( i = 0; ( i < numTargets ) && ( freeIndicators.Size() > 0 ); i += 1 )
		{
			EnableTargetIndicator( freeIndicators.PopBack(), targetList[ i ] );
		}
		for( i = 0; i < freeIndicators.Size(); i += 1 )
		{
			DisableTargetIndicator( freeIndicators[ i ] );
		}
	}

}

struct TargetIndicatorEntry
{
	var targetID : EntityID;
	var indicator : weak< inkWidget >;
}

class PanzerSmartWeaponTargetController extends inkLogicController
{
	private editable var m_distanceText : inkTextRef;
	private var m_lockingAnimationProxy : inkAnimProxy;

	protected event OnInitialize()
	{
		GetRootWidget().SetVisible( false );
	}

	public function SetData( const data : ref< smartGunUITargetParameters > )
	{
		var playbackOptions : inkAnimOptions;
		if( data.state == gamesmartGunTargetState.Locking )
		{
			GetRootWidget().SetVisible( true );
			if( !( m_lockingAnimationProxy ) )
			{
				playbackOptions.dependsOnTimeDilation = true;
				m_lockingAnimationProxy = PlayLibraryAnimation( 'target', playbackOptions );
			}
		}
		else
		{
			GetRootWidget().SetVisible( data.state == gamesmartGunTargetState.Locked || data.state == gamesmartGunTargetState.Unlocking );
			StopAnimation();
		}
		inkTextRef.SetText( m_distanceText, ( "Dis.\n" + SpaceFill( IntToString( RoundMath( data.distance ) ), 2, ESpaceFillMode.JustifyRight, "0" ) ) + " m" );
	}

	public function StopAnimation()
	{
		if( m_lockingAnimationProxy )
		{
			m_lockingAnimationProxy.GotoEndAndStop();
			m_lockingAnimationProxy = NULL;
		}
	}

}

