class TerminalInkGameControllerBase extends MasterDeviceInkGameControllerBase
{
	[ customEditor = "TweakDBGroupInheritance;WidgetDefinition" ]
	protected editable var m_layoutID : TweakDBID;
	protected var m_currentLayoutLibraryID : CName;
	protected var m_mainLayout : weak< inkWidget >;
	protected var m_currentlyActiveDevices : array< PersistentID >;
	private var m_buttonVisibility : Bool;
	private var m_mainDisplayWidget : weak< inkVideo >;
	private var m_terminalTitle : String;
	private var m_onGlitchingStateChangedListener : CallbackHandle;

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

	protected override function SetupWidgets()
	{
		if( !( m_isInitialized ) )
		{
			m_mainDisplayWidget = ( ( inkVideo )( GetWidget( 'main_display' ) ) );
			m_mainDisplayWidget.SetVisible( false );
			InitializeMainLayout();
		}
	}

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

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

	private function SetupTerminalTitle()
	{
		if( GetOwner().ShouldShowTerminalTitle() )
		{
			m_terminalTitle = GetOwner().GetDisplayName();
		}
	}

	public const function GetTerminalTitle() : String
	{
		return m_terminalTitle;
	}

	protected virtual function InitializeMainLayout()
	{
		var layoutRecord : WidgetDefinition_Record;
		var screenDef : ScreenDefinitionPackage;
		var newLibraryID : CName;
		var spawnData : AsyncSpawnData;
		if( !( TDBID.IsValid( m_layoutID ) ) )
		{
			m_layoutID = T"DevicesUIDefinitions.TerminalLayoutWidget";
		}
		screenDef = GetScreenDefinition();
		layoutRecord = TweakDBInterface.GetWidgetDefinitionRecord( m_layoutID );
		newLibraryID = GetCurrentFullLibraryID( layoutRecord, screenDef.screenDefinition.TerminalScreenType(), screenDef.style );
		if( m_currentLayoutLibraryID == newLibraryID )
		{
			return;
		}
		if( m_mainLayout != NULL )
		{
			( ( inkCompoundWidget )( GetRootWidget() ) ).RemoveChild( m_mainLayout );
		}
		spawnData = new AsyncSpawnData;
		spawnData.Initialize( this, 'OnMainLayoutSpawned', NULL, this );
		m_currentLayoutLibraryID = RequestWidgetFromLibrary( GetRootWidget(), layoutRecord, screenDef.screenDefinition.TerminalScreenType(), screenDef.style, , , spawnData );
		SetupTerminalTitle();
	}

	protected function IsMainLayoutInitialized() : Bool
	{
		return m_mainLayout != NULL;
	}

	protected event OnMainLayoutSpawned( widget : inkWidget, userData : IScriptable )
	{
		var controller : TerminalMainLayoutWidgetController;
		m_mainLayout = widget;
		m_mainLayout.SetAnchor( inkEAnchor.Fill );
		controller = GetMainLayoutController();
		if( controller )
		{
			RegisterReturnButtonCallback();
			controller.Initialize( this );
		}
		if( GetOwner().IsReadyForUI() )
		{
			Refresh( GetOwner().GetDeviceState() );
		}
	}

	protected override function UpdateThumbnailWidgets( const widgetsData : ref< array< SThumbnailWidgetPackage > > )
	{
		var i : Int32;
		var widget : inkWidget;
		super.UpdateThumbnailWidgets( widgetsData );
		GetMainLayoutController().GetDevicesSlot().SetVisible( false );
		GetMainLayoutController().GetThumbnailListSlot().SetVisible( true );
		if( widgetsData.Size() == 1 )
		{
			if( !( IsOwner( widgetsData[ i ].ownerID ) ) )
			{
				m_buttonVisibility = false;
				m_currentlyActiveDevices.Clear();
				m_currentlyActiveDevices.PushBack( widgetsData[ i ].ownerID );
				RequestDeviceWidgetsUpdate( m_currentlyActiveDevices );
			}
		}
		else
		{
			m_buttonVisibility = true;
			for( i = 0; i < widgetsData.Size(); i += 1 )
			{
				widget = GetThumbnailWidget( widgetsData[ i ] );
				if( widget == NULL )
				{
					CreateThumbnailWidgetAsync( GetMainLayoutController().GetThumbnailListSlot(), widgetsData[ i ] );
				}
				else
				{
					InitializeThumbnailWidget( widget, widgetsData[ i ] );
				}
			}
		}
		GoUp();
		UpdateReturnButtonVisibility();
	}

	protected override function UpdateDeviceWidgets( const widgetsData : ref< array< SDeviceWidgetPackage > > )
	{
		var i : Int32;
		var widget : inkWidget;
		var element : SBreadcrumbElementData;
		super.UpdateDeviceWidgets( widgetsData );
		m_currentlyActiveDevices.Clear();
		GetMainLayoutController().GetDevicesSlot().SetVisible( true );
		GetMainLayoutController().GetThumbnailListSlot().SetVisible( false );
		GetMainLayoutController().HideBackgroundIcon();
		for( i = 0; i < widgetsData.Size(); i += 1 )
		{
			if( !( IsOwner( widgetsData[ i ].ownerID ) ) )
			{
				m_currentlyActiveDevices.PushBack( widgetsData[ i ].ownerID );
			}
			widget = GetDeviceWidget( widgetsData[ i ] );
			if( widget == NULL )
			{
				CreateDeviceWidgetAsync( GetMainLayoutController().GetDevicesSlot(), widgetsData[ i ] );
			}
			else
			{
				InitializeDeviceWidget( widget, widgetsData[ i ] );
			}
		}
		element = GetCurrentBreadcrumbElement();
		if( element.elementName != "device" )
		{
			element.elementName = "device";
			GoDown( element );
		}
		UpdateReturnButtonVisibility();
	}

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

	protected override function Refresh( state : EDeviceStatus )
	{
		SetupWidgets();
		InitializeMainLayout();
		if( !( IsMainLayoutInitialized() ) )
		{
			return;
		}
		switch( state )
		{
			case EDeviceStatus.ON:
				TurnOn();
			break;
			case EDeviceStatus.OFF:
				TurnOff();
			break;
			case EDeviceStatus.UNPOWERED:
				TurnOff();
			break;
			case EDeviceStatus.DISABLED:
				TurnOff();
			break;
			default:
				break;
		}
		super.Refresh( state );
	}

	protected function RegisterReturnButtonCallback()
	{
		GetMainLayoutController().GetReturnButton().RegisterToCallback( 'OnRelease', this, 'OnReturnCallback' );
	}

	protected event OnReturnCallback( e : inkPointerEvent )
	{
		if( e.IsAction( 'click' ) )
		{
			GoUp();
			ResolveBreadcrumbLevel();
		}
	}

	protected override function ResolveBreadcrumbLevel()
	{
		var element : SBreadcrumbElementData;
		if( ( !( GetOwner().GetDevicePS().IsPlayerAuthorized() ) || GetOwner().HasActiveStaticHackingSkillcheck() ) || GetOwner().ShouldAlwaysUpdateDeviceWidgets() )
		{
			RequestDeviceWidgetsUpdate();
			return;
		}
		if( m_currentlyActiveDevices.Size() == 0 )
		{
			ClearBreadcrumbStack();
		}
		element = GetCurrentBreadcrumbElement();
		if( !( IsStringValid( element.elementName ) ) )
		{
			RequestThumbnailWidgetsUpdate();
			GetMainLayoutController().ShowBackgroundIcon();
		}
		else if( element.elementName == "device" )
		{
			RequestDeviceWidgetsUpdate( m_currentlyActiveDevices );
			GetMainLayoutController().HideBackgroundIcon();
		}
	}

	public override function UpdateBreadCrumbBar( const data : ref< SBreadCrumbUpdateData > )
	{
		var currentElement : SBreadcrumbElementData;
		currentElement = GetCurrentBreadcrumbElement();
		if( data.elementName != currentElement.elementName )
		{
			if( !( IsStringValid( data.elementName ) ) )
			{
				ClearBreadcrumbStack();
				ResolveBreadcrumbLevel();
			}
		}
	}

	public virtual function GetMainLayoutController() : TerminalMainLayoutWidgetController
	{
		return ( ( TerminalMainLayoutWidgetController )( m_mainLayout.GetController() ) );
	}

	protected function TurnOn()
	{
		m_mainLayout.SetVisible( true );
		ResolveBreadcrumbLevel();
	}

	protected function TurnOff()
	{
		ClearBreadcrumbStack();
		m_mainLayout.SetVisible( false );
	}

	protected function UpdateReturnButtonVisibility()
	{
		if( m_breadcrumbStack.Size() == 0 )
		{
			GetMainLayoutController().GetReturnButton().SetVisible( false );
		}
		else
		{
			GetMainLayoutController().GetReturnButton().SetVisible( true && m_buttonVisibility );
		}
	}

	private override function StartGlitchingScreen( glitchData : GlitchData )
	{
		var glitchVideoPath : ResRef;
		if( glitchData.state == EGlitchState.SUBLIMINAL_MESSAGE )
		{
			glitchVideoPath = GetOwner().GetBroadcastGlitchVideoPath();
		}
		else
		{
			glitchVideoPath = GetOwner().GetDefaultGlitchVideoPath();
		}
		if( ResRef.IsValid( glitchVideoPath ) )
		{
			m_mainDisplayWidget.SetVisible( true );
			m_mainLayout.SetVisible( false );
			StopVideo();
			PlayVideo( glitchVideoPath, true, '' );
		}
	}

	private override function StopGlitchingScreen()
	{
		StopVideo();
		m_mainDisplayWidget.SetVisible( false );
		m_mainLayout.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();
	}

}

