Spending/Catalogue.cs
namespace PlanetMeat;

public sealed class Catalogue( Scene scene ) : GameObjectSystem<Catalogue>( scene )
{
	public readonly struct Category( string ident, string displayIcon )
	{
		public string Ident { get; } = ident;
		public string DisplayName => "shop.category." + (Ident == "" ? "misc" : Ident);
		public string LocDisplayName => Game.Language.GetPhrase( DisplayName );
		public string DisplayIcon { get; } = displayIcon;
	}

	public Dictionary<string, Category> Categories { get; } = new()
	{
		["drill_gun"] = new( "drill_gun", "search" ),
		["drill_hp"] = new( "drill_hp", "health_and_safety" ),
		["flame"] = new( "flame", "local_fire_department" ),
		["mortar"] = new( "mortar", "flare" ),
		["heli"] = new( "heli", "flight_land" ),
		["pulse"] = new( "pulse", "offline_bolt" ),
		["goop_econ"] = new( "goop_econ", "water_drop" ),
		["meat_econ"] = new( "meat_econ", "link" ),
		["multishot"] = new( "multishot", "call_split" ),
		["lifesteal"] = new( "lifesteal", "bloodtype" ),
		["thorns"] = new( "thorns", "cyclone" ),
		[""] = new( "", "category" ),
	};

	public List<string> BlameTools
	{
		get
		{
			if ( field is null )
			{
				field = ["drill_gun", "flame", "mortar", "heli", "pulse", "thorns", "phoenix"];
				field.Sort( ( a, b ) => BaseTech.TrToolTitle( a ).CompareTo( BaseTech.TrToolTitle( b ) ) );
				field.Add( "burster" );
			}
			return field;
		}
	}

	public Category GetCategory( string ident )
	{
		if ( ident != "" && Categories.TryGetValue( ident, out Category cat ) )
			return cat;
		return Categories[""];
	}

	public Dictionary<string, List<IPurchaseableUpgrade>> Upgrades { get; } = [];
	public List<string> CategoryOrder { get; } = [];

	public string CurrentTab { get; set; } = "";

	public void CloseTab() => CurrentTab = "";

	public int SortCategories( string a, string b )
	{
		if ( a == "" )
			return -1;
		if ( b == "" )
			return 1;
		if ( a == "drill_hp" )
			return -1;
		if ( b == "drill_hp" )
			return 1;

		return GetCategory( a ).LocDisplayName.CompareTo( GetCategory( b ).LocDisplayName );
	}

	public static int SortUpgrades( IPurchaseableUpgrade a, IPurchaseableUpgrade b )
	{
		if ( a.Ident == "target.repair" )
			return -1;
		if ( b.Ident == "target.repair" )
			return 1;

		return Game.Language.GetPhrase( a.DisplayName ).CompareTo( Game.Language.GetPhrase( b.DisplayName ) );
	}

	public void BakeUpgrades( IEnumerable<IPurchaseableUpgrade> upgrades )
	{
		Upgrades.Clear();
		CategoryOrder.Clear();
		foreach ( var up in upgrades.Where( up => up.Visible ) )
		{
			var categoryIdent = GetCategory( up.CategoryIdent ).Ident;
			Upgrades.GetOrCreate( categoryIdent ).Add( up );
			if ( !CategoryOrder.Contains( categoryIdent ) )
				CategoryOrder.Add( categoryIdent );
		}

		foreach ( var (cat, ups) in Upgrades )
			ups.Sort( SortUpgrades );

		CategoryOrder.Sort( SortCategories );
		CloseTab();
	}
}