class questLogV2GameController extends gameuiMenuGameController
{
	private editable var m_QuestDetailsRef : inkWidgetRef;
	private editable var m_QuestDetailsHeader : inkWidgetRef;
	private editable var m_OptinalObjectivesGroupRef : inkWidgetRef;
	private editable var m_CompletedObjectivesGroupRef : inkWidgetRef;
	private editable var m_QuestListRef : inkCompoundRef;
	private editable var m_ObjectivesListRef : inkCompoundRef;
	private editable var m_OptinalObjectivesListRef : inkCompoundRef;
	private editable var m_CompletedObjectivesListRef : inkCompoundRef;
	private editable var m_QuestTitleRef : inkTextRef;
	private editable var m_QuestDescriptionRef : inkTextRef;
	private editable var m_recommendedLevel : inkTextRef;
	private editable var m_rewardsList : inkCompoundRef;
	private editable var m_codexLinksList : inkCompoundRef;
	private editable var m_CodexEntryParent : inkCompoundRef;
	private editable var m_CodexButtonRef : inkCompoundRef;
	private editable var m_buttonHintsManagerRef : inkWidgetRef;
	private editable var m_codexLibraryPath : ResRef;
	private editable var m_ObjectiveViewName : CName;
	private editable var m_QuestGroupName : CName;
	private var m_JournalWrapper : JournalWrapper;
	private var m_CurrentQuestData : QuestDataWrapper;
	private var m_ObjectiveItems : array< weak< ObjectiveController > >;
	private var m_QuestLists : array< weak< QuestListController > >;
	private var m_CodexLinksListController : weak< ListController >;
	private var m_codexButton : weak< inkButtonController >;
	private var m_menuEventDispatcher : weak< inkMenuEventDispatcher >;
	private var m_buttonHintsController : weak< ButtonHints >;

	protected event OnInitialize()
	{
		var ownerEntity : weak< GameObject >;
		var gameInstance : GameInstance;
		var m_QuestDetails : weak< inkWidget >;
		var m_QuestList : weak< inkWidget >;
		ownerEntity = ( ( GameObject )( GetPlayerControlledObject() ) );
		gameInstance = ( ( GameInstance )( ownerEntity.GetGame() ) );
		m_QuestDetails = inkCompoundRef.Get( m_ObjectivesListRef );
		m_QuestList = inkCompoundRef.Get( m_QuestListRef );
		m_QuestList.RegisterToCallback( 'OnHoverOver', this, 'OnQuestHover' );
		m_QuestDetails.RegisterToCallback( 'OnHoverOver', this, 'OnObjectiveHover' );
		m_QuestList.RegisterToCallback( 'OnHoverOut', this, 'OnHoverOut' );
		m_QuestDetails.RegisterToCallback( 'OnHoverOut', this, 'OnHoverOut' );
		m_JournalWrapper = new JournalWrapper;
		m_JournalWrapper.Init( gameInstance );
		m_CodexLinksListController = ( ( ListController )( inkCompoundRef.GetControllerByType( m_codexLinksList, 'inkListController' ) ) );
		m_CodexLinksListController.RegisterToCallback( 'OnItemActivated', this, 'OnCodexLinkClicked' );
		m_codexButton = ( ( inkButtonController )( inkCompoundRef.GetController( m_CodexButtonRef ) ) );
		m_codexButton.RegisterToCallback( 'OnRelease', this, 'OnCodexOpenButtonClicked' );
		inkCompoundRef.SetVisible( m_CodexButtonRef, false );
		m_buttonHintsController = ( ( ButtonHints )( SpawnFromExternal( inkWidgetRef.Get( m_buttonHintsManagerRef ), R"base\gameplay\gui\common\buttonhints.inkwidget", 'Root' ).GetController() ) );
		m_buttonHintsController.AddButtonHint( EInputKey.IK_Pad_B_CIRCLE, GetLocalizedText( "Common-Access-Close" ) );
		inkCompoundRef.RemoveAllChildren( m_QuestListRef );
		CreateQuestGroup( gameJournalQuestType.MainQuest, "MAIN QUESTS" );
		CreateQuestGroup( gameJournalQuestType.SideQuest, "SIDE QUESTS" );
		CreateQuestGroup( gameJournalQuestType.StreetStory, "STREET STORIES" );
		CreateQuestGroup( gameJournalQuestType.Contract, "CONTRACTS" );
		CreateQuestGroup( gameJournalQuestType.VehicleQuest, "VEHICLES" );
		CreateQuestGroup( gameJournalQuestType.ApartmentQuest, "APARTMENTS" );
		CreateQuestGroup( gameJournalQuestType.CourierQuest, "COURIERS" );
		RefreshUI();
	}

	protected event OnPlayerAttach( playerPuppet : GameObject )
	{
		m_JournalWrapper = new JournalWrapper;
		m_JournalWrapper.Init( playerPuppet.GetGame() );
		RefreshUI();
	}

	private function RefreshUI()
	{
		var ownerEntity : weak< GameObject >;
		var gameInstance : GameInstance;
		ownerEntity = ( ( GameObject )( GetPlayerControlledObject() ) );
		gameInstance = ( ( GameInstance )( ownerEntity.GetGame() ) );
		m_JournalWrapper = new JournalWrapper;
		m_JournalWrapper.Init( gameInstance );
		BuildQuestList();
		BuildQuestDetails();
	}

	private function CreateQuestGroup( questType : gameJournalQuestType, const questLOCKey : ref< String > )
	{
		var currList : weak< QuestListController >;
		currList = ( ( QuestListController )( SpawnFromLocal( inkCompoundRef.Get( m_QuestListRef ), m_QuestGroupName ).GetControllerByType( 'QuestListController' ) ) );
		currList.Setup( questType, questLOCKey );
		currList.RegisterToCallback( 'OnActiveQuestChanged', this, 'OnActiveQuestChanged' );
		m_QuestLists.PushBack( currList );
	}

	private function BuildQuestList()
	{
		var i, limit, j, limitJ : Int32;
		var listQuests : array< weak< JournalEntry > >;
		var currQuest : weak< JournalQuest >;
		var questData : QuestDataWrapper;
		var currEntry : weak< JournalEntry >;
		m_JournalWrapper.GetQuests( listQuests );
		for( i = 0, limit = m_QuestLists.Size(); i < limit; i += 1 )
		{
			m_QuestLists[ i ].Clear();
		}
		for( i = 0, limit = listQuests.Size(); i < limit; i += 1 )
		{
			currQuest = ( ( JournalQuest )( listQuests[ i ] ) );
			if( currQuest )
			{
				questData = m_JournalWrapper.BuildQuestData( currQuest );
				for( j = 0, limitJ = m_QuestLists.Size(); j < limitJ; j += 1 )
				{
					if( m_QuestLists[ j ].CanAddQuest( questData ) )
					{
						if( !( m_CurrentQuestData ) )
						{
							m_CurrentQuestData = questData;
							currEntry = ( ( JournalEntry )( m_CurrentQuestData.GetQuest() ) );
							m_JournalWrapper.SetVisited( currEntry );
							questData.UpdateIsNew( false );
						}
						m_QuestLists[ j ].AddQuest( questData, m_CurrentQuestData.GetId() == questData.GetId() );
						break;
					}
				}
			}
		}
	}

	private function BuildQuestDetails()
	{
		var i : Int32;
		var linksData : array< weak< JournalEntry > >;
		var linksScriptableData : array< IScriptable >;
		if( m_CurrentQuestData )
		{
			CreateQuestObjectives( m_CurrentQuestData );
			inkTextRef.SetText( m_QuestTitleRef, m_CurrentQuestData.GetTitle() );
			linksData = m_CurrentQuestData.GetLinks();
			inkTextRef.SetText( m_QuestDescriptionRef, m_CurrentQuestData.GetDescription() );
			m_CodexLinksListController.Clear();
			for( i = 0; i < linksData.Size(); i += 1 )
			{
				linksScriptableData.PushBack( linksData[ i ] );
			}
			m_CodexLinksListController.PushDataList( linksScriptableData, true );
			inkTextRef.SetText( m_recommendedLevel, ( ( String )( m_CurrentQuestData.GetLevel() ) ) );
		}
		else
		{
			inkTextRef.SetText( m_QuestTitleRef, GetLocalizedText( "LocKey#22226" ) );
			inkTextRef.SetText( m_QuestDescriptionRef, "" );
			inkTextRef.SetText( m_recommendedLevel, "" );
			m_CodexLinksListController.Clear();
			for( i = 0; i < m_ObjectiveItems.Size(); i += 1 )
			{
				RemoveQuestObjective( i );
			}
		}
	}

	private function CreateQuestObjectives( currQuestData : QuestDataWrapper )
	{
		var questObjectives : array< QuestObjectiveWrapper >;
		var i, limit : Int32;
		var targetParent : weak< inkCompoundWidget >;
		var journalManager : weak< JournalManager >;
		journalManager = m_JournalWrapper.GetJournalManager();
		questObjectives = currQuestData.GetObjectives();
		for( i = 0, limit = Max( questObjectives.Size(), m_ObjectiveItems.Size() ); i < limit; i += 1 )
		{
			if( i >= m_ObjectiveItems.Size() )
			{
				if( questObjectives[ i ].IsActive() )
				{
					AddQuestObjective();
				}
			}
			if( ( i >= questObjectives.Size() ) || !( questObjectives[ i ].IsActive() ) )
			{
				RemoveQuestObjective( i );
				continue;
			}
			if( questObjectives[ i ].IsActive() )
			{
				m_ObjectiveItems[ i ].Setup( questObjectives[ i ], journalManager.GetIsObjectiveOptional( questObjectives[ i ].GetQuestObjective() ) );
				if( !( questObjectives[ i ].IsActive() ) )
				{
					targetParent = ( ( inkCompoundWidget )( inkCompoundRef.Get( m_ObjectivesListRef ) ) );
				}
				else if( journalManager.GetIsObjectiveOptional( questObjectives[ i ].GetQuestObjective() ) )
				{
					targetParent = ( ( inkCompoundWidget )( inkCompoundRef.Get( m_ObjectivesListRef ) ) );
				}
				else
				{
					targetParent = ( ( inkCompoundWidget )( inkCompoundRef.Get( m_ObjectivesListRef ) ) );
				}
				m_ObjectiveItems[ i ].Reparent( targetParent );
			}
		}
		inkWidgetRef.SetVisible( m_OptinalObjectivesGroupRef, inkCompoundRef.GetNumChildren( m_OptinalObjectivesListRef ) > 0 );
		inkWidgetRef.SetVisible( m_CompletedObjectivesGroupRef, inkCompoundRef.GetNumChildren( m_CompletedObjectivesListRef ) > 0 );
	}

	private function RemoveQuestObjective( index : Int32 )
	{
		m_ObjectiveItems[ index ].GetRootWidget().SetVisible( false );
		m_ObjectiveItems[ index ].Reparent( GetRootCompoundWidget() );
	}

	private function AddQuestObjective()
	{
		var currObjective : weak< ObjectiveController >;
		currObjective = ( ( ObjectiveController )( SpawnFromLocal( GetRootWidget(), m_ObjectiveViewName ).GetControllerByType( 'ObjectiveController' ) ) );
		currObjective.RegisterToCallback( 'OnTrackingRequest', this, 'OnTrackingRequest' );
		currObjective.GetRootWidget().SetVisible( false );
		m_ObjectiveItems.PushBack( currObjective );
	}

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

	protected event OnBack( userData : IScriptable )
	{
		if( !( StatusEffectSystem.ObjectHasStatusEffectWithTag( GetPlayerControlledObject(), 'LockInHubMenu' ) ) )
		{
			m_menuEventDispatcher.SpawnEvent( 'OnCloseHubMenu' );
		}
	}

	protected event OnUninitialize()
	{
		m_codexButton.UnregisterFromCallback( 'OnRelease', this, 'OnCodexOpenButtonClicked' );
		m_menuEventDispatcher.UnregisterFromEvent( 'OnBack', this, 'OnBack' );
	}

	protected event OnActiveQuestChanged( widget : weak< inkWidget > )
	{
		var currLogic : weak< QuestListController >;
		var questData : weak< JournalEntry >;
		currLogic = ( ( QuestListController )( widget.GetControllerByType( 'QuestListController' ) ) );
		if( currLogic )
		{
			m_CurrentQuestData = currLogic.GetLastQuestData();
			questData = ( ( JournalEntry )( m_CurrentQuestData.GetQuest() ) );
			m_JournalWrapper.SetVisited( questData );
			RefreshUI();
		}
	}

	protected event OnTrackingRequestEvent( evt : QuestTrackingEvent )
	{
		m_JournalWrapper.SetTracking( evt.m_journalEntry );
		RefreshUI();
	}

	protected event OnTrackingRequest( widget : weak< inkWidget > )
	{
		var currObjective : weak< ObjectiveController >;
		currObjective = ( ( ObjectiveController )( widget.GetControllerByType( 'ObjectiveController' ) ) );
		m_JournalWrapper.SetTracking( currObjective.GetToTrack().GetQuestObjective() );
		RefreshUI();
		currObjective.SetState( 'Tracked' );
	}

	protected event OnQuestHover( evt : inkPointerEvent )
	{
		m_buttonHintsController.ClearButtonHints();
		m_buttonHintsController.AddButtonHint( EInputKey.IK_Pad_X_SQUARE, GetLocalizedText( "UI-UserActions-Select" ) );
		m_buttonHintsController.AddButtonHint( EInputKey.IK_Pad_Y_TRIANGLE, GetLocalizedText( "UI-UserActions-TrackObjective" ) );
		m_buttonHintsController.AddButtonHint( EInputKey.IK_Pad_B_CIRCLE, GetLocalizedText( "Common-Access-Close" ) );
	}

	protected event OnObjectiveHover( evt : inkPointerEvent )
	{
		m_buttonHintsController.ClearButtonHints();
		m_buttonHintsController.AddButtonHint( EInputKey.IK_Pad_X_SQUARE, GetLocalizedText( "UI-UserActions-TrackObjective" ) );
		m_buttonHintsController.AddButtonHint( EInputKey.IK_Pad_B_CIRCLE, GetLocalizedText( "Common-Access-Close" ) );
	}

	protected event OnHoverOut( evt : inkPointerEvent )
	{
		m_buttonHintsController.ClearButtonHints();
		m_buttonHintsController.AddButtonHint( EInputKey.IK_Pad_B_CIRCLE, GetLocalizedText( "Common-Access-Close" ) );
	}

	protected event OnCodexLinkClicked( index : Int32, target : ListItemController )
	{
		OpenEntry( ( ( JournalCodexEntry )( target.GetData() ) ) );
	}

	protected event OnCodexOpenButtonClicked( e : inkPointerEvent ) {}

	private function OpenEntry( entry : weak< JournalCodexEntry > )
	{
		inkCompoundRef.SetVisible( m_CodexButtonRef, true );
	}

}

class CodexLinkQuestLog extends CodexImageButton
{

	protected event OnInitialize()
	{
		RegisterToCallback( 'OnDataChanged', this, 'OnDataChanged' );
		super.OnInitialize();
	}

	protected event OnDataChanged( value : IScriptable )
	{
		var data : weak< JournalCodexEntry >;
		data = ( ( JournalCodexEntry )( value ) );
		if( data )
		{
			inkTextRef.SetText( m_labelPathRef, data.GetTitle() );
		}
		else
		{
			inkTextRef.SetText( m_labelPathRef, "### not found" );
		}
	}

}

