importonly struct RemoteControlDrivingUIData
{
	import var remoteControlledVehicle : weak< VehicleObject >;
	import var isDistanceDisconnect : Bool;
}

import class RemoteControlDrivingHUDGameController extends inkHUDGameController
{
	private editable var m_overlay : inkWidgetRef;
	private editable var m_vehicleManufacturer : inkImageRef;
	private editable var m_containerSignalStrength : inkWidgetRef;
	private editable var m_signalStrengthBarFill : inkWidgetRef;
	private var m_containerSignalStrengthIntroOutroAnimProxy : inkAnimProxy;
	private var m_weakSignalStrengthAnimProxy : inkAnimProxy;
	private var m_remoteControlledVehicleDataCallback : CallbackHandle;
	private var m_remoteControlledVehicleCameraChangedToTPPCallback : CallbackHandle;
	private var m_remoteControlledVehicle : weak< VehicleObject >;
	private var m_maxRemoteControlDrivingRange : Float;
	private var m_mappinID : NewMappinID;

	protected event OnInitialize()
	{
		m_maxRemoteControlDrivingRange = TweakDBInterface.GetFloat( T"player.vehicleQuickHacks.maxRange", 0.0 );
	}

	protected event OnUpdate( dT : Float )
	{
		var currentSignalStrength : Float;
		if( inkWidgetRef.IsVisible( m_containerSignalStrength ) && !( m_containerSignalStrengthIntroOutroAnimProxy.IsValid() ) )
		{
			currentSignalStrength = 1.0 - MinF( SqrtF( m_remoteControlledVehicle.GetDistanceToPlayerSquared() ) / m_maxRemoteControlDrivingRange, 1.0 );
			inkWidgetRef.SetScale( m_signalStrengthBarFill, Vector2( currentSignalStrength, 1.0 ) );
			if( currentSignalStrength > 0.25 )
			{
				if( m_weakSignalStrengthAnimProxy.IsValid() )
				{
					m_weakSignalStrengthAnimProxy.GotoStartAndStop();
					m_weakSignalStrengthAnimProxy = NULL;
				}
			}
			else
			{
				if( !( m_weakSignalStrengthAnimProxy.IsValid() ) )
				{
					m_weakSignalStrengthAnimProxy = PlayLibraryAnimation( 'signal_strength_blinking' );
				}
			}
		}
	}

	protected event OnPlayerAttach( player : GameObject )
	{
		m_remoteControlledVehicleCameraChangedToTPPCallback = GetPSMBlackboard( player ).RegisterListenerBool( GetAllBlackboardDefs().PlayerStateMachine.IsVehicleRemoteControlCameraTPP, this, 'OnPSMRemoteControlledVehicleCameraChangedToTPP' );
		m_remoteControlledVehicleDataCallback = GameInstance.GetBlackboardSystem( player.GetGame() ).Get( GetAllBlackboardDefs().UI_ActiveVehicleData ).RegisterListenerVariant( GetAllBlackboardDefs().UI_ActiveVehicleData.RemoteControlledVehicleData, this, 'OnRemoteControlledVehicleChanged', true );
	}

	protected event OnPlayerDetach( player : GameObject )
	{
		if( m_remoteControlledVehicleCameraChangedToTPPCallback )
		{
			GetPSMBlackboard( player ).UnregisterListenerBool( GetAllBlackboardDefs().PlayerStateMachine.IsVehicleRemoteControlCameraTPP, m_remoteControlledVehicleCameraChangedToTPPCallback );
		}
		if( m_remoteControlledVehicleDataCallback )
		{
			GameInstance.GetBlackboardSystem( player.GetGame() ).Get( GetAllBlackboardDefs().UI_ActiveVehicleData ).UnregisterListenerVariant( GetAllBlackboardDefs().UI_ActiveVehicleData.RemoteControlledVehicleData, m_remoteControlledVehicleDataCallback );
		}
	}

	protected event OnPSMRemoteControlledVehicleCameraChangedToTPP( value : Bool )
	{
		GameInstance.GetMappinSystem( GetPlayerControlledObject().GetGame() ).SetMappinActive( m_mappinID, !( value ) );
	}

	protected event OnRemoteControlledVehicleChanged( value : Variant )
	{
		var data : RemoteControlDrivingUIData;
		var options : inkAnimOptions;
		var progression : Float;
		var record : Vehicle_Record;
		var player : weak< GameObject >;
		var isQuestRemoteControlDriving : Bool;
		data = ( ( RemoteControlDrivingUIData )value );
		player = GetPlayerControlledObject();
		isQuestRemoteControlDriving = false;
		m_remoteControlledVehicle = data.remoteControlledVehicle;
		DestroyMappin();
		if( m_remoteControlledVehicle )
		{
			isQuestRemoteControlDriving = m_remoteControlledVehicle && ( m_remoteControlledVehicle == GetMountedVehicle( player ) );
			if( !( isQuestRemoteControlDriving ) )
			{
				CreateMappin();
				inkWidgetRef.SetVisible( m_containerSignalStrength, true );
				m_containerSignalStrengthIntroOutroAnimProxy = PlayLibraryAnimation( 'connection-intro' );
				if( VehicleComponent.GetVehicleRecord( m_remoteControlledVehicle, record ) )
				{
					inkImageRef.SetTexturePart( m_vehicleManufacturer, TweakDBInterface.GetUIIconRecord( TDBID.Create( "UIIcon." + record.Manufacturer().EnumName() ) ).AtlasPartName() );
				}
				GameObjectEffectHelper.StartEffectEvent( player, 'fish_eye' );
			}
		}
		else
		{
			if( m_containerSignalStrengthIntroOutroAnimProxy.IsValid() )
			{
				progression = m_containerSignalStrengthIntroOutroAnimProxy.GetProgression();
				m_containerSignalStrengthIntroOutroAnimProxy.Stop();
				m_containerSignalStrengthIntroOutroAnimProxy = NULL;
				if( progression < 1.15999997 )
				{
					options.fromMarker = 'connection_lost';
				}
			}
			else
			{
				if( data.isDistanceDisconnect )
				{
					options.fromMarker = 'connection_lost';
				}
			}
			m_containerSignalStrengthIntroOutroAnimProxy = PlayLibraryAnimation( 'connection-outro', options );
			m_containerSignalStrengthIntroOutroAnimProxy.RegisterToCallback( inkanimEventType.OnFinish, this, 'OnConnectionOutroFinished' );
			GameObjectEffectHelper.StopEffectEvent( player, 'fish_eye' );
		}
		inkWidgetRef.SetVisible( m_overlay, ( m_remoteControlledVehicle != NULL ) && !( isQuestRemoteControlDriving ) );
	}

	protected event OnConnectionOutroFinished( anim : inkAnimProxy )
	{
		m_containerSignalStrengthIntroOutroAnimProxy.UnregisterFromCallback( inkanimEventType.OnFinish, this, 'OnConnectionOutroFinished' );
		m_containerSignalStrengthIntroOutroAnimProxy = NULL;
		inkWidgetRef.SetVisible( m_containerSignalStrength, false );
	}

	private function CreateMappin()
	{
		var mappinSystem : MappinSystem;
		var mappinData : MappinData;
		mappinSystem = GameInstance.GetMappinSystem( GetPlayerControlledObject().GetGame() );
		mappinData.mappinType = T"Mappins.RemoteControlDrivingMappinDefinition";
		mappinData.variant = gamedataMappinVariant.Zzz10_RemoteControlDrivingVariant;
		mappinData.active = true;
		mappinData.visibleThroughWalls = true;
		m_mappinID = mappinSystem.RegisterMappinWithObject( mappinData, m_remoteControlledVehicle, 'vehMappin' );
	}

	private function DestroyMappin()
	{
		var mappinSystem : MappinSystem;
		if( m_mappinID.value != ( ( Uint64 )( 0 ) ) )
		{
			mappinSystem = GameInstance.GetMappinSystem( GetPlayerControlledObject().GetGame() );
			mappinSystem.UnregisterMappin( m_mappinID );
			m_mappinID.value = ( ( Uint64 )( 0 ) );
		}
	}

}

