class TarotMainGameController extends gameuiMenuGameController
{
	protected editable var m_buttonHintsManagerRef : inkWidgetRef;
	private editable var m_TooltipsManagerRef : inkWidgetRef;
	private editable var m_list : inkCompoundRef;
	protected var m_journalManager : weak< JournalManager >;
	private var m_buttonHintsController : weak< ButtonHints >;
	private var m_TooltipsManager : weak< gameuiTooltipsManager >;
	private var m_selectedTarotCard : weak< tarotCardLogicController >;
	private var m_fullscreenPreviewController : weak< TarotPreviewGameController >;
	private var m_menuEventDispatcher : weak< inkMenuEventDispatcher >;
	private var m_tarotPreviewPopupToken : inkGameNotificationToken;
	private var m_afterCloseRequest : Bool;
	private var m_numberOfCardsInTarotDeck : Int32;
	private var m_baseCards : Int32;
	default m_baseCards = 22;
	private var m_ep1Cards : Int32;
	default m_ep1Cards = 26;

	protected event OnInitialize()
	{
		m_buttonHintsController = ( ( ButtonHints )( SpawnFromExternal( inkWidgetRef.Get( m_buttonHintsManagerRef ), R"base\gameplay\gui\common\buttonhints.inkwidget", 'Root' ).GetController() ) );
		m_buttonHintsController.AddButtonHint( 'back', GetLocalizedText( "Common-Access-Close" ) );
		m_journalManager = GameInstance.GetJournalManager( ( ( GameObject )( GetPlayerControlledObject() ) ).GetGame() );
		m_journalManager.RegisterScriptCallback( this, 'OnJournalReady', gameJournalListenerType.State );
		inkCompoundRef.RemoveAllChildren( m_list );
		PrepareTooltips();
		PushCodexData();
		PlayLibraryAnimation( 'panel_intro' );
	}

	protected event OnUninitalize()
	{
		m_menuEventDispatcher.UnregisterFromEvent( 'OnBack', this, 'OnBack' );
	}

	protected event OnSetMenuEventDispatcher( menuEventDispatcher : weak< inkMenuEventDispatcher > )
	{
		m_menuEventDispatcher = menuEventDispatcher;
		m_menuEventDispatcher.RegisterToEvent( 'OnBack', this, 'OnBack' );
	}

	protected event OnTarotCardPreviewShowRequest( evt : TarotCardPreviewPopupEvent )
	{
		m_tarotPreviewPopupToken = ShowGameNotification( evt.m_data );
		m_tarotPreviewPopupToken.RegisterListener( this, 'OnTarotPreviewPopup' );
	}

	protected event OnTarotPreviewPopup( data : inkGameNotificationData )
	{
		m_tarotPreviewPopupToken = NULL;
	}

	protected event OnBack( userData : IScriptable )
	{
		if( !( m_afterCloseRequest ) && !( StatusEffectSystem.ObjectHasStatusEffectWithTag( GetPlayerControlledObject(), 'LockInHubMenu' ) ) )
		{
			super.OnBack( userData );
		}
		else
		{
			m_afterCloseRequest = false;
		}
	}

	protected event OnJournalReady( entryHash : Uint32, className : CName, notifyOption : JournalNotifyOption, changeType : JournalChangeType )
	{
		var entryCodex : JournalTarotGroup;
		entryCodex = ( ( JournalTarotGroup )( m_journalManager.GetEntry( entryHash ) ) );
		if( entryCodex != NULL )
		{
			PushCodexData();
		}
	}

	private function PushCodexData()
	{
		var journalContext : JournalRequestContext;
		var groupEntries : array< weak< JournalEntry > >;
		var tarotEntries : array< weak< JournalEntry > >;
		var entry : weak< JournalTarot >;
		var dataArray : array< TarotCardData >;
		var sortedArray : array< TarotCardData >;
		var data : TarotCardData;
		var i, j, f : Int32;
		var cardFound : Bool;
		journalContext.stateFilter.active = true;
		m_journalManager.GetTarots( journalContext, groupEntries );
		for( i = 0; i < groupEntries.Size(); i += 1 )
		{
			tarotEntries.Clear();
			m_journalManager.GetChildren( groupEntries[ i ], journalContext.stateFilter, tarotEntries );
			for( f = 0; f < tarotEntries.Size(); f += 1 )
			{
				entry = ( ( JournalTarot )( tarotEntries[ f ] ) );
				data.empty = false;
				data.index = entry.GetIndex();
				data.imagePath = entry.GetImagePart();
				data.label = entry.GetName();
				data.desc = entry.GetDescription();
				data.isEp1 = m_journalManager.IsEp1Entry( entry );
				dataArray.PushBack( data );
			}
		}
		m_numberOfCardsInTarotDeck = ( ( IsEP1() ) ? ( m_ep1Cards ) : ( m_baseCards ) );
		for( i = 0; i < m_numberOfCardsInTarotDeck; i += 1 )
		{
			cardFound = false;
			for( j = 0; j < dataArray.Size(); j += 1 )
			{
				if( dataArray[ j ].index == i )
				{
					sortedArray.PushBack( dataArray[ j ] );
					cardFound = true;
					break;
				}
			}
			if( !( cardFound ) )
			{
				data.empty = true;
				data.index = i;
				data.isEp1 = i >= 22;
				data.imagePath = '';
				data.label = "";
				data.desc = "";
				sortedArray.PushBack( data );
			}
		}
		CreateTarotCards( sortedArray );
	}

	protected event OnUninitialize()
	{
		m_journalManager.UnregisterScriptCallback( this, 'OnJournalReady' );
	}

	private function CreateTarotCards( const data : ref< array< TarotCardData > > )
	{
		var i : Int32;
		var tarotCard : weak< tarotCardLogicController >;
		for( i = 0; i < data.Size(); i += 1 )
		{
			tarotCard = ( ( tarotCardLogicController )( SpawnFromLocal( inkCompoundRef.Get( m_list ), 'tarotCard' ).GetController() ) );
			tarotCard.SetupData( data[ i ] );
			tarotCard.RegisterToCallback( 'OnRelease', this, 'OnElementClick' );
			tarotCard.RegisterToCallback( 'OnHoverOver', this, 'OnElementHoverOver' );
			tarotCard.RegisterToCallback( 'OnHoverOut', this, 'OnElementHoverOut' );
		}
	}

	protected event OnElementClick( evt : inkPointerEvent )
	{
		var controller : weak< tarotCardLogicController >;
		var data : TarotCardData;
		var previewEvent : TarotCardPreviewPopupEvent;
		if( evt.IsAction( 'click' ) )
		{
			controller = GetTarotCardControllerFromTarget( evt );
			data = controller.GetData();
			if( !( data.empty ) )
			{
				previewEvent = new TarotCardPreviewPopupEvent;
				previewEvent.m_data = new TarotCardPreviewData;
				previewEvent.m_data.cardData = data;
				previewEvent.m_data.queueName = 'modal_popup';
				previewEvent.m_data.notificationName = 'base\gameplay\gui\widgets\notifications\tarot_card_preview.inkwidget';
				previewEvent.m_data.isBlocking = true;
				previewEvent.m_data.useCursor = true;
				QueueBroadcastEvent( previewEvent );
				HideTooltips();
				m_selectedTarotCard.HoverOut();
			}
		}
	}

	protected event OnElementHoverOver( evt : inkPointerEvent )
	{
		var controller : weak< tarotCardLogicController >;
		var data : TarotCardData;
		controller = GetTarotCardControllerFromTarget( evt );
		data = controller.GetData();
		if( !( data.empty ) )
		{
			RequestTooltip( controller.GetData() );
		}
		m_selectedTarotCard = controller;
		m_selectedTarotCard.HoverOver();
	}

	protected event OnElementHoverOut( evt : inkPointerEvent )
	{
		HideTooltips();
		m_selectedTarotCard.HoverOut();
	}

	private function PrepareTooltips()
	{
		m_TooltipsManager = ( ( gameuiTooltipsManager )( inkWidgetRef.GetControllerByType( m_TooltipsManagerRef, 'gameuiTooltipsManager' ) ) );
		m_TooltipsManager.Setup( ETooltipsStyle.Menus );
	}

	private function RequestTooltip( const data : ref< TarotCardData > )
	{
		var toolTipData : MessageTooltipData;
		toolTipData = new MessageTooltipData;
		toolTipData.Title = data.label;
		toolTipData.Description = data.desc;
		m_TooltipsManager.ShowTooltip( toolTipData );
	}

	private function HideTooltips()
	{
		m_TooltipsManager.HideTooltips();
	}

	private function GetTarotCardControllerFromTarget( evt : inkPointerEvent ) : tarotCardLogicController
	{
		var widget : inkWidget;
		var controller : weak< tarotCardLogicController >;
		widget = evt.GetCurrentTarget();
		controller = ( ( tarotCardLogicController )( widget.GetController() ) );
		return controller;
	}

}

class tarotCardLogicController extends inkLogicController
{
	private editable var m_image : inkImageRef;
	private editable var m_highlight : inkWidgetRef;
	editable var m_ep1Icon : inkWidgetRef;
	private var m_data : TarotCardData;

	protected event OnInitialize()
	{
		inkWidgetRef.SetVisible( m_highlight, false );
	}

	public function SetupData( const data : ref< TarotCardData > )
	{
		m_data = data;
		if( !( m_data.empty ) )
		{
			InkImageUtils.RequestSetImage( this, m_image, "UIIcon." + NameToString( m_data.imagePath ) );
		}
		else
		{
			InkImageUtils.RequestSetImage( this, m_image, T"UIIcon.TarotCard_Reverse" );
		}
		if( data.isEp1 )
		{
			inkWidgetRef.SetVisible( m_ep1Icon, true );
		}
	}

	public function HoverOver()
	{
		inkWidgetRef.SetVisible( m_highlight, true );
	}

	public function HoverOut()
	{
		inkWidgetRef.SetVisible( m_highlight, false );
	}

	public function GetData() : TarotCardData
	{
		return m_data;
	}

}

struct TarotCardData
{
	var empty : Bool;
	var index : Int32;
	var imagePath : CName;
	var label : String;
	var desc : String;
	var isEp1 : Bool;
}

