enum ScannerDetailTab
{
	Data = 0,
	Hacking = 1,
}

class scannerDetailsGameController extends inkHUDGameController
{
	private editable var m_scannerCountainer : inkCompoundRef;
	private editable var m_quickhackContainer : inkCompoundRef;
	private editable var m_cluesContainer : inkCompoundRef;
	private editable var m_toggleDescirptionHackPart : inkWidgetRef;
	private editable var m_kiroshiLogo : inkWidgetRef;
	private persistent var m_lastOpenTab : ScannerDetailTab;
	private var m_player : weak< GameObject >;
	private var m_scanningState : gameScanningState;
	private var m_scannedObjectType : ScannerObjectType;
	private var m_currentTab : ScannerDetailTab;
	default m_currentTab = ScannerDetailTab.Data;
	private var m_isQuickHackAble : Bool;
	private var m_isQuickHackPanelOpened : Bool;
	private var m_asyncSpawnRequests : array< weak< inkAsyncSpawnRequest > >;
	private var m_uiScannedObjectTypeChangedCallbackID : CallbackHandle;
	private var m_uiScanningStateChangedCallbackID : CallbackHandle;
	private var m_uiScannedObjectChangedCallbackID : CallbackHandle;
	private var m_uiQHDescriptionChangedCallbackID : CallbackHandle;
	private var m_uiQHPanelOpenedCallbackID : CallbackHandle;
	private var m_uiSystemIsInMenuCallbackID : CallbackHandle;
	private var m_introAnimProxy : inkAnimProxy;
	private var m_outroAnimProxy : inkAnimProxy;
	private var m_scannerToggleTabAnimProxy : inkAnimProxy;

	protected event OnInitialize()
	{
		var bbSys : BlackboardSystem;
		var uiBlackboard : weak< IBlackboard >;
		var uiQuickSlotsDataBB : weak< IBlackboard >;
		bbSys = GetBlackboardSystem();
		uiBlackboard = bbSys.Get( GetAllBlackboardDefs().UI_Scanner );
		uiQuickSlotsDataBB = bbSys.Get( GetAllBlackboardDefs().UI_QuickSlotsData );
		GetRootWidget().SetVisible( false );
		inkCompoundRef.SetVisible( m_scannerCountainer, false );
		AsyncSpawnFromLocal( inkCompoundRef.Get( m_quickhackContainer ), 'QuickHackDescription' );
		m_uiScanningStateChangedCallbackID = uiBlackboard.RegisterDelayedListenerVariant( GetAllBlackboardDefs().UI_Scanner.CurrentState, this, 'OnScanningStateChanged' );
		m_uiScannedObjectChangedCallbackID = uiBlackboard.RegisterDelayedListenerEntityID( GetAllBlackboardDefs().UI_Scanner.ScannedObject, this, 'OnScannedObjectChanged' );
		m_uiScannedObjectTypeChangedCallbackID = bbSys.Get( GetAllBlackboardDefs().UI_ScannerModules ).RegisterDelayedListenerInt( GetAllBlackboardDefs().UI_ScannerModules.ObjectType, this, 'OnScannedObjectTypeChanged' );
		m_uiQHDescriptionChangedCallbackID = uiQuickSlotsDataBB.RegisterDelayedListenerBool( GetAllBlackboardDefs().UI_QuickSlotsData.quickHackDescritpionVisible, this, 'OnQHDescriptionChanged' );
		m_uiQHPanelOpenedCallbackID = uiQuickSlotsDataBB.RegisterDelayedListenerBool( GetAllBlackboardDefs().UI_QuickSlotsData.quickhackPanelOpen, this, 'OnQHPanelOpened' );
		m_uiSystemIsInMenuCallbackID = bbSys.Get( GetAllBlackboardDefs().UI_System ).RegisterDelayedListenerBool( GetAllBlackboardDefs().UI_System.IsInMenu, this, 'OnMenuUpdate' );
		AsyncSpawnFromLocal( inkCompoundRef.Get( m_cluesContainer ), 'ScannerQuestEntries' );
	}

	protected event OnUnitialize()
	{
		var bbSys : BlackboardSystem;
		var uiBlackboard : weak< IBlackboard >;
		var uiScannerChunkBlackboard : weak< IBlackboard >;
		var uiQuickSlotsDataBB : weak< IBlackboard >;
		bbSys = GetBlackboardSystem();
		uiBlackboard = bbSys.Get( GetAllBlackboardDefs().UI_Scanner );
		uiScannerChunkBlackboard = bbSys.Get( GetAllBlackboardDefs().UI_ScannerModules );
		uiQuickSlotsDataBB = bbSys.Get( GetAllBlackboardDefs().UI_QuickSlotsData );
		if( m_uiScannedObjectTypeChangedCallbackID )
		{
			uiScannerChunkBlackboard.UnregisterDelayedListener( GetAllBlackboardDefs().UI_ScannerModules.ObjectType, m_uiScannedObjectTypeChangedCallbackID );
		}
		if( m_uiScannedObjectChangedCallbackID )
		{
			uiBlackboard.UnregisterDelayedListener( GetAllBlackboardDefs().UI_Scanner.ScannedObject, m_uiScannedObjectChangedCallbackID );
		}
		if( m_uiScanningStateChangedCallbackID )
		{
			uiBlackboard.UnregisterDelayedListener( GetAllBlackboardDefs().UI_Scanner.CurrentState, m_uiScanningStateChangedCallbackID );
		}
		if( m_uiQHDescriptionChangedCallbackID )
		{
			uiQuickSlotsDataBB.UnregisterDelayedListener( GetAllBlackboardDefs().UI_QuickSlotsData.quickHackDescritpionVisible, m_uiQHDescriptionChangedCallbackID );
		}
		if( m_uiQHPanelOpenedCallbackID )
		{
			uiQuickSlotsDataBB.UnregisterDelayedListener( GetAllBlackboardDefs().UI_QuickSlotsData.quickhackPanelOpen, m_uiQHPanelOpenedCallbackID );
		}
		if( m_uiSystemIsInMenuCallbackID )
		{
			bbSys.Get( GetAllBlackboardDefs().UI_System ).UnregisterDelayedListener( GetAllBlackboardDefs().UI_System.IsInMenu, m_uiSystemIsInMenuCallbackID );
		}
	}

	protected event OnPlayerAttach( player : GameObject )
	{
		m_player = player;
	}

	protected event OnScanningStateChanged( value : Variant )
	{
		var isRefreshingLayout : Bool;
		isRefreshingLayout = m_scanningState == gameScanningState.Default || m_scanningState == gameScanningState.Stopped;
		m_scanningState = ( ( gameScanningState )value );
		if( isRefreshingLayout )
		{
			RefreshLayout();
		}
	}

	protected event OnScannedObjectChanged( value : EntityID )
	{
		var scannedObject : GameObject;
		if( EntityID.IsDefined( value ) )
		{
			scannedObject = ( ( GameObject )( GameInstance.FindEntityByID( m_player.GetGame(), value ) ) );
			m_isQuickHackAble = scannedObject.IsQuickHackAble();
			ToggleQHTabVisibility();
			inkWidgetRef.SetVisible( m_kiroshiLogo, GameInstance.GetStatsSystem( m_player.GetGame() ).GetStatValue( m_player.GetEntityID(), gamedataStatType.HasLinkToBountySystem ) > 0.0 );
		}
		else
		{
			m_scannedObjectType = ScannerObjectType.INVALID;
			m_isQuickHackAble = false;
			PlayOutroAnimation();
		}
	}

	protected event OnScannedObjectTypeChanged( value : Int32 )
	{
		m_scannedObjectType = ( ( ScannerObjectType )( value ) );
		RefreshLayout();
	}

	protected event OnQHDescriptionChanged( value : Bool )
	{
		var isForceSkippingToggleAnimation : Bool;
		if( m_outroAnimProxy && m_outroAnimProxy.IsValid() )
		{
			return true;
		}
		if( m_introAnimProxy && m_introAnimProxy.IsValid() )
		{
			isForceSkippingToggleAnimation = true;
		}
		SetTab( ( ( value ) ? ( ScannerDetailTab.Hacking ) : ( ScannerDetailTab.Data ) ), isForceSkippingToggleAnimation );
	}

	protected event OnMenuUpdate( value : Bool )
	{
		if( ( !( value ) && m_player ) && m_isQuickHackPanelOpened )
		{
			GameInstance.GetDelaySystem( m_player.GetGame() ).DelayEventNextFrame( m_player, new RefreshQuickhackMenuEvent );
		}
	}

	protected event OnQHPanelOpened( value : Bool )
	{
		if( m_isQuickHackPanelOpened == value )
		{
			return true;
		}
		m_isQuickHackPanelOpened = value;
		if( ( m_outroAnimProxy && m_outroAnimProxy.IsValid() ) && !( value ) )
		{
			return true;
		}
		ToggleQHTabVisibility();
		if( ( m_introAnimProxy && m_introAnimProxy.IsValid() ) && value )
		{
			return true;
		}
		SetTab( ( ( m_isQuickHackAble && m_isQuickHackPanelOpened ) ? ( m_lastOpenTab ) : ( ScannerDetailTab.Data ) ) );
	}

	private function RefreshLayout()
	{
		var i : Int32;
		StopAnimations();
		if( HUDManager.GetActiveMode( m_player.GetGame() ) != ActiveMode.FOCUS )
		{
			PlayOutroAnimation();
		}
		if( ( m_scanningState == gameScanningState.Started || m_scanningState == gameScanningState.Complete ) || m_scanningState == gameScanningState.ShallowComplete )
		{
			GetRootWidget().SetVisible( false );
			for( i = 0; i < m_asyncSpawnRequests.Size(); i += 1 )
			{
				m_asyncSpawnRequests[ i ].Cancel();
			}
			m_asyncSpawnRequests.Clear();
			inkCompoundRef.RemoveAllChildren( m_scannerCountainer );
			switch( m_scannedObjectType )
			{
				case ScannerObjectType.PUPPET:
				{
					GetRootWidget().SetVisible( true );
					AsyncSpawnScannerModule( 'ScannerNPCHeaderWidget' );
					AsyncSpawnScannerModule( 'ScannerNPCBodyWidget' );
					AsyncSpawnScannerModule( 'ScannerBountySystemWidget' );
					AsyncSpawnScannerModule( 'ScannerRequirementsWidget' );
					AsyncSpawnScannerModule( 'ScannerAbilitiesWidget' );
					AsyncSpawnScannerModule( 'ScannerResistancesWidget' );
					AsyncSpawnScannerModule( 'ScannerDeviceDescriptionWidget' );
					break;
				}
				case ScannerObjectType.DEVICE:
				{
					GetRootWidget().SetVisible( true );
					AsyncSpawnScannerModule( 'ScannerDeviceHeaderWidget' );
					AsyncSpawnScannerModule( 'ScannerVulnerabilitiesWidget' );
					AsyncSpawnScannerModule( 'ScannerRequirementsWidget' );
					AsyncSpawnScannerModule( 'ScannerDeviceDescriptionWidget' );
					break;
				}
				case ScannerObjectType.VEHICLE:
				{
					GetRootWidget().SetVisible( true );
					AsyncSpawnScannerModule( 'ScannerVehicleBody' );
					AsyncSpawnScannerModule( 'ScannerDeviceDescriptionWidget' );
					break;
				}
				case ScannerObjectType.GENERIC:
				{
					GetRootWidget().SetVisible( true );
					AsyncSpawnScannerModule( 'ScannerDeviceHeaderWidget' );
					AsyncSpawnScannerModule( 'ScannerDeviceDescriptionWidget' );
					break;
				}
				default:
				{
					return;
				}
			}
			SetTab( ( ( m_isQuickHackAble && m_isQuickHackPanelOpened ) ? ( m_lastOpenTab ) : ( ScannerDetailTab.Data ) ), true );
			inkCompoundRef.SetVisible( m_scannerCountainer, !( m_isQuickHackAble ) );
			m_introAnimProxy = PlayLibraryAnimation( 'intro' );
			m_introAnimProxy.RegisterToCallback( inkanimEventType.OnFinish, this, 'OnScannerDetailsShown' );
		}
		else if( m_scanningState == gameScanningState.Default || m_scanningState == gameScanningState.Stopped )
		{
			PlayOutroAnimation();
		}
	}

	private function AsyncSpawnScannerModule( scannerWidgetLibraryName : CName )
	{
		m_asyncSpawnRequests.PushBack( AsyncSpawnFromLocal( inkCompoundRef.Get( m_scannerCountainer ), scannerWidgetLibraryName ) );
	}

	private function StopAnimations()
	{
		if( m_introAnimProxy && m_introAnimProxy.IsValid() )
		{
			m_introAnimProxy.UnregisterFromAllCallbacks( inkanimEventType.OnFinish );
			m_introAnimProxy.Stop();
			m_introAnimProxy = NULL;
		}
		if( m_outroAnimProxy && m_outroAnimProxy.IsValid() )
		{
			m_outroAnimProxy.UnregisterFromAllCallbacks( inkanimEventType.OnFinish );
			m_outroAnimProxy.Stop();
			m_outroAnimProxy = NULL;
		}
	}

	private function PlayOutroAnimation()
	{
		var progress : Float;
		if( m_introAnimProxy && m_introAnimProxy.IsValid() )
		{
			progress = 1.0 - m_introAnimProxy.GetProgression();
			m_introAnimProxy.UnregisterFromAllCallbacks( inkanimEventType.OnFinish );
			m_introAnimProxy.Stop();
			m_introAnimProxy = NULL;
		}
		if( m_outroAnimProxy && m_outroAnimProxy.IsValid() )
		{
			return;
		}
		m_outroAnimProxy = PlayLibraryAnimation( 'outro' );
		m_outroAnimProxy.RegisterToCallback( inkanimEventType.OnFinish, this, 'OnScannerDetailsHidden' );
		if( progress > 0.0 )
		{
			m_outroAnimProxy.SetNormalizedPosition( progress, true );
		}
	}

	private function SetTab( scannerDetailTab : ScannerDetailTab, optional isForceSkippingToggleAnimation : Bool )
	{
		var progress : Float;
		var animation : CName;
		if( m_currentTab == scannerDetailTab )
		{
			return;
		}
		m_currentTab = scannerDetailTab;
		if( m_scannerToggleTabAnimProxy && m_scannerToggleTabAnimProxy.IsValid() )
		{
			progress = 1.0 - m_scannerToggleTabAnimProxy.GetProgression();
			m_scannerToggleTabAnimProxy.GotoEndAndStop();
		}
		switch( m_currentTab )
		{
			case ScannerDetailTab.Data:
			{
				animation = 'hack_to_scan';
				break;
			}
			case ScannerDetailTab.Hacking:
			{
				animation = 'scan_to_hack';
				break;
			}
		}
		m_scannerToggleTabAnimProxy = PlayLibraryAnimation( animation );
		if( isForceSkippingToggleAnimation )
		{
			m_scannerToggleTabAnimProxy.GotoEndAndStop();
		}
		else
		{
			if( progress > 0.0 )
			{
				m_scannerToggleTabAnimProxy.SetNormalizedPosition( progress, true );
			}
		}
		if( m_isQuickHackAble && m_isQuickHackPanelOpened )
		{
			m_lastOpenTab = m_currentTab;
		}
	}

	private function ToggleQHTabVisibility()
	{
		inkWidgetRef.SetVisible( m_toggleDescirptionHackPart, m_isQuickHackAble && m_isQuickHackPanelOpened );
	}

	protected event OnScannerDetailsShown( animationProxy : inkAnimProxy )
	{
		m_introAnimProxy = NULL;
		inkCompoundRef.SetVisible( m_scannerCountainer, true );
		SetTab( ( ( m_isQuickHackAble && m_isQuickHackPanelOpened ) ? ( m_lastOpenTab ) : ( ScannerDetailTab.Data ) ), true );
	}

	protected event OnScannerDetailsHidden( animationProxy : inkAnimProxy )
	{
		m_outroAnimProxy = NULL;
		inkCompoundRef.SetVisible( m_scannerCountainer, false );
		inkWidgetRef.SetVisible( m_toggleDescirptionHackPart, false );
	}

}

