class NcartTimetableInkGameController extends DeviceInkGameControllerBase
{
	private var m_defaultUI : weak< inkCanvas >;
	private var m_mainDisplayWidget : weak< inkVideo >;
	private var m_counterWidget : weak< inkText >;
	private var m_trainImage : weak< inkImage >;
	private var m_cachedLine : Int32;
	private editable var m_lineAIcon : inkImageRef;
	private editable var m_lineBIcon : inkImageRef;
	private editable var m_lineCIcon : inkImageRef;
	private editable var m_lineDIcon : inkImageRef;
	private editable var m_lineEIcon : inkImageRef;
	private var m_onGlitchingStateChangedListener : CallbackHandle;
	private var m_onTimeToDepartChangedListener : CallbackHandle;
	private var m_onCurrentLineNumberChangedListener : CallbackHandle;
	private var m_animProxy : inkAnimProxy;

	protected event OnInitialize()
	{
		super.OnInitialize();
		m_cachedLine = GetBlackboard().GetInt( GetOwner().GetBlackboardDef().NextTrainLine );
		UpdateLineIconVisiblity();
		SetTrainColor();
		ResolvePrologueState();
	}

	protected event OnUninitialize()
	{
		super.OnUninitialize();
		m_mainDisplayWidget.Stop();
	}

	protected override function SetupWidgets()
	{
		if( !( m_isInitialized ) )
		{
			m_defaultUI = ( ( inkCanvas )( GetWidget( 'default_ui' ) ) );
			m_counterWidget = ( ( inkText )( GetWidget( 'default_ui/CounterPane/counter_text' ) ) );
			m_mainDisplayWidget = ( ( inkVideo )( GetWidget( 'main_display' ) ) );
			m_trainImage = ( ( inkImage )( GetWidget( 'default_ui/Train' ) ) );
			m_rootWidget.SetVisible( false );
		}
	}

	public override function UpdateActionWidgets( const widgetsData : ref< array< SActionWidgetPackage > > ) {}

	public override function Refresh( state : EDeviceStatus )
	{
		SetupWidgets();
		RequestActionWidgetsUpdate();
		switch( state )
		{
			case EDeviceStatus.ON:
				TurnOn();
			break;
			case EDeviceStatus.OFF:
				TurnOff();
			break;
			case EDeviceStatus.UNPOWERED:
				break;
			case EDeviceStatus.DISABLED:
				break;
			default:
				break;
		}
		super.Refresh( state );
	}

	protected override function RegisterBlackboardCallbacks( blackboard : IBlackboard )
	{
		super.RegisterBlackboardCallbacks( blackboard );
		if( blackboard )
		{
			m_onGlitchingStateChangedListener = blackboard.RegisterListenerVariant( GetOwner().GetBlackboardDef().GlitchData, this, 'OnGlitchingStateChanged' );
			m_onTimeToDepartChangedListener = blackboard.RegisterListenerInt( GetOwner().GetBlackboardDef().TimeToDepart, this, 'OnTimeToDepartChanged' );
		}
	}

	protected override function UnRegisterBlackboardCallbacks( blackboard : IBlackboard )
	{
		super.UnRegisterBlackboardCallbacks( blackboard );
		if( blackboard )
		{
			blackboard.UnregisterListenerVariant( GetOwner().GetBlackboardDef().GlitchData, m_onGlitchingStateChangedListener );
			blackboard.UnregisterListenerInt( GetOwner().GetBlackboardDef().TimeToDepart, m_onTimeToDepartChangedListener );
		}
	}

	protected override function GetOwner() : NcartTimetable
	{
		return ( ( NcartTimetable )( GetOwnerEntity() ) );
	}

	protected event OnActionWidgetsUpdate( value : Variant )
	{
		var widgets : array< SActionWidgetPackage >;
		widgets = ( ( array< SActionWidgetPackage > )value );
		UpdateActionWidgets( widgets );
	}

	protected event OnTrainArrivalAnimationFinished( proxy : inkAnimProxy )
	{
		proxy.UnregisterFromCallback( inkanimEventType.OnFinish, this, 'OnTrainArrivalAnimationFinished' );
		m_animProxy = PlayLibraryAnimation( 'TrainDeparture' );
		m_animProxy.RegisterToCallback( inkanimEventType.OnFinish, this, 'OnTrainDepartureAnimationFinished' );
	}

	protected event OnTrainDepartureAnimationFinished( proxy : inkAnimProxy )
	{
		proxy.UnregisterFromCallback( inkanimEventType.OnFinish, this, 'OnTrainArrivalAnimationFinished' );
		m_cachedLine = GetBlackboard().GetInt( GetOwner().GetBlackboardDef().NextTrainLine );
		UpdateLineIconVisiblity();
		SetTrainColor();
		PlayLibraryAnimation( 'TimerReset' );
	}

	protected event OnTimeToDepartChanged( value : Int32 )
	{
		var textParams : inkTextParams;
		if( value == 5 )
		{
			m_animProxy = PlayLibraryAnimation( 'TrainArrival' );
			m_animProxy.RegisterToCallback( inkanimEventType.OnFinish, this, 'OnTrainArrivalAnimationFinished' );
		}
		if( m_counterWidget != NULL )
		{
			textParams = new inkTextParams;
			textParams.AddTime( "TIMER", value );
			m_counterWidget.SetLocalizedTextScript( "LocKey#48343", textParams );
		}
	}

	private function SetTrainColor()
	{
		switch( m_cachedLine )
		{
			case 1:
			{
				m_trainImage.SetTintColor( Color( 229, 25, 25, 255 ) );
			}
			break;
			case 2:
			{
				m_trainImage.SetTintColor( Color( 255, 248, 0, 255 ) );
			}
			break;
			case 3:
			{
				m_trainImage.SetTintColor( Color( 18, 228, 255, 255 ) );
			}
			break;
			case 4:
			{
				m_trainImage.SetTintColor( Color( 27, 233, 32, 255 ) );
			}
			break;
			case 5:
			{
				m_trainImage.SetTintColor( Color( 250, 131, 0, 255 ) );
			}
			break;
			default:
			{
				m_trainImage.SetTintColor( Color( 18, 228, 255, 255 ) );
			}
		}
	}

	private function ResolvePrologueState()
	{
		var prologueFact : Int32;
		prologueFact = GameInstance.GetQuestsSystem( GetOwner().GetGame() ).GetFact( 'watson_prolog_lock' );
		if( prologueFact > 0 )
		{
			m_defaultUI.SetOpacity( 0.0 );
		}
		else
		{
			m_defaultUI.SetOpacity( 1.0 );
		}
	}

	private function UpdateLineIconVisiblity()
	{
		switch( m_cachedLine )
		{
			case 1:
			{
				inkImageRef.SetOpacity( m_lineAIcon, 1.0 );
				inkImageRef.SetOpacity( m_lineBIcon, 0.0 );
				inkImageRef.SetOpacity( m_lineCIcon, 0.0 );
				inkImageRef.SetOpacity( m_lineDIcon, 0.0 );
				inkImageRef.SetOpacity( m_lineEIcon, 0.0 );
			}
			break;
			case 2:
			{
				inkImageRef.SetOpacity( m_lineAIcon, 0.0 );
				inkImageRef.SetOpacity( m_lineBIcon, 1.0 );
				inkImageRef.SetOpacity( m_lineCIcon, 0.0 );
				inkImageRef.SetOpacity( m_lineDIcon, 0.0 );
				inkImageRef.SetOpacity( m_lineEIcon, 0.0 );
			}
			break;
			case 3:
			{
				inkImageRef.SetOpacity( m_lineAIcon, 0.0 );
				inkImageRef.SetOpacity( m_lineBIcon, 0.0 );
				inkImageRef.SetOpacity( m_lineCIcon, 1.0 );
				inkImageRef.SetOpacity( m_lineDIcon, 0.0 );
				inkImageRef.SetOpacity( m_lineEIcon, 0.0 );
			}
			break;
			case 4:
			{
				inkImageRef.SetOpacity( m_lineAIcon, 0.0 );
				inkImageRef.SetOpacity( m_lineBIcon, 0.0 );
				inkImageRef.SetOpacity( m_lineCIcon, 0.0 );
				inkImageRef.SetOpacity( m_lineDIcon, 1.0 );
				inkImageRef.SetOpacity( m_lineEIcon, 0.0 );
			}
			break;
			case 5:
			{
				inkImageRef.SetOpacity( m_lineAIcon, 0.0 );
				inkImageRef.SetOpacity( m_lineBIcon, 0.0 );
				inkImageRef.SetOpacity( m_lineCIcon, 0.0 );
				inkImageRef.SetOpacity( m_lineDIcon, 0.0 );
				inkImageRef.SetOpacity( m_lineEIcon, 1.0 );
			}
			break;
			default:
			{
				inkImageRef.SetOpacity( m_lineAIcon, 1.0 );
				inkImageRef.SetOpacity( m_lineBIcon, 0.0 );
				inkImageRef.SetOpacity( m_lineCIcon, 0.0 );
				inkImageRef.SetOpacity( m_lineDIcon, 0.0 );
				inkImageRef.SetOpacity( m_lineEIcon, 0.0 );
			}
		}
	}

	private override function StartGlitchingScreen( glitchData : GlitchData )
	{
		StopVideo();
		m_defaultUI.SetVisible( false );
		if( glitchData.state == EGlitchState.DEFAULT )
		{
			PlayVideo( R"base\movies\misc\generic_noise_white.bk2", true, '' );
		}
		else
		{
			PlayVideo( R"base\movies\misc\distraction_generic.bk2", true, '' );
		}
	}

	private override function StopGlitchingScreen()
	{
		StopVideo();
		m_defaultUI.SetVisible( true );
	}

	public function PlayVideo( videoPath : ResRef, looped : Bool, audioEvent : CName )
	{
		m_mainDisplayWidget.SetVideoPath( videoPath );
		m_mainDisplayWidget.SetLoop( looped );
		if( IsNameValid( audioEvent ) )
		{
			m_mainDisplayWidget.SetAudioEvent( audioEvent );
		}
		m_mainDisplayWidget.Play();
	}

	public function StopVideo()
	{
		m_mainDisplayWidget.Stop();
	}

	public function TurnOff()
	{
		m_rootWidget.SetVisible( false );
		m_mainDisplayWidget.UnregisterFromCallback( 'OnVideoFinished', this, 'OnVideoFinished' );
	}

	public function TurnOn()
	{
		m_rootWidget.SetVisible( true );
	}

}

