struct ncartDoorScreenLineDataDef
{
	editable var m_lineNumber : Uint32;
	editable var m_lineColor : Color;
	editable var m_lineSymbolWidget : inkWidgetRef;
}

class NcartDoorScreenInkController extends NcartTrainInkControllerBase
{
	private const editable var m_LinesList : array< ncartDoorScreenLineDataDef >;
	private editable var m_ActiveLineFactName : CName;
	private editable var m_NextStationFactName : CName;
	private editable var m_MetroStoppingFactName : CName;
	private var m_root : weak< inkCompoundWidget >;
	private var m_questsSystem : weak< QuestsSystem >;
	private var m_StopListenerId : Uint32;
	private var m_NextStationListenerId : Uint32;
	private var m_gameTimeCallback : CallbackHandle;
	private editable var m_ncartTextLogo : inkImageRef;
	private editable var m_timeWidget : inkTextRef;
	private editable var m_stationNameWidget : inkTextRef;
	private editable var m_stationStatusWidget : inkTextRef;
	private editable var m_districtNameWidget : inkTextRef;
	private editable var m_stationDistrictBackgroundColor : inkImageRef;
	private editable var m_sun_moon_container : inkWidgetRef;
	private editable var m_weather_sun_widget : inkImageRef;
	private editable var m_weather_moon_widget : inkImageRef;
	private editable var m_weather_cloud_a_widget : inkImageRef;
	private editable var m_weather_cloud_b_widget : inkImageRef;
	private editable var m_weather_rain_widget : inkImageRef;
	private editable var m_speed_display : inkTextRef;
	private editable var m_speed_display_deco_1 : inkImageRef;
	private editable var m_speed_display_deco_2 : inkImageRef;
	private editable var m_speed_display_deco_3 : inkImageRef;
	private editable var m_speed_display_deco_4 : inkImageRef;
	private var m_cachedActiveLine : Int32;
	private var m_cachedNextStation : Int32;
	private var m_cachedDistrict : ENcartDistricts;
	default m_cachedDistrict = ENcartDistricts.ERROR;
	private var m_updateDistrictName : Bool;
	private var m_ownerObject : weak< VehicleObject >;
	private var m_vehicleBlackboard : weak< IBlackboard >;
	private var m_AnimProxy : inkAnimProxy;
	private var speedListner : CallbackHandle;
	private var speedLastValue : Float;

	protected event OnInitialize()
	{
		super.OnInitialize();
		m_ownerObject = ( ( VehicleObject )( GetOwnerEntity() ) );
		m_questsSystem = GameInstance.GetQuestsSystem( m_ownerObject.GetGame() );
		m_vehicleBlackboard = m_ownerObject.GetBlackboard();
		m_StopListenerId = m_questsSystem.RegisterListener( m_MetroStoppingFactName, this, 'OnMetroArrivingAtStationEvent' );
		m_NextStationListenerId = m_questsSystem.RegisterListener( m_NextStationFactName, this, 'OnMetroNextStationChangeEvent' );
		m_root = ( ( inkCompoundWidget )( GetRootWidget() ) );
		m_cachedActiveLine = m_questsSystem.GetFact( m_ActiveLineFactName );
		m_cachedNextStation = m_questsSystem.GetFact( m_NextStationFactName );
		m_cachedDistrict = GetMetroStationDistrict( GetMetroStationEnumFromNumber( m_cachedNextStation ) );
		if( inkTextRef.IsValid( m_speed_display ) )
		{
			speedListner = m_vehicleBlackboard.RegisterListenerFloat( GetAllBlackboardDefs().Vehicle.SpeedValue, this, 'OnTrainSpeedChanged' );
		}
		m_updateDistrictName = true;
		UpdateMetroLine( m_cachedActiveLine );
		UpdateWeather();
		RegisterBlackBoardCallbacks();
		m_vehicleBlackboard.SignalString( GetAllBlackboardDefs().Vehicle.GameTime );
	}

	protected event OnUninitialize()
	{
		m_questsSystem.UnregisterListener( m_MetroStoppingFactName, m_StopListenerId );
		m_questsSystem.UnregisterListener( m_NextStationFactName, m_NextStationListenerId );
		UnregisterBlackBoardCallbacks();
	}

	protected event OnMetroNextStationChangeEvent( factValue : Int32 )
	{
		ChangeNextStationName( factValue );
	}

	protected event OnMetroArrivingAtStationEvent( factValue : Int32 )
	{
		if( factValue == 1 )
		{
			TrainStopAnim();
		}
	}

	protected event OnTrainSpeedChanged( speed : Float )
	{
		var randomSway : Float;
		speedLastValue = speed;
		if( ( speed == speedLastValue ) && ( speed > 1.0 ) )
		{
			randomSway = RandRangeF( -0.2, 0.2 );
		}
		if( ( speed < 2.0 ) && ( speed > 0.0 ) )
		{
			inkTextRef.SetText( m_speed_display, "1.0" );
		}
		if( speed >= 0.0 )
		{
			inkTextRef.SetText( m_speed_display, "0.0" );
		}
		inkTextRef.SetText( m_speed_display, FloatToStringPrec( ( speed * 2.5999999 ) + randomSway, 1 ) );
	}

	private function UpdateMetroLine( activeLine : Int32 )
	{
		var color : Color;
		color = m_LinesList[ activeLine - 1 ].m_lineColor;
		inkWidgetRef.SetTintColor( m_LinesList[ activeLine - 1 ].m_lineSymbolWidget, color );
		inkWidgetRef.SetOpacity( m_LinesList[ activeLine - 1 ].m_lineSymbolWidget, 1.0 );
		inkImageRef.SetTintColor( m_ncartTextLogo, color );
		if( inkTextRef.IsValid( m_speed_display ) )
		{
			inkImageRef.SetTintColor( m_speed_display_deco_1, color );
			inkImageRef.SetTintColor( m_speed_display_deco_2, color );
			inkImageRef.SetTintColor( m_speed_display_deco_3, color );
			inkImageRef.SetTintColor( m_speed_display_deco_4, color );
		}
		PlayArrowsAnimation();
		UpdateDestinationStation( m_cachedNextStation );
	}

	private function UpdateDestinationStation( DestinationStation : Int32 )
	{
		if( m_updateDistrictName )
		{
			inkTextRef.SetLocalizedTextString( m_districtNameWidget, GetDistrictLocalizedName( m_cachedDistrict ) );
			inkImageRef.SetTintColor( m_stationDistrictBackgroundColor, GetDistrictColor( m_cachedDistrict ) );
		}
		inkTextRef.SetLocalizedTextString( m_stationNameWidget, GetMetroStationLocalizedNameByNumber( DestinationStation ) );
	}

	private function UpdateWeather()
	{
		var weatherFact : Int32;
		weatherFact = m_questsSystem.GetFact( 'ue_metro_weather' );
		UpdateDayNightWeatherIcon();
		switch( weatherFact )
		{
			case 1:
			{
				inkWidgetRef.SetOpacity( m_sun_moon_container, 1.0 );
			}
			break;
			case 2:
			{
				inkWidgetRef.SetOpacity( m_sun_moon_container, 1.0 );
				inkImageRef.SetOpacity( m_weather_cloud_a_widget, 1.0 );
			}
			break;
			case 3:
			{
				inkImageRef.SetOpacity( m_weather_cloud_a_widget, 1.0 );
				inkImageRef.SetOpacity( m_weather_cloud_b_widget, 1.0 );
			}
			break;
			case 3:
			{
				inkImageRef.SetOpacity( m_weather_rain_widget, 1.0 );
			}
			break;
			default:
			{
				inkImageRef.SetOpacity( m_weather_cloud_a_widget, 1.0 );
				inkImageRef.SetOpacity( m_weather_cloud_b_widget, 1.0 );
			}
			break;
		}
	}

	private function TrainStopAnim()
	{
		var animSetup : inkAnimOptions;
		animSetup.loopInfinite = false;
		animSetup.loopType = inkanimLoopType.None;
		animSetup.dependsOnTimeDilation = true;
		PlayLibraryAnimation( 'ArrivingAtStation', animSetup );
	}

	private function PlayArrowsAnimation()
	{
		var animSetup : inkAnimOptions;
		animSetup.loopInfinite = true;
		animSetup.loopType = inkanimLoopType.Cycle;
		animSetup.dependsOnTimeDilation = true;
		PlayLibraryAnimation( 'ArrowsLoop', animSetup );
	}

	private function ChangeNextStationName( newStation : Int32 )
	{
		var animSetup : inkAnimOptions;
		var district : ENcartDistricts;
		m_cachedNextStation = m_questsSystem.GetFact( m_NextStationFactName );
		district = GetMetroStationDistrict( GetMetroStationEnumFromNumber( m_cachedNextStation ) );
		animSetup.loopInfinite = false;
		animSetup.loopType = inkanimLoopType.None;
		animSetup.dependsOnTimeDilation = true;
		m_AnimProxy = PlayLibraryAnimation( 'HideStationName', animSetup );
		if( district != m_cachedDistrict )
		{
			m_cachedDistrict = district;
			PlayLibraryAnimation( 'HideDistrictPane', animSetup );
			m_updateDistrictName = true;
		}
		m_AnimProxy.RegisterToCallback( inkanimEventType.OnFinish, this, 'OnEndAnimLoop' );
	}

	protected event OnEndAnimLoop( proxy : inkAnimProxy )
	{
		UpdateDestinationStation( m_cachedNextStation );
		PlayLibraryAnimation( 'ShowNewStationName' );
		if( m_updateDistrictName )
		{
			m_updateDistrictName = false;
			PlayLibraryAnimation( 'ShowDistrictPane' );
		}
		m_AnimProxy.UnregisterFromCallback( inkanimEventType.OnEndLoop, this, 'OnEndAnimLoop' );
	}

	private function RegisterBlackBoardCallbacks()
	{
		if( m_vehicleBlackboard )
		{
			if( !( m_gameTimeCallback ) )
			{
				m_gameTimeCallback = m_vehicleBlackboard.RegisterListenerString( GetAllBlackboardDefs().Vehicle.GameTime, this, 'OnGameTimeChanged' );
			}
		}
	}

	private function UnregisterBlackBoardCallbacks()
	{
		if( m_vehicleBlackboard )
		{
			m_vehicleBlackboard.UnregisterListenerString( GetAllBlackboardDefs().Vehicle.GameTime, m_gameTimeCallback );
		}
	}

	private function UpdateDayNightWeatherIcon()
	{
		var sunSet : GameTime;
		var sunRise : GameTime;
		var currTime : GameTime;
		var time : GameTime;
		time = GameInstance.GetTimeSystem( m_ownerObject.GetGame() ).GetGameTime();
		sunSet = GameTime.MakeGameTime( 0, 20, 0, 0 );
		sunRise = GameTime.MakeGameTime( 0, 5, 0, 0 );
		currTime = GameTime.MakeGameTime( 0, GameTime.Hours( time ), GameTime.Minutes( time ), GameTime.Seconds( time ) );
		if( ( currTime <= sunSet ) && ( currTime >= sunRise ) )
		{
			inkImageRef.SetOpacity( m_weather_sun_widget, 1.0 );
			inkImageRef.SetOpacity( m_weather_moon_widget, 0.0 );
		}
		else
		{
			inkImageRef.SetOpacity( m_weather_sun_widget, 0.0 );
			inkImageRef.SetOpacity( m_weather_moon_widget, 1.0 );
		}
	}

	public function OnGameTimeChanged( time : String )
	{
		if( inkTextRef.IsValid( m_timeWidget ) )
		{
			inkTextRef.SetText( m_timeWidget, time );
			UpdateDayNightWeatherIcon();
		}
	}

}

