abstract class QuestLogUtils
{

	public static function GetFixerData( journalManager : JournalManager, firstObjective : weak< JournalQuestObjective > ) : TweakDBID
	{
		var codexLink : weak< JournalQuestCodexLink >;
		var childEntries : array< weak< JournalEntry > >;
		var childEntry : weak< JournalEntry >;
		var i, size : Int32;
		var unpackFilter : JournalRequestStateFilter;
		var replacementEntry : weak< JournalCodexEntry >;
		var currentType : CodexCategoryType;
		var currentCategory : weak< JournalCodexCategory >;
		var currentGroup : weak< JournalCodexGroup >;
		var journalCodexEntry : JournalCodexEntry;
		var id : TweakDBID;
		unpackFilter.active = true;
		unpackFilter.inactive = true;
		QuestLogUtils.UnpackRecursiveWithFilter( journalManager, firstObjective, unpackFilter, childEntries, true );
		size = childEntries.Size();
		for( i = 0; i < size; i += 1 )
		{
			codexLink = ( ( JournalQuestCodexLink )( childEntries[ i ] ) );
			if( codexLink )
			{
				childEntry = ( ( JournalEntry )( journalManager.GetEntry( codexLink.GetLinkPathHash() ) ) );
				if( ( ( JournalCodexEntry )( childEntry ) ) )
				{
					currentGroup = ( ( JournalCodexGroup )( journalManager.GetParentEntry( childEntry ) ) );
					currentCategory = ( ( JournalCodexCategory )( journalManager.GetParentEntry( currentGroup ) ) );
					currentType = CodexUtils.GetCategoryTypeFromId( currentCategory.GetId() );
					if( currentType == CodexCategoryType.Characters && currentGroup.GetId() == "fixers" )
					{
						replacementEntry = CodexUtils.GetCodexReplacementRecord( journalManager, childEntry );
						if( replacementEntry )
						{
							childEntry = replacementEntry;
						}
						journalCodexEntry = ( ( JournalCodexEntry )( childEntry ) );
						return journalCodexEntry.GetLinkImageID();
					}
				}
			}
		}
		return id;
	}

	public static function GetDefaultFilter() : JournalRequestStateFilter
	{
		var contextFilter : JournalRequestStateFilter;
		contextFilter.active = true;
		contextFilter.inactive = true;
		contextFilter.succeeded = false;
		contextFilter.failed = false;
		return contextFilter;
	}

	public static function GetObjectiveFilter() : JournalRequestStateFilter
	{
		var contextFilter : JournalRequestStateFilter;
		contextFilter.active = false;
		contextFilter.inactive = true;
		contextFilter.succeeded = false;
		contextFilter.failed = false;
		return contextFilter;
	}

	public static function GetSuccessFilter() : JournalRequestStateFilter
	{
		var contextFilter : JournalRequestStateFilter;
		contextFilter.active = false;
		contextFilter.inactive = false;
		contextFilter.succeeded = true;
		contextFilter.failed = false;
		return contextFilter;
	}

	public static function GetFailedFilter() : JournalRequestStateFilter
	{
		var contextFilter : JournalRequestStateFilter;
		contextFilter.active = false;
		contextFilter.inactive = false;
		contextFilter.succeeded = false;
		contextFilter.failed = true;
		return contextFilter;
	}

	public static function UnpackRecursiveWithFilter( journalManager : JournalManager, entry : weak< JournalContainerEntry >, filter : JournalRequestStateFilter, result : ref< array< weak< JournalEntry > > >, optional includeInactive : Bool )
	{
		var i : Int32;
		var containerEntry : JournalContainerEntry;
		var childEntries : array< weak< JournalEntry > >;
		var currentEntry : weak< JournalEntry >;
		childEntries = Unpack( journalManager, entry, filter );
		for( i = 0; i < childEntries.Size(); i += 1 )
		{
			currentEntry = childEntries[ i ];
			if( !( includeInactive ) && ( journalManager.GetEntryState( currentEntry ) == gameJournalEntryState.Inactive && ( ( ( JournalQuestMapPinBase )( currentEntry ) ) == NULL ) ) )
			{
				continue;
			}
			result.PushBack( currentEntry );
			containerEntry = ( ( JournalContainerEntry )( currentEntry ) );
			if( containerEntry )
			{
				if( ( ( JournalQuestObjective )( containerEntry ) ) )
				{
					UnpackRecursiveWithFilter( journalManager, containerEntry, GetDefaultFilter(), result, includeInactive );
					UnpackRecursiveWithFilter( journalManager, containerEntry, GetObjectiveFilter(), result, includeInactive );
				}
				else
				{
					UnpackRecursiveWithFilter( journalManager, containerEntry, filter, result, includeInactive );
				}
			}
		}
	}

	public static function UnpackRecursive( journalManager : JournalManager, entry : weak< JournalContainerEntry >, result : ref< array< weak< JournalEntry > > > )
	{
		UnpackRecursiveWithFilter( journalManager, entry, GetDefaultFilter(), result );
	}

	public static function Unpack( journalManager : JournalManager, entry : weak< JournalContainerEntry >, filter : JournalRequestStateFilter ) : array< weak< JournalEntry > >
	{
		var childEntries : array< weak< JournalEntry > >;
		journalManager.GetChildren( entry, filter, childEntries );
		return childEntries;
	}

	public static function GetDescriptions( journalManager : JournalManager, entry : weak< JournalContainerEntry > ) : array< weak< JournalQuestDescription > >
	{
		var contextFilter : JournalRequestStateFilter;
		var objects : array< weak< JournalEntry > >;
		var results : array< weak< JournalQuestDescription > >;
		var i : Int32;
		contextFilter.active = true;
		contextFilter.inactive = false;
		contextFilter.succeeded = true;
		contextFilter.failed = true;
		UnpackRecursiveWithFilter( journalManager, entry, contextFilter, objects );
		for( i = 0; i < objects.Size(); i += 1 )
		{
			if( ( ( JournalQuestDescription )( objects[ i ] ) ) )
			{
				results.PushBack( ( ( JournalQuestDescription )( objects[ i ] ) ) );
			}
		}
		return results;
	}

	public static function GetLevelState( playerLevel : Int32, targetLevel : Int32 ) : CName
	{
		var difference : Int32;
		difference = playerLevel - targetLevel;
		if( difference <= ( ( Int32 )( gameEPowerDifferential.IMPOSSIBLE ) ) )
		{
			return 'ThreatVeryHigh';
		}
		if( difference <= ( ( Int32 )( gameEPowerDifferential.HARD ) ) )
		{
			return 'ThreatHigh';
		}
		if( difference <= ( ( Int32 )( gameEPowerDifferential.NORMAL ) ) )
		{
			return 'ThreatMedium';
		}
		if( difference <= ( ( Int32 )( gameEPowerDifferential.EASY ) ) )
		{
			return 'ThreatLow';
		}
		if( difference <= ( ( Int32 )( gameEPowerDifferential.TRASH ) ) )
		{
			return 'ThreatVeryLow';
		}
		return 'ThreatVeryLow';
	}

	public static function GetThreatText( playerLevel : Int32, targetLevel : Int32 ) : String
	{
		var result : String;
		result = GetLocalizedText( "UI-ResourceExports-Threat" ) + ": ";
		switch( QuestLogUtils.GetLevelState( playerLevel, targetLevel ) )
		{
			case 'ThreatVeryLow':
				result += GetLocalizedText( "UI-Tooltips-ThreatVeryLow" );
			break;
			case 'ThreatLow':
				result += GetLocalizedText( "UI-Tooltips-Low" );
			break;
			case 'ThreatMedium':
				result += GetLocalizedText( "UI-Tooltips-ThreatMedium" );
			break;
			case 'ThreatHigh':
				result += GetLocalizedText( "UI-Tooltips-ThreatHigh" );
			break;
			case 'ThreatVeryHigh':
				result += GetLocalizedText( "UI-Tooltips-ThreatVeryHigh" );
			break;
		}
		return result;
	}

}

final abstract class QuestTypeIconUtils
{

	public static function GetIcon( filterType : QuestListItemType ) : CName
	{
		switch( filterType )
		{
			case QuestListItemType.All:
				return 'journal_all';
			case QuestListItemType.MainQuest:
				return 'quest';
			case QuestListItemType.SideQuest:
				return 'minor_quest';
			case QuestListItemType.Gig:
				return 'gigs';
			case QuestListItemType.Cyberpsycho:
				return 'hunt_for_psycho';
			case QuestListItemType.NCPDQuest:
				return 'map_bounty';
			case QuestListItemType.Apartment:
				return 'apartment_to_buy';
			case QuestListItemType.Courier:
				return 'courier';
			case QuestListItemType.Finished:
				return 'completed';
		}
		return 'invalid';
	}

	public static function GetFilterIcon( filterType : QuestListItemType ) : CName
	{
		switch( filterType )
		{
			case QuestListItemType.All:
				return 'journal_all';
			case QuestListItemType.MainQuest:
			case QuestListItemType.SideQuest:
				return 'quest_filter';
			case QuestListItemType.Gig:
			case QuestListItemType.Cyberpsycho:
			case QuestListItemType.NCPDQuest:
			case QuestListItemType.Apartment:
			case QuestListItemType.Courier:
				return 'world_activities';
			case QuestListItemType.Finished:
				return 'completed';
		}
		return 'invalid';
	}

	public static function GetIconState( filterType : QuestListItemType ) : CName
	{
		switch( filterType )
		{
			case QuestListItemType.All:
				return 'All';
			case QuestListItemType.MainQuest:
				return 'MainQuest';
			case QuestListItemType.SideQuest:
				return 'MainQuest';
			case QuestListItemType.Gig:
				return 'Gig';
			case QuestListItemType.Cyberpsycho:
				return 'Cyberpsycho';
			case QuestListItemType.NCPDQuest:
				return 'Cyberpsycho';
			case QuestListItemType.Apartment:
				return 'Apartment';
			case QuestListItemType.Courier:
				return 'Gig';
			case QuestListItemType.Finished:
				return 'Finished';
		}
		return 'Default';
	}

}

