class MenuDataBuilder
{
	var m_data : array< MenuData >;

	public static function Make() : MenuDataBuilder
	{
		var instance : MenuDataBuilder;
		instance = new MenuDataBuilder;
		return instance;
	}

	public function AddIf( condition : Bool, identifier : Int32, fullscreenName : CName, icon : CName, labelKey : CName, optional userData : IScriptable ) : MenuDataBuilder
	{
		if( condition )
		{
			return Add( identifier, fullscreenName, icon, labelKey, userData );
		}
		return this;
	}

	public function Add( identifier : Int32, fullscreenName : CName, icon : CName, labelKey : CName, optional userData : IScriptable ) : MenuDataBuilder
	{
		var data : MenuData;
		data.label = GetLocalizedTextByKey( labelKey );
		data.icon = icon;
		data.fullscreenName = fullscreenName;
		data.identifier = identifier;
		data.userData = userData;
		m_data.PushBack( data );
		return this;
	}

	private function Add( data : MenuData, identifier : HubMenuItems, parentIdentifier : HubMenuItems, fullscreenName : CName, icon : CName, optional userData : IScriptable, optional disabled : Bool ) : MenuDataBuilder
	{
		data.icon = icon;
		data.fullscreenName = fullscreenName;
		data.identifier = ( ( Int32 )( identifier ) );
		data.parentIdentifier = ( ( Int32 )( parentIdentifier ) );
		data.userData = userData;
		data.disabled = disabled;
		m_data.PushBack( data );
		return this;
	}

	public function Add( identifier : HubMenuItems, parentIdentifier : HubMenuItems, fullscreenName : CName, icon : CName, labelKey : String, optional userData : IScriptable, optional disabled : Bool ) : MenuDataBuilder
	{
		var data : MenuData;
		data.label = GetLocalizedText( labelKey );
		return Add( data, identifier, parentIdentifier, fullscreenName, icon, userData, disabled );
	}

	public function Add( identifier : HubMenuItems, parentIdentifier : HubMenuItems, fullscreenName : CName, icon : CName, labelName : CName, optional userData : IScriptable, optional disabled : Bool ) : MenuDataBuilder
	{
		var data : MenuData;
		data.label = GetLocalizedTextByKey( labelName );
		return Add( data, identifier, parentIdentifier, fullscreenName, icon, userData, disabled );
	}

	public function AddWithSubmenu( identifier : Int32, fullscreenName : CName, icon : CName, labelKey : CName, optional userData : IScriptable, optional disabled : Bool ) : SubmenuDataBuilder
	{
		var data : MenuData;
		data.label = GetLocalizedTextByKey( labelKey );
		data.icon = icon;
		data.fullscreenName = fullscreenName;
		data.identifier = identifier;
		data.userData = userData;
		data.disabled = disabled;
		m_data.PushBack( data );
		return SubmenuDataBuilder.Make( this, m_data.Size() - 1 );
	}

	public function Get() : array< MenuData >
	{
		return m_data;
	}

	public function GetMainMenus() : array< MenuData >
	{
		var i, count : Int32;
		var res : array< MenuData >;
		var currentData : MenuData;
		count = m_data.Size();
		for( i = 0; i < count; i = i + 1 )
		{
			currentData = m_data[ i ];
			if( currentData.parentIdentifier == ( ( Int32 )( HubMenuItems.None ) ) )
			{
				res.PushBack( currentData );
			}
		}
		return res;
	}

	public function GetData( identifier : Int32 ) : MenuData
	{
		var i, count : Int32;
		var res : MenuData;
		count = m_data.Size();
		for( i = 0; i < count; i = i + 1 )
		{
			res = m_data[ i ];
			if( res.identifier == identifier )
			{
				return res;
			}
		}
		res.identifier = ( ( Int32 )( HubMenuItems.None ) );
		return res;
	}

	public function GetData( fullscreenName : CName ) : MenuData
	{
		var i, count : Int32;
		var res : MenuData;
		count = m_data.Size();
		for( i = 0; i < count; i = i + 1 )
		{
			res = m_data[ i ];
			if( res.fullscreenName == fullscreenName )
			{
				return res;
			}
		}
		res.identifier = ( ( Int32 )( HubMenuItems.None ) );
		return res;
	}

}

class HubMenuUtility
{

	public static function IsPlayerHardwareDisabled( player : weak< GameObject > ) : Bool
	{
		var gameInstance : GameInstance;
		var questsSystem : QuestsSystem;
		var isDisabled : Bool;
		gameInstance = player.GetGame();
		questsSystem = GameInstance.GetQuestsSystem( gameInstance );
		isDisabled = questsSystem.GetFact( 'q307_hub_disabled_except_journal' );
		return isDisabled;
	}

	public static function IsCraftingAvailable( player : weak< PlayerPuppet > ) : Bool
	{
		var isInComaQuest : Bool;
		var psmBlackboard : IBlackboard;
		var playerStateID : Int32;
		var isPlayerInCombat : Bool;
		var hasCraftingRestriction : Bool;
		isInComaQuest = IsPlayerHardwareDisabled( player );
		psmBlackboard = player.GetPlayerStateMachineBlackboard();
		playerStateID = psmBlackboard.GetInt( GetAllBlackboardDefs().PlayerStateMachine.Combat );
		isPlayerInCombat = playerStateID == ( ( Int32 )( gamePSMCombat.InCombat ) );
		hasCraftingRestriction = StatusEffectSystem.ObjectHasStatusEffectWithTag( player, 'NoCrafting' );
		return ( !( isPlayerInCombat ) && !( hasCraftingRestriction ) ) && !( isInComaQuest );
	}

	public static function CreateMenuData( player : weak< PlayerPuppet > ) : MenuDataBuilder
	{
		var isInComaQuest : Bool;
		var gameInstance : GameInstance;
		var questsSystem : QuestsSystem;
		var isCraftingAvailable : Bool;
		var isMapAvailable : Bool;
		var isTarotAvailable : Bool;
		isInComaQuest = IsPlayerHardwareDisabled( player );
		gameInstance = player.GetGame();
		questsSystem = GameInstance.GetQuestsSystem( gameInstance );
		isCraftingAvailable = IsCraftingAvailable( player );
		isMapAvailable = questsSystem.GetFact( 'map_blocked' ) || !( isInComaQuest );
		isTarotAvailable = !( questsSystem.GetFact( 'q101_done' ) );
		return MenuDataBuilder.Make().Add( HubMenuItems.Cyberware, HubMenuItems.None, 'cyberware_equip', 'ico_cyberware', 'UI-PanelNames-CYBERWARE', , isInComaQuest ).Add( HubMenuItems.Inventory, HubMenuItems.None, 'inventory_screen', 'ico_inventory', 'UI-PanelNames-INVENTORY', , isInComaQuest ).Add( HubMenuItems.Map, HubMenuItems.None, 'world_map', 'ico_map', 'UI-PanelNames-MAP', , !( isMapAvailable ) ).Add( HubMenuItems.Character, HubMenuItems.None, 'new_perks', 'ico_character', 'UI-PanelNames-CHARACTER', , isInComaQuest ).Add( HubMenuItems.Journal, HubMenuItems.None, 'quest_log', 'ico_journal', 'UI-PanelNames-JOURNAL' ).Add( HubMenuItems.Crafting, HubMenuItems.Inventory, 'crafting_main', 'ico_cafting', 'Gameplay-RPG-Skills-CraftingName', , !( isCraftingAvailable ) ).Add( HubMenuItems.Stats, HubMenuItems.Character, 'temp_stats', 'ico_stats_hub', 'UI-PanelNames-STATS', , isInComaQuest ).Add( HubMenuItems.Phone, HubMenuItems.Journal, 'phone', 'ico_phone', 'UI-PanelNames-PHONE' ).Add( HubMenuItems.Tarot, HubMenuItems.Journal, 'tarot_main', 'ico_tarot_hub', 'UI-PanelNames-TAROT', , isTarotAvailable ).Add( HubMenuItems.Shards, HubMenuItems.Journal, 'shards', 'ico_shards_hub', 'UI-PanelNames-SHARDS', CodexUserData.Make( CodexDataSource.Onscreen ) ).Add( HubMenuItems.Backpack, HubMenuItems.Inventory, 'backpack', 'ico_backpack', 'UI-PanelNames-BACKPACK', , isInComaQuest ).Add( HubMenuItems.Codex, HubMenuItems.Journal, 'codex', 'ico_data', 'UI-PanelNames-CODEX', CodexUserData.Make( CodexDataSource.Codex ), isInComaQuest );
	}

}

class SubmenuDataBuilder
{
	private var m_menuBuilder : MenuDataBuilder;
	private var m_menuDataIndex : Int32;

	public static function Make( menuBuilder : MenuDataBuilder, menuDataIndex : Int32 ) : SubmenuDataBuilder
	{
		var instance : SubmenuDataBuilder;
		instance = new SubmenuDataBuilder;
		instance.m_menuDataIndex = menuDataIndex;
		instance.m_menuBuilder = menuBuilder;
		return instance;
	}

	public function AddSubmenu( identifier : Int32, fullscreenName : CName, labelKey : CName, optional userData : IScriptable ) : SubmenuDataBuilder
	{
		var data : MenuData;
		data.label = GetLocalizedTextByKey( labelKey );
		data.fullscreenName = fullscreenName;
		data.identifier = identifier;
		data.userData = userData;
		m_menuBuilder.m_data[ m_menuDataIndex ].subMenus.PushBack( data );
		return this;
	}

	public function AddSubmenuIf( condition : Bool, identifier : Int32, fullscreenName : CName, labelKey : CName, optional userData : IScriptable ) : SubmenuDataBuilder
	{
		if( condition )
		{
			return AddSubmenu( identifier, fullscreenName, labelKey, userData );
		}
		return this;
	}

	public function GetMenuBuilder() : MenuDataBuilder
	{
		return m_menuBuilder;
	}

}

enum HubMenuItems
{
	None = -1,
	Default = 0,
	Crafting = 1,
	Character = 2,
	Inventory = 3,
	Map = 4,
	Journal = 5,
	Phone = 6,
	Database = 7,
	Stats = 8,
	Backpack = 9,
	HubMenuItems = 10,
	Codex = 11,
	Shards = 12,
	Tarot = 13,
	Gear = 14,
	Cyberware = 15,
	VisualSets = 16,
	Count = 17,
}

enum HubMenuCraftingItems
{
	Crafting = 0,
	Upgrade = 1,
}

enum HubMenuInventoryItems
{
	Gear = 0,
	Cyberware = 1,
	Backpack = 2,
}

enum HubMenuCharacterItems
{
	Skills = 0,
	Stats = 1,
}

enum HubMenuDatabaseItems
{
	Codex = 0,
	Tarot = 1,
	Shards = 2,
}

enum HubVendorMenuItems
{
	Trade = 0,
	Cyberware = 1,
}

struct MenuData
{
	var identifier : Int32;
	default identifier = -1;
	var label : String;
	var icon : CName;
	var subMenus : array< MenuData >;
	var eventName : CName;
	var fullscreenName : CName;
	var userData : IScriptable;
	var disabled : Bool;
	var parentIdentifier : Int32;
	var attrFlag : Bool;
	var attrText : Int32;
	var perkFlag : Bool;
	var perkText : Int32;
	var m_overrideDefaultUserData : Bool;
	var m_overrideSubMenuUserData : Bool;
}

