class hudCarController extends inkHUDGameController
{
	private editable var m_SpeedValue : inkTextRef;
	private editable var m_SpeedUnits : inkTextRef;
	private const editable var m_RPMChunks : array< inkImageRef >;
	private var m_psmBlackboard : weak< IBlackboard >;
	private var m_PSM_BBID : CallbackHandle;
	private var m_currentZoom : Float;
	private var currentTime : GameTime;
	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_activeChunks : Int32;
	private var m_rpmMaxValue : Float;
	private var m_currentSpeed : Int32;
	default m_currentSpeed = -1;
	private var m_activeVehicle : weak< VehicleObject >;
	private var m_driver : Bool;
	protected var m_settings : UserSettings;
	protected var m_settingsListener : CarSpeedometerSettingsListener;
	protected var m_groupPath : CName;
	default m_groupPath = '/interface';
	private var m_kmOn : Bool;

	protected event OnInitialize()
	{
		PlayLibraryAnimation( 'intro' );
	}

	protected event OnUninitialize() {}

	protected event OnPlayerAttach( playerPuppet : GameObject )
	{
		m_psmBlackboard = GetPSMBlackboard( playerPuppet );
		if( m_psmBlackboard )
		{
			m_PSM_BBID = m_psmBlackboard.RegisterDelayedListenerFloat( GetAllBlackboardDefs().PlayerStateMachine.ZoomLevel, this, 'OnZoomChange' );
		}
		m_activeVehicle = GetMountedVehicle( GetPlayerControlledObject() );
		m_driver = VehicleComponent.IsDriver( m_activeVehicle.GetGame(), GetPlayerControlledObject() );
		if( m_activeVehicle && m_driver )
		{
			GetRootWidget().SetVisible( CheckIfInTPP() );
			RegisterUserSettingsListener();
			RegisterToVehicle( true );
			Reset();
		}
		else
		{
			GetRootWidget().SetVisible( false );
		}
	}

	protected event OnPlayerDetach( playerPuppet : GameObject )
	{
		m_psmBlackboard.UnregisterDelayedListener( GetAllBlackboardDefs().PlayerStateMachine.ZoomLevel, m_PSM_BBID );
		if( m_activeVehicle )
		{
			GetRootWidget().SetVisible( false );
			RegisterToVehicle( false );
			m_activeVehicle = NULL;
			m_currentSpeed = -1;
		}
	}

	protected event OnMountingEvent( evt : MountingEvent )
	{
		m_activeVehicle = GetMountedVehicle( GetPlayerControlledObject() );
		m_driver = VehicleComponent.IsDriver( m_activeVehicle.GetGame(), GetPlayerControlledObject() );
		GetRootWidget().SetVisible( false );
		RegisterToVehicle( true );
		Reset();
	}

	protected event OnUnmountingEvent( evt : UnmountingEvent )
	{
		if( !( evt.request.mountData.mountEventOptions.silentUnmount ) )
		{
			GetRootWidget().SetVisible( false );
			RegisterToVehicle( false );
			m_activeVehicle = NULL;
			m_currentSpeed = -1;
		}
	}

	private function CheckIfInTPP() : Bool
	{
		var activeVehicleUIBlackboard : weak< IBlackboard >;
		if( m_activeVehicle == NULL )
		{
			return false;
		}
		activeVehicleUIBlackboard = GameInstance.GetBlackboardSystem( m_activeVehicle.GetGame() ).Get( GetAllBlackboardDefs().UI_ActiveVehicleData );
		return activeVehicleUIBlackboard.GetBool( GetAllBlackboardDefs().UI_ActiveVehicleData.IsTPPCameraOn );
	}

	private function RegisterToVehicle( register : Bool )
	{
		var vehicle : VehicleObject;
		var vehicleBlackboard : weak< IBlackboard >;
		var activeVehicleUIBlackboard : weak< IBlackboard >;
		var record : weak< Vehicle_Record >;
		var vehEngineData : weak< VehicleEngineData_Record >;
		vehicle = m_activeVehicle;
		if( vehicle == NULL )
		{
			return;
		}
		vehicleBlackboard = vehicle.GetBlackboard();
		if( vehicleBlackboard )
		{
			if( register )
			{
				m_speedBBConnectionId = vehicleBlackboard.RegisterListenerFloat( GetAllBlackboardDefs().Vehicle.SpeedValue, this, 'OnSpeedValueChanged' );
				m_gearBBConnectionId = vehicleBlackboard.RegisterListenerInt( GetAllBlackboardDefs().Vehicle.GearValue, this, 'OnGearValueChanged' );
				m_rpmValueBBConnectionId = vehicleBlackboard.RegisterListenerFloat( GetAllBlackboardDefs().Vehicle.RPMValue, this, 'OnRpmValueChanged' );
				record = vehicle.GetRecord();
				vehEngineData = record.VehEngineData();
				m_rpmMaxValue = vehEngineData.MaxRPM();
			}
			else
			{
				vehicleBlackboard.UnregisterListenerFloat( GetAllBlackboardDefs().Vehicle.SpeedValue, m_speedBBConnectionId );
				vehicleBlackboard.UnregisterListenerInt( GetAllBlackboardDefs().Vehicle.GearValue, m_gearBBConnectionId );
				vehicleBlackboard.UnregisterListenerFloat( GetAllBlackboardDefs().Vehicle.RPMValue, m_rpmValueBBConnectionId );
			}
		}
		activeVehicleUIBlackboard = GameInstance.GetBlackboardSystem( vehicle.GetGame() ).Get( GetAllBlackboardDefs().UI_ActiveVehicleData );
		if( activeVehicleUIBlackboard )
		{
			if( register )
			{
				m_tppBBConnectionId = activeVehicleUIBlackboard.RegisterListenerBool( GetAllBlackboardDefs().UI_ActiveVehicleData.IsTPPCameraOn, this, 'OnCameraModeChanged', true );
			}
			else
			{
				activeVehicleUIBlackboard.UnregisterListenerBool( GetAllBlackboardDefs().UI_ActiveVehicleData.IsTPPCameraOn, m_tppBBConnectionId );
			}
		}
	}

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

	protected event OnRpmMaxChanged( rpmMax : Float ) {}

	protected event OnSpeedValueChanged( speedValue : Float )
	{
		var multiplier, floatspeed : Float;
		var speed : Int32;
		speedValue = AbsF( speedValue );
		multiplier = GameInstance.GetStatsDataSystem( m_activeVehicle.GetGame() ).GetValueFromCurve( 'vehicle_ui', speedValue, 'speed_to_multiplier' );
		floatspeed = speedValue * multiplier;
		speed = RoundMath( speedValue * multiplier );
		if( speed != m_currentSpeed )
		{
			if( m_kmOn )
			{
				inkTextRef.SetText( m_SpeedValue, IntToString( RoundMath( floatspeed * 1.60933995 ) ) );
			}
			else
			{
				inkTextRef.SetText( m_SpeedValue, IntToString( speed ) );
			}
			m_currentSpeed = speed;
		}
	}

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

	protected event OnRpmValueChanged( rpmValue : Float )
	{
		drawRPMGaugeFull( rpmValue );
	}

	private function Reset()
	{
		OnSpeedValueChanged( 0.0 );
		OnRpmValueChanged( 0.0 );
	}

	public function drawRPMGaugeFull( rpmValue : Float )
	{
		var level : Float;
		var levelInt : Int32;
		level = ( ( rpmValue / m_rpmMaxValue ) * 5000.0 ) / ( ( Float )( ( m_RPMChunks.Size() * 49 ) ) );
		levelInt = ( ( Int32 )( level ) );
		if( ( rpmValue > 500.0 ) && ( level < 1.0 ) )
		{
			levelInt = 1;
		}
		EvaluateRPMMeterWidget( levelInt );
	}

	private function EvaluateRPMMeterWidget( currentAmountOfChunks : Int32 )
	{
		if( currentAmountOfChunks == m_activeChunks )
		{
			return;
		}
		m_activeChunks = currentAmountOfChunks;
		UpdateChunkVisibility();
	}

	private function UpdateChunkVisibility()
	{
		var i : Int32;
		var visible : Bool;
		for( i = 0; i <= m_RPMChunks.Size(); i += 1 )
		{
			visible = i < m_activeChunks;
			inkImageRef.SetVisible( m_RPMChunks[ i ], visible );
		}
	}

	protected event OnLeanAngleChanged( leanAngle : Float ) {}

	protected event OnCameraModeChanged( mode : Bool )
	{
		if( m_driver )
		{
			GetRootWidget().SetVisible( mode );
			RegisterUserSettingsListener();
		}
	}

	public function OnVarModified( groupPath : CName, varName : CName, varType : ConfigVarType, reason : ConfigChangeReason )
	{
		switch( varName )
		{
			case 'SpeedometerUnits':
				UpdateMeasurementUnits();
			break;
			default:
				break;
		}
	}

	private function UpdateMeasurementUnits()
	{
		var configVar : ConfigVarListString;
		configVar = ( ( ConfigVarListString )( m_settings.GetVar( m_groupPath, 'SpeedometerUnits' ) ) );
		SetMeasurementUnits( configVar.GetIndex() );
	}

	protected virtual function SetMeasurementUnits( value : Int32 )
	{
		if( value == 1 )
		{
			m_kmOn = false;
			inkTextRef.SetLocalizedTextScript( m_SpeedUnits, "LocKey#95281" );
		}
		else
		{
			m_kmOn = true;
			inkTextRef.SetLocalizedTextScript( m_SpeedUnits, "LocKey#95356" );
		}
	}

	private function RegisterUserSettingsListener()
	{
		m_settings = new UserSettings;
		m_settingsListener = new CarSpeedometerSettingsListener;
		m_settingsListener.RegisterController( this );
		m_settingsListener.Register( m_groupPath );
		UpdateMeasurementUnits();
	}

}

class CarSpeedometerSettingsListener extends ConfigVarListener
{
	private var m_ctrl : weak< hudCarController >;

	public function RegisterController( ctrl : hudCarController )
	{
		m_ctrl = ctrl;
	}

	public export override function OnVarModified( groupPath : CName, varName : CName, varType : ConfigVarType, reason : ConfigChangeReason )
	{
		m_ctrl.OnVarModified( groupPath, varName, varType, reason );
	}

}

