Decompiled source of UpgradeFiltering v1.1.2

BepInEx/plugins/UpgradeFiltering.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Pigeon;
using Sparroh.UI;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Sparroh")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.2.0")]
[assembly: AssemblyInformationalVersion("1.1.2")]
[assembly: AssemblyProduct("UpgradeFiltering")]
[assembly: AssemblyTitle("UpgradeFiltering")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
public static class ConfigManager
{
	private const float DebounceSeconds = 0.25f;

	private static ConfigFile config;

	private static ManualLogSource logger;

	private static FileSystemWatcher configWatcher;

	private static volatile bool reloadPending;

	private static float lastReloadTime;

	public static ConfigEntry<bool> EnableStatReformat { get; private set; }

	public static void Initialize(ConfigFile configFile, ManualLogSource log)
	{
		config = configFile;
		logger = log;
		EnableStatReformat = config.Bind<bool>("General", "Enable Reformat", false, "Force Key: Value stat format");
		StatFormatHandling.enableStatReformat = EnableStatReformat.Value;
		EnableStatReformat.SettingChanged += OnStatReformatChanged;
		try
		{
			SetupFileWatcher();
		}
		catch (Exception ex)
		{
			logger.LogError((object)("Error setting up config file watcher: " + ex.Message));
		}
	}

	public static void Tick()
	{
		if (!reloadPending || Time.unscaledTime - lastReloadTime < 0.25f)
		{
			return;
		}
		reloadPending = false;
		lastReloadTime = Time.unscaledTime;
		try
		{
			config.Reload();
			StatFormatHandling.enableStatReformat = EnableStatReformat.Value;
			logger.LogInfo((object)"Config reloaded from disk.");
		}
		catch (Exception ex)
		{
			logger.LogError((object)("Error reloading config: " + ex.Message));
		}
	}

	public static void Dispose()
	{
		if (EnableStatReformat != null)
		{
			EnableStatReformat.SettingChanged -= OnStatReformatChanged;
		}
		if (configWatcher != null)
		{
			configWatcher.EnableRaisingEvents = false;
			configWatcher.Changed -= OnConfigFileChanged;
			configWatcher.Created -= OnConfigFileChanged;
			configWatcher.Renamed -= OnConfigFileChanged;
			configWatcher.Dispose();
			configWatcher = null;
		}
	}

	private static void SetupFileWatcher()
	{
		configWatcher = new FileSystemWatcher(Paths.ConfigPath, "sparroh.upgradefiltering.cfg");
		configWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite;
		configWatcher.Changed += OnConfigFileChanged;
		configWatcher.Created += OnConfigFileChanged;
		configWatcher.Renamed += OnConfigFileChanged;
		configWatcher.EnableRaisingEvents = true;
	}

	private static void OnConfigFileChanged(object sender, FileSystemEventArgs e)
	{
		reloadPending = true;
	}

	private static void OnStatReformatChanged(object sender, EventArgs e)
	{
		StatFormatHandling.enableStatReformat = EnableStatReformat.Value;
	}
}
public class FilterPanelUI
{
	private readonly Dictionary<Rarity, UIButton> _rarityButtons = new Dictionary<Rarity, UIButton>();

	private UIButton _favHide;

	private UIButton _favOnly;

	private UIButton _favShowAll;

	private UIScrollView _statScroll;

	private UIWindow _window;

	private bool isInitialized;

	public bool IsExpanded { get; private set; }

	public void Toggle()
	{
		if (!isInitialized)
		{
			CreateFilterPanel();
			if (!isInitialized)
			{
				return;
			}
		}
		IsExpanded = !IsExpanded;
		if (IsExpanded)
		{
			RegenerateStatFilters();
			_window.Show();
		}
		else
		{
			_window.Hide(false);
		}
	}

	public void RegenerateStatFilters()
	{
		try
		{
			if (isInitialized && _statScroll != null)
			{
				FilterState.CurrentFilters.StatIncludeList.Clear();
				FilterState.CurrentFilters.FilterStats = false;
				RebuildStatToggles();
			}
		}
		catch
		{
		}
	}

	public void RebuildFilterPanel()
	{
		try
		{
			bool isExpanded = IsExpanded;
			if (_window != null)
			{
				_window.Destroy();
				_window = null;
			}
			_rarityButtons.Clear();
			isInitialized = false;
			IsExpanded = false;
			CreateFilterPanel();
			if (isExpanded && isInitialized)
			{
				IsExpanded = true;
				_window.Show();
			}
		}
		catch
		{
		}
	}

	private void CreateFilterPanel()
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_015f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: Unknown result type (might be due to invalid IL or missing references)
		//IL_0175: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0295: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
		if (isInitialized)
		{
			return;
		}
		try
		{
			UITheme.Initialize();
			_window = UIWindow.Create("UpgradeFilter", (Vector2?)new Vector2(280f, 480f), "Upgrade Filters", true, true, (int?)(UITheme.WindowSortingOrder + 7));
			_window.OnClose((Action)delegate
			{
				IsExpanded = false;
			});
			Transform content = _window.Content;
			UIFactory.AddVerticalLayout(((Component)content).gameObject, UITheme.S(6f), UITheme.ScaledPadding(6, 6, 6, 6), (TextAnchor)0, true, false, true, true);
			UIButton.Create(content, "Clear All Filters", (Action)ClearAllFilters, (UIButtonStyle)2, (string)null, (float?)UITheme.S(28f));
			UIText.Create(content, "RarityLbl", "Hide Rarities", UITheme.ScaledFontSmall, (Color?)UIColors.TextSecondary, (TextAlignmentOptions)513, false);
			(string, Rarity)[] array = new(string, Rarity)[5]
			{
				("Standard", (Rarity)0),
				("Rare", (Rarity)1),
				("Epic", (Rarity)2),
				("Exotic", (Rarity)3),
				("Oddity", (Rarity)4)
			};
			for (int num = 0; num < array.Length; num++)
			{
				(string, Rarity) tuple = array[num];
				Rarity rarity = tuple.Item2;
				bool flag = FilterState.CurrentFilters.HiddenRarities.Contains(rarity);
				UIButton value = UIButton.Create(content, tuple.Item1, (Action)delegate
				{
					//IL_000b: Unknown result type (might be due to invalid IL or missing references)
					//IL_0076: Unknown result type (might be due to invalid IL or missing references)
					//IL_008c: Unknown result type (might be due to invalid IL or missing references)
					//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
					//IL_0022: Unknown result type (might be due to invalid IL or missing references)
					//IL_0039: Unknown result type (might be due to invalid IL or missing references)
					//IL_0055: Unknown result type (might be due to invalid IL or missing references)
					if (FilterState.CurrentFilters.HiddenRarities.Contains(rarity))
					{
						FilterState.CurrentFilters.HiddenRarities.Remove(rarity);
						_rarityButtons[rarity].SetStyle((UIButtonStyle)0);
						UpgradeFilteringPlugin.Logger.LogInfo((object)$"Filter: show rarity {rarity}");
					}
					else
					{
						FilterState.CurrentFilters.HiddenRarities.Add(rarity);
						_rarityButtons[rarity].SetStyle((UIButtonStyle)2);
						UpgradeFilteringPlugin.Logger.LogInfo((object)$"Filter: hide rarity {rarity}");
					}
					UpgradeFilteringPlugin.Logger.LogInfo((object)("Filter: HiddenRarities=[" + string.Join(",", FilterState.CurrentFilters.HiddenRarities) + "]"));
					RefreshUpgrades();
				}, (UIButtonStyle)(flag ? 2 : 0), (string)null, (float?)UITheme.S(24f));
				_rarityButtons[rarity] = value;
			}
			UIText.Create(content, "FavLbl", "Favorites", UITheme.ScaledFontSmall, (Color?)UIColors.TextSecondary, (TextAlignmentOptions)513, false);
			_favShowAll = UIButton.Create(content, "Show All", (Action)delegate
			{
				FilterState.CurrentFilters.FavoriteSetting = FavoriteFilter.ShowAll;
				UpdateFavoriteHighlights();
				RefreshUpgrades();
			}, (UIButtonStyle)3, (string)null, (float?)UITheme.S(24f));
			_favOnly = UIButton.Create(content, "Only Favorite", (Action)delegate
			{
				FilterState.CurrentFilters.FavoriteSetting = FavoriteFilter.ShowOnlyFavorited;
				UpdateFavoriteHighlights();
				RefreshUpgrades();
			}, (UIButtonStyle)0, (string)null, (float?)UITheme.S(24f));
			_favHide = UIButton.Create(content, "Hide Favorite", (Action)delegate
			{
				FilterState.CurrentFilters.FavoriteSetting = FavoriteFilter.HideFavorited;
				UpdateFavoriteHighlights();
				RefreshUpgrades();
			}, (UIButtonStyle)0, (string)null, (float?)UITheme.S(24f));
			UIText.Create(content, "StatLbl", "Show Only With", UITheme.ScaledFontSmall, (Color?)UIColors.TextSecondary, (TextAlignmentOptions)513, false);
			_statScroll = UIScrollView.Create(content, "StatScroll", true, false);
			GameObject gameObject = _statScroll.GameObject;
			float? num2 = UITheme.S(160f);
			float? num3 = UITheme.S(120f);
			UIHelpers.EnsureLayoutElement(gameObject, (float?)null, num2, num3);
			RebuildStatToggles();
			_window.Hide(false);
			isInitialized = true;
			IsExpanded = false;
		}
		catch (Exception)
		{
			isInitialized = false;
		}
	}

	private void UpdateFavoriteHighlights()
	{
		FavoriteFilter favoriteSetting = FilterState.CurrentFilters.FavoriteSetting;
		if (_favShowAll != null)
		{
			_favShowAll.SetStyle((UIButtonStyle)((favoriteSetting == FavoriteFilter.ShowAll) ? 3 : 0));
		}
		if (_favOnly != null)
		{
			_favOnly.SetStyle((UIButtonStyle)((favoriteSetting == FavoriteFilter.ShowOnlyFavorited) ? 3 : 0));
		}
		if (_favHide != null)
		{
			_favHide.SetStyle((UIButtonStyle)((favoriteSetting == FavoriteFilter.HideFavorited) ? 3 : 0));
		}
	}

	private void ClearAllFilters()
	{
		FilterState.CurrentFilters.HiddenRarities.Clear();
		FilterState.CurrentFilters.FavoriteSetting = FavoriteFilter.ShowAll;
		FilterState.CurrentFilters.FilterStats = false;
		FilterState.CurrentFilters.StatIncludeList.Clear();
		foreach (KeyValuePair<Rarity, UIButton> rarityButton in _rarityButtons)
		{
			rarityButton.Value.SetStyle((UIButtonStyle)0);
		}
		UpdateFavoriteHighlights();
		RebuildStatToggles();
		RefreshUpgrades();
	}

	private void RebuildStatToggles()
	{
		if (_statScroll == null)
		{
			return;
		}
		UIHelpers.DestroyChildren((Transform)(object)_statScroll.Content);
		foreach (string item in from p in GetContextAwareProperties()
			orderby p
			select p)
		{
			string text = item.Replace("_", " ");
			string prop = item;
			GameObject gameObject = UIToggle.Create((Transform)(object)_statScroll.Content, text, false, (Action<bool>)delegate(bool value)
			{
				if (value)
				{
					FilterState.CurrentFilters.FilterStats = true;
					if (!FilterState.CurrentFilters.StatIncludeList.Contains(prop))
					{
						FilterState.CurrentFilters.StatIncludeList.Add(prop);
					}
				}
				else
				{
					FilterState.CurrentFilters.StatIncludeList.Remove(prop);
					if (FilterState.CurrentFilters.StatIncludeList.Count == 0)
					{
						FilterState.CurrentFilters.FilterStats = false;
					}
				}
				RefreshUpgrades();
			}, (string)null).GameObject;
			float? num = UITheme.S(22f);
			UIHelpers.EnsureLayoutElement(gameObject, (float?)null, num, (float?)null);
		}
	}

	private List<string> GetContextAwareProperties()
	{
		try
		{
			GearDetailsWindow openWindow = FilterState.GetOpenWindow();
			bool flag = false;
			if ((Object)(object)openWindow != (Object)null)
			{
				FieldInfo fieldInfo = AccessTools.Field(typeof(GearDetailsWindow), "inSkinMode");
				if (fieldInfo != null)
				{
					try
					{
						flag = (bool)fieldInfo.GetValue(openWindow);
					}
					catch
					{
					}
				}
			}
			return flag ? DiscoverSkinProperties() : GetCuratedUpgradeProperties();
		}
		catch
		{
			return GetCuratedUpgradeProperties();
		}
	}

	private static List<string> GetCuratedUpgradeProperties()
	{
		return new List<string>
		{
			"AmmoCapacity", "AutomaticFire", "BatteryCapacity", "BulletsPerShot", "BurstFire", "Carver_Blood", "Charge", "Damage", "FireInterval", "Globbler_Globblometer",
			"Health", "HealthRegenDelay", "HitForce", "MagazineSize", "MaxBounces", "MeleeDamage", "Range", "Recoil", "Reload", "Speed"
		};
	}

	private static List<string> DiscoverSkinProperties()
	{
		List<string> list = new List<string>();
		try
		{
			Type skinUpgradePropertyType = typeof(GearUpgradeUI).Assembly.GetType("SkinUpgradeProperty");
			if (skinUpgradePropertyType == null)
			{
				return list;
			}
			foreach (Type item in (from t in skinUpgradePropertyType.Assembly.GetTypes()
				where t.IsClass && !t.IsAbstract && skinUpgradePropertyType.IsAssignableFrom(t) && t.FullName != null && t.FullName.StartsWith("SkinUpgradeProperty_")
				select t).ToList())
			{
				string text = item.Name;
				if (text.StartsWith("SkinUpgradeProperty_"))
				{
					text = text.Substring("SkinUpgradeProperty_".Length);
				}
				list.Add(text);
			}
			return (from p in list.Distinct()
				orderby p
				select p).ToList();
		}
		catch
		{
			return list;
		}
	}

	private void RefreshUpgrades()
	{
		GearDetailsWindow val = PriorityPatches.ResolveWindow() ?? FilterState.GetOpenWindow();
		if ((Object)(object)val == (Object)null)
		{
			UpgradeFilteringPlugin.Logger.LogWarning((object)"Filter refresh: no GearDetailsWindow.");
			return;
		}
		UpgradeFilteringPlugin.Logger.LogInfo((object)$"Filter refresh: window={((Object)val).name}, priorityActive={PriorityPatches.PrioritySortActive}");
		try
		{
			FilterState.ApplyToWindow(val);
		}
		catch (Exception ex)
		{
			UpgradeFilteringPlugin.Logger.LogError((object)("Filter refresh failed: " + ex.Message + "\n" + ex.StackTrace));
		}
	}
}
[HarmonyPatch(typeof(GearDetailsWindow))]
public static class GearDetailsWindowPatches
{
	[HarmonyPostfix]
	[HarmonyPatch("OnOpen")]
	private static void OnOpen(GearDetailsWindow __instance)
	{
		try
		{
			FieldInfo fieldInfo = AccessTools.Field(typeof(GearDetailsWindow), "inSkinMode");
			if (fieldInfo != null)
			{
				bool flag = (bool)fieldInfo.GetValue(__instance);
				if (FilterState.PreviousSkinMode.HasValue && FilterState.PreviousSkinMode.Value != flag && FilterState.FilterPanel != null)
				{
					FilterState.FilterPanel.RegenerateStatFilters();
				}
				FilterState.PreviousSkinMode = flag;
			}
		}
		catch
		{
		}
		if (FilterState.FilterPanel == null)
		{
			FilterState.FilterPanel = new FilterPanelUI();
		}
	}

	[HarmonyPrefix]
	[HarmonyPatch("SwitchUpgradeView")]
	private static void SwitchUpgradeView_Prefix()
	{
		ListRebuildReapply.BeginViewSwitch();
	}

	[HarmonyPostfix]
	[HarmonyPatch("SwitchUpgradeView")]
	private static void SwitchUpgradeView_Postfix(GearDetailsWindow __instance)
	{
		try
		{
			ListRebuildReapply.After(__instance, "SwitchUpgradeView");
		}
		finally
		{
			ListRebuildReapply.EndViewSwitch();
		}
	}
}
[HarmonyPatch(typeof(GearDetailsWindow), "SetupUpgrades", new Type[]
{
	typeof(IUpgradable),
	typeof(bool),
	typeof(bool)
})]
public static class SetupUpgradesPatch
{
	[HarmonyPostfix]
	public static void Postfix(GearDetailsWindow __instance, bool skins)
	{
		if (!ListRebuildReapply.SuppressNestedReapply)
		{
			ListRebuildReapply.After(__instance, $"SetupUpgrades(skins={skins})");
		}
	}
}
[HarmonyPatch(typeof(GearDetailsWindow), "SortUpgrades", new Type[]
{
	typeof(SortingMethod),
	typeof(bool)
})]
public static class SortUpgradesMethodPatch
{
	private static bool? lastSkinMode;

	[HarmonyPostfix]
	public static void Postfix(GearDetailsWindow __instance, SortingMethod method, bool resetScroll)
	{
		if (ListRebuildReapply.SuppressNestedReapply || PriorityPatches.PrioritySortActive)
		{
			return;
		}
		FieldInfo fieldInfo = AccessTools.Field(typeof(GearDetailsWindow), "inSkinMode");
		bool flag = false;
		if (fieldInfo != null)
		{
			try
			{
				flag = (bool)fieldInfo.GetValue(__instance);
			}
			catch
			{
			}
		}
		bool num = lastSkinMode.HasValue && lastSkinMode.Value != flag;
		lastSkinMode = flag;
		if (num)
		{
			return;
		}
		try
		{
			FilterState.ApplyToWindow(__instance);
		}
		catch
		{
		}
	}
}
internal static class ListRebuildReapply
{
	public static bool SuppressNestedReapply { get; private set; }

	public static void After(GearDetailsWindow window, string reason)
	{
		if ((Object)(object)window == (Object)null)
		{
			return;
		}
		try
		{
			PriorityPatches.currentWindow = window;
			PriorityPatches.CancelDeferredLayout();
			List<GearUpgradeUI> upgradeUIs = FilterState.GetUpgradeUIs();
			int num = FilterState.GetUpgradeUICount(window);
			if (upgradeUIs == null)
			{
				UpgradeFilteringPlugin.Logger.LogWarning((object)("List rebuild (" + reason + "): upgradeUIs null"));
				return;
			}
			if (num <= 0 || num > upgradeUIs.Count)
			{
				num = upgradeUIs.Count;
			}
			PriorityPatches.ClearStalePoolSlots(upgradeUIs, num);
			if (!PriorityPatches.LogUniqueInstanceIds("BEFORE repair (" + reason + ")", upgradeUIs, num) && !PriorityPatches.TryRepairDuplicateUiRefs(window, upgradeUIs, num))
			{
				UpgradeFilteringPlugin.Logger.LogError((object)("List rebuild (" + reason + "): pool repair failed — reopen gear window."));
				return;
			}
			PriorityPatches.ActivateAllLiveSlots(upgradeUIs, num);
			if (PriorityPatches.PrioritySortActive)
			{
				PriorityPatches.ApplyPrioritySort(window, resetScroll: false, skipDeferred: true);
				UpgradeFilteringPlugin.Logger.LogInfo((object)$"List rebuild re-apply ({reason}): visual priority + filters, isGrid={PriorityPatches.GetIsGridView(window)}");
			}
			else if (FilterState.HasActiveFilters())
			{
				FilterState.ApplyToWindow(window);
				UpgradeFilteringPlugin.Logger.LogInfo((object)$"List rebuild re-apply ({reason}): filters only, isGrid={PriorityPatches.GetIsGridView(window)}");
			}
			else
			{
				PriorityPatches.ForceLayoutVisibleOnly(window, upgradeUIs, num);
				UpgradeFilteringPlugin.Logger.LogInfo((object)$"List rebuild re-apply ({reason}): layout only, isGrid={PriorityPatches.GetIsGridView(window)}");
			}
		}
		catch (Exception ex)
		{
			UpgradeFilteringPlugin.Logger.LogError((object)("List rebuild re-apply failed (" + reason + "): " + ex.Message + "\n" + ex.StackTrace));
		}
	}

	public static void BeginViewSwitch()
	{
		SuppressNestedReapply = true;
		PriorityPatches.CancelDeferredLayout();
	}

	public static void EndViewSwitch()
	{
		SuppressNestedReapply = false;
	}
}
public enum FavoriteFilter
{
	ShowAll,
	ShowOnlyFavorited,
	HideFavorited
}
public struct FilterSettings
{
	public List<Rarity> HiddenRarities;

	public bool FilterStats;

	public List<string> StatIncludeList;

	public FavoriteFilter FavoriteSetting;
}
public static class FilterState
{
	internal static FilterPanelUI FilterPanel;

	internal static readonly Dictionary<Rarity, int> RarityOrder = new Dictionary<Rarity, int>
	{
		{
			(Rarity)4,
			5
		},
		{
			(Rarity)3,
			4
		},
		{
			(Rarity)2,
			3
		},
		{
			(Rarity)1,
			2
		},
		{
			(Rarity)0,
			1
		},
		{
			(Rarity)(-1),
			0
		}
	};

	internal static FilterSettings CurrentFilters = new FilterSettings
	{
		HiddenRarities = new List<Rarity>(),
		FilterStats = false,
		StatIncludeList = new List<string>(),
		FavoriteSetting = FavoriteFilter.ShowAll
	};

	internal static bool? PreviousSkinMode;

	private static FieldInfo _upgradeUIsField;

	private static FieldInfo _upgradeUICountField;

	public static bool HasActiveFilters()
	{
		if (!CurrentFilters.HiddenRarities.Any() && CurrentFilters.FavoriteSetting == FavoriteFilter.ShowAll)
		{
			if (CurrentFilters.FilterStats)
			{
				return CurrentFilters.StatIncludeList.Any();
			}
			return false;
		}
		return true;
	}

	public static void ApplyVisibilityOnly(GearDetailsWindow window)
	{
		if ((Object)(object)window == (Object)null)
		{
			return;
		}
		List<GearUpgradeUI> upgradeUIs = GetUpgradeUIs();
		if (upgradeUIs == null || upgradeUIs.Count == 0)
		{
			return;
		}
		int num = GetUpgradeUICount(window);
		if (num <= 0)
		{
			num = upgradeUIs.Count;
		}
		num = Mathf.Min(num, upgradeUIs.Count);
		bool isGridView = PriorityPatches.GetIsGridView(window);
		int num2 = 0;
		int num3 = 0;
		int num4 = 0;
		for (int i = 0; i < num; i++)
		{
			GearUpgradeUI val = upgradeUIs[i];
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			UpgradeInstance upgrade = ((HoverInfoUpgrade)val).Upgrade;
			if ((Object)(object)((upgrade != null) ? upgrade.Upgrade : null) == (Object)null)
			{
				if (((Component)val).gameObject.activeSelf)
				{
					((Component)val).gameObject.SetActive(false);
				}
				num3++;
			}
			else if (ShouldShow(val))
			{
				if (!((Component)val).gameObject.activeSelf)
				{
					((Component)val).gameObject.SetActive(true);
					try
					{
						val.SetUpgrade(((HoverInfoUpgrade)val).Upgrade, false);
					}
					catch
					{
					}
					num4++;
				}
				try
				{
					val.EnableGridView(isGridView);
				}
				catch
				{
				}
				num2++;
			}
			else
			{
				if (((Component)val).gameObject.activeSelf)
				{
					((Component)val).gameObject.SetActive(false);
				}
				num3++;
			}
		}
		UpgradeFilteringPlugin.Logger.LogInfo((object)($"Filter visibility: count={num}, visible={num2}, hidden={num3}, " + $"reenabled={num4}, fav={CurrentFilters.FavoriteSetting}"));
	}

	public static void ApplyToWindow(GearDetailsWindow window)
	{
		if ((Object)(object)window == (Object)null)
		{
			UpgradeFilteringPlugin.Logger.LogWarning((object)"ApplyToWindow: window null");
			return;
		}
		List<GearUpgradeUI> upgradeUIs = GetUpgradeUIs();
		if (upgradeUIs == null || upgradeUIs.Count == 0)
		{
			UpgradeFilteringPlugin.Logger.LogWarning((object)"ApplyToWindow: upgradeUIs empty");
			return;
		}
		int num = GetUpgradeUICount(window);
		if (num <= 0)
		{
			num = upgradeUIs.Count;
		}
		num = Mathf.Min(num, upgradeUIs.Count);
		string arg = ((CurrentFilters.HiddenRarities != null && CurrentFilters.HiddenRarities.Count > 0) ? string.Join(",", CurrentFilters.HiddenRarities) : "(none)");
		UpgradeFilteringPlugin.Logger.LogInfo((object)($"Filter apply: count={num}, hiddenRarities=[{arg}], " + $"fav={CurrentFilters.FavoriteSetting}, stats={CurrentFilters.FilterStats}/" + $"{CurrentFilters.StatIncludeList?.Count ?? 0}"));
		ApplyVisibilityOnly(window);
		if (PriorityPatches.PrioritySortActive)
		{
			List<PriorityCriteria> order = PriorityPatches.FilterOrderForAvailableMods(PriorityPatches.LoadPriorityOrder());
			PriorityPatches.ApplyVisualPriorityOrder(window, upgradeUIs, num, order);
		}
		else
		{
			PriorityPatches.ForceLayoutVisibleOnly(window, upgradeUIs, num);
		}
		try
		{
			typeof(GearDetailsWindow).GetMethod("SetUpgradeListScroll", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(float) }, null)?.Invoke(window, new object[1] { 1f });
		}
		catch
		{
		}
	}

	internal static List<GearUpgradeUI> GetUpgradeUIs()
	{
		try
		{
			if (_upgradeUIsField == null)
			{
				_upgradeUIsField = typeof(GearDetailsWindow).GetField("upgradeUIs", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			}
			if (_upgradeUIsField == null)
			{
				return null;
			}
			return _upgradeUIsField.GetValue(null) as List<GearUpgradeUI>;
		}
		catch
		{
			return null;
		}
	}

	internal static int GetUpgradeUICount(GearDetailsWindow window)
	{
		if ((Object)(object)window == (Object)null)
		{
			return 0;
		}
		try
		{
			if (_upgradeUICountField == null)
			{
				_upgradeUICountField = typeof(GearDetailsWindow).GetField("upgradeUICount", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
			if (_upgradeUICountField == null)
			{
				return 0;
			}
			return (int)_upgradeUICountField.GetValue(window);
		}
		catch
		{
			return 0;
		}
	}

	internal static GearDetailsWindow GetOpenWindow()
	{
		try
		{
			Menu instance = Menu.Instance;
			if ((Object)(object)((instance != null) ? instance.WindowSystem : null) != (Object)null)
			{
				Window top = Menu.Instance.WindowSystem.GetTop();
				GearDetailsWindow val = (GearDetailsWindow)(object)((top is GearDetailsWindow) ? top : null);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
		}
		catch
		{
		}
		if ((Object)(object)PriorityPatches.currentWindow != (Object)null)
		{
			try
			{
				if ((Object)(object)((Component)PriorityPatches.currentWindow).gameObject != (Object)null)
				{
					return PriorityPatches.currentWindow;
				}
			}
			catch
			{
			}
		}
		try
		{
			return Object.FindObjectOfType<GearDetailsWindow>();
		}
		catch
		{
			return null;
		}
	}

	public static bool ShouldShow(GearUpgradeUI ui)
	{
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		object obj;
		if (ui == null)
		{
			obj = null;
		}
		else
		{
			UpgradeInstance upgrade = ((HoverInfoUpgrade)ui).Upgrade;
			obj = ((upgrade != null) ? upgrade.Upgrade : null);
		}
		if ((Object)obj == (Object)null)
		{
			return false;
		}
		bool flag = true;
		if (CurrentFilters.HiddenRarities != null && CurrentFilters.HiddenRarities.Count > 0)
		{
			flag &= !CurrentFilters.HiddenRarities.Contains(((HoverInfoUpgrade)ui).Upgrade.Upgrade.Rarity);
		}
		switch (CurrentFilters.FavoriteSetting)
		{
		case FavoriteFilter.ShowOnlyFavorited:
			flag &= ((HoverInfoUpgrade)ui).Upgrade.Favorite;
			break;
		case FavoriteFilter.HideFavorited:
			flag &= !((HoverInfoUpgrade)ui).Upgrade.Favorite;
			break;
		}
		if (CurrentFilters.FilterStats && CurrentFilters.StatIncludeList != null && CurrentFilters.StatIncludeList.Count > 0)
		{
			foreach (string statInclude in CurrentFilters.StatIncludeList)
			{
				bool flag2 = false;
				Enumerator properties = ((HoverInfoUpgrade)ui).Upgrade.Upgrade.GetProperties();
				while (((Enumerator)(ref properties)).MoveNext())
				{
					UpgradeProperty current2 = ((Enumerator)(ref properties)).Current;
					if (current2 != null)
					{
						string text = ((object)current2).GetType().Name;
						if (text.StartsWith("UpgradeProperty_"))
						{
							text = text.Substring("UpgradeProperty_".Length);
						}
						else if (text.StartsWith("SkinUpgradeProperty_"))
						{
							text = text.Substring("SkinUpgradeProperty_".Length);
						}
						if (text == statInclude)
						{
							flag2 = true;
							break;
						}
					}
				}
				if (!flag2)
				{
					return false;
				}
			}
		}
		return flag;
	}
}
[BepInPlugin("sparroh.upgradefiltering", "UpgradeFiltering", "1.1.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[MycoMod(/*Could not decode attribute arguments.*/)]
public class UpgradeFilteringPlugin : BaseUnityPlugin
{
	public const string PluginGUID = "sparroh.upgradefiltering";

	public const string PluginName = "UpgradeFiltering";

	public const string PluginVersion = "1.1.2";

	internal static ManualLogSource Logger;

	public static UpgradeFilteringPlugin Instance;

	private bool _barRegistered;

	private void Awake()
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Expected O, but got Unknown
		try
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			Harmony val = new Harmony("sparroh.upgradefiltering");
			try
			{
				ConfigManager.Initialize(((BaseUnityPlugin)this).Config, Logger);
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("Failed to setup configuration bindings: " + ex.Message));
			}
			try
			{
				StatFormatHandling.Initialize();
			}
			catch (Exception ex2)
			{
				Logger.LogError((object)("Failed to initialize StatFormatHandling: " + ex2.Message));
			}
			try
			{
				PriorityGUI.EnsureExists();
			}
			catch (Exception ex3)
			{
				Logger.LogError((object)("Failed to initialize PriorityGUI: " + ex3.Message));
			}
			try
			{
				PriorityPatches.Patch(val);
			}
			catch (Exception ex4)
			{
				Logger.LogError((object)("Failed to apply PriorityPatches: " + ex4.Message));
			}
			Type[] array = new Type[4]
			{
				typeof(GearDetailsWindowPatches),
				typeof(SetupUpgradesPatch),
				typeof(SortUpgradesMethodPatch),
				typeof(PriorityPatches)
			};
			foreach (Type type in array)
			{
				try
				{
					val.PatchAll(type);
				}
				catch (Exception ex5)
				{
					Logger.LogError((object)("Failed to patch " + type.Name + ": " + ex5.Message));
				}
			}
			try
			{
				array = typeof(UpgradeFilteringPlugin).Assembly.GetTypes();
				foreach (Type type2 in array)
				{
					if (type2 == typeof(GearDetailsWindowPatches) || type2 == typeof(SetupUpgradesPatch) || type2 == typeof(SortUpgradesMethodPatch) || type2 == typeof(PriorityPatches) || type2 == typeof(ListRebuildReapply) || !type2.IsClass)
					{
						continue;
					}
					object[] customAttributes = type2.GetCustomAttributes(typeof(HarmonyPatch), inherit: true);
					if (customAttributes != null && customAttributes.Length != 0)
					{
						try
						{
							val.PatchAll(type2);
						}
						catch (Exception ex6)
						{
							Logger.LogError((object)("Failed to patch " + type2.Name + ": " + ex6.Message));
						}
					}
				}
			}
			catch (Exception ex7)
			{
				Logger.LogError((object)("Failed scanning assembly patches: " + ex7.Message));
			}
		}
		catch (Exception ex8)
		{
			Logger.LogError((object)("Critical error during mod initialization: " + ex8.Message + "\n" + ex8.StackTrace));
		}
		Logger.LogInfo((object)"UpgradeFiltering loaded successfully.");
	}

	private void Update()
	{
		ConfigManager.Tick();
		GearActionBar.Tick();
		if (GearActionBar.IsGearMenuOpen() && !_barRegistered)
		{
			GearActionBar.Register("filter", "Filter", 100, (Action)delegate
			{
				FilterState.FilterPanel?.Toggle();
			}, (UIButtonStyle)0);
			GearActionBar.Register("priority", "Upgr. Sort", 110, (Action)PriorityGUI.ToggleWindowStatic, (UIButtonStyle)1);
			_barRegistered = true;
		}
	}

	private void OnDestroy()
	{
		ConfigManager.Dispose();
		GearActionBar.Unregister("filter");
		GearActionBar.Unregister("priority");
		_barRegistered = false;
	}
}
[Serializable]
public class PriorityData
{
	public List<int> order;

	public PriorityData()
	{
		order = new List<int>
		{
			0, 1, 2, 3, 7, 8, 9, 10, 11, 12,
			14, 4, 5, 6
		};
	}

	public string ToJson()
	{
		return JsonUtility.ToJson((object)this);
	}

	public static PriorityData FromJson(string json)
	{
		if (string.IsNullOrEmpty(json))
		{
			return new PriorityData();
		}
		return JsonUtility.FromJson<PriorityData>(json);
	}
}
public enum PriorityCriteria
{
	Favorited,
	NotFavorited,
	Unlocked,
	Locked,
	RecentlyUsed,
	RecentlyAcquired,
	InstanceName,
	Oddity,
	Exotic,
	Epic,
	Rare,
	Standard,
	Turbocharged,
	Trashed,
	NotTurbocharged,
	NotTrashed
}
public class PriorityGUI : MonoBehaviour
{
	private static readonly PriorityCriteria[] BaseDefaultOrder = new PriorityCriteria[14]
	{
		PriorityCriteria.Favorited,
		PriorityCriteria.NotFavorited,
		PriorityCriteria.Unlocked,
		PriorityCriteria.Locked,
		PriorityCriteria.Oddity,
		PriorityCriteria.Exotic,
		PriorityCriteria.Epic,
		PriorityCriteria.Rare,
		PriorityCriteria.Standard,
		PriorityCriteria.Turbocharged,
		PriorityCriteria.NotTurbocharged,
		PriorityCriteria.RecentlyUsed,
		PriorityCriteria.RecentlyAcquired,
		PriorityCriteria.InstanceName
	};

	private static readonly PriorityCriteria[] TrashCriteria = new PriorityCriteria[2]
	{
		PriorityCriteria.Trashed,
		PriorityCriteria.NotTrashed
	};

	private UIDragList _list;

	private UIWindow _window;

	private List<PriorityCriteria> currentOrder;

	private bool showWindow;

	public static PriorityGUI Instance { get; private set; }

	private void Awake()
	{
		Instance = this;
		Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
		currentOrder = PriorityPatches.LoadPriorityOrder();
	}

	private void Update()
	{
		if (!PriorityPatches.IsWindowOpen && !GearActionBar.IsGearMenuOpen() && showWindow)
		{
			CloseWindow(reload: true);
		}
	}

	private void OnDestroy()
	{
		if ((Object)(object)Instance == (Object)(object)this)
		{
			Instance = null;
		}
	}

	private static List<PriorityCriteria> BuildDefaultOrder()
	{
		List<PriorityCriteria> list = BaseDefaultOrder.ToList();
		if (PriorityPatches.IsBatchScrappingPresent())
		{
			int num = list.IndexOf(PriorityCriteria.Locked);
			if (num < 0)
			{
				num = list.Count - 1;
			}
			list.InsertRange(num + 1, TrashCriteria);
		}
		return list;
	}

	public static void EnsureExists()
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		PriorityGUI priorityGUI = Object.FindObjectOfType<PriorityGUI>();
		if ((Object)(object)priorityGUI != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)priorityGUI).gameObject);
			Instance = null;
		}
		new GameObject("PriorityGUI").AddComponent<PriorityGUI>();
	}

	public static void ToggleWindowStatic()
	{
		if (!((Object)(object)Instance == (Object)null))
		{
			Instance.ToggleWindow();
		}
	}

	private void ToggleWindow()
	{
		if (showWindow)
		{
			CloseWindow(reload: true);
		}
		else
		{
			OpenWindow();
		}
	}

	private void OpenWindow()
	{
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e5: Expected O, but got Unknown
		showWindow = true;
		currentOrder = PriorityPatches.LoadPriorityOrder();
		if (currentOrder == null || currentOrder.Count == 0)
		{
			currentOrder = BuildDefaultOrder();
		}
		else
		{
			currentOrder = PriorityPatches.FilterOrderForAvailableMods(currentOrder);
		}
		if (_window == null)
		{
			_window = UIWindow.Create("SortPriority", (Vector2?)new Vector2(340f, 560f), "Sort Priority", false, true, (int?)null);
			_window.OnClose((Action)delegate
			{
				CloseWindow(reload: true);
			});
			Transform content = _window.Content;
			UIFactory.AddVerticalLayout(((Component)content).gameObject, UITheme.S(8f), UITheme.ScaledPadding(8, 8, 8, 8), (TextAnchor)0, true, false, true, true);
			UIText.Create(content, "Hint", "Higher = applied first. Put rarities above Name/Recently* or they won't matter.", UITheme.ScaledFontSmall, (Color?)UIColors.TextSecondary, (TextAlignmentOptions)513, false);
			_list = UIDragList.Create(content, "PriorityList");
			GameObject gameObject = _list.GameObject;
			float? num = UITheme.S(400f);
			float? num2 = UITheme.S(280f);
			UIHelpers.EnsureLayoutElement(gameObject, (float?)null, num, num2);
			LayoutElement component = _list.GameObject.GetComponent<LayoutElement>();
			if ((Object)(object)component != (Object)null)
			{
				component.flexibleHeight = 1f;
			}
			_list.OnReordered((Action<int, int>)delegate(int from, int to)
			{
				if (from >= 0 && to >= 0 && from < currentOrder.Count && to < currentOrder.Count)
				{
					PriorityCriteria item = currentOrder[from];
					currentOrder.RemoveAt(from);
					currentOrder.Insert(to, item);
				}
			});
			RectTransform obj = UIFactory.CreateRect("Buttons", content);
			GameObject gameObject2 = ((Component)obj).gameObject;
			num2 = UITheme.ScaledButtonHeight + UITheme.S(4f);
			UIHelpers.EnsureLayoutElement(gameObject2, (float?)null, num2, (float?)null);
			UIFactory.AddHorizontalLayout(((Component)obj).gameObject, UITheme.S(8f), new RectOffset(0, 0, 0, 0), (TextAnchor)4, false, false, true, true);
			UIButton.Create((Transform)(object)obj, "Save", (Action)delegate
			{
				PriorityPatches.SavePriorityOrder(currentOrder);
				PriorityPatches.TriggerPrioritySort(currentOrder);
				CloseWindow(reload: false);
			}, (UIButtonStyle)1, (string)null, (float?)null).SetWidth(UITheme.S(90f));
			UIButton.Create((Transform)(object)obj, "Cancel", (Action)delegate
			{
				CloseWindow(reload: true);
			}, (UIButtonStyle)0, (string)null, (float?)null).SetWidth(UITheme.S(90f));
			UIButton.Create((Transform)(object)obj, "Reset", (Action)delegate
			{
				currentOrder = BuildDefaultOrder();
				RefreshList();
			}, (UIButtonStyle)2, (string)null, (float?)null).SetWidth(UITheme.S(90f));
		}
		RefreshList();
		_window.Show();
	}

	private void RefreshList()
	{
		if (_list == null || currentOrder == null)
		{
			return;
		}
		List<string> list = new List<string>();
		foreach (PriorityCriteria item in currentOrder)
		{
			list.Add(GetCriteriaName(item));
		}
		_list.SetItems((IList<string>)list);
	}

	private void CloseWindow(bool reload)
	{
		showWindow = false;
		if (reload)
		{
			currentOrder = PriorityPatches.LoadPriorityOrder();
		}
		if (_window != null)
		{
			_window.Hide(true);
		}
	}

	private string GetCriteriaName(PriorityCriteria criteria)
	{
		return criteria switch
		{
			PriorityCriteria.Favorited => "Favorited", 
			PriorityCriteria.NotFavorited => "Not Favorited", 
			PriorityCriteria.Unlocked => "Unlocked", 
			PriorityCriteria.Locked => "Locked", 
			PriorityCriteria.RecentlyUsed => "Recently Used", 
			PriorityCriteria.RecentlyAcquired => "Recently Acquired", 
			PriorityCriteria.InstanceName => "Name (tie-break)", 
			PriorityCriteria.Oddity => "Oddity", 
			PriorityCriteria.Exotic => "Exotic", 
			PriorityCriteria.Epic => "Epic", 
			PriorityCriteria.Rare => "Rare", 
			PriorityCriteria.Standard => "Standard", 
			PriorityCriteria.Turbocharged => "Turbocharged", 
			PriorityCriteria.Trashed => "Trashed (BatchScrapping)", 
			PriorityCriteria.NotTurbocharged => "Not Turbocharged", 
			PriorityCriteria.NotTrashed => "Not Trashed (BatchScrapping)", 
			_ => "Unknown", 
		};
	}
}
public static class PriorityPatches
{
	private struct SortEntry
	{
		public GearUpgradeUI Ui;

		public int[] Keys;
	}

	private sealed class SortEntryComparer : IComparer<SortEntry>
	{
		public static readonly SortEntryComparer Instance = new SortEntryComparer();

		public int Compare(SortEntry x, SortEntry y)
		{
			int[] keys = x.Keys;
			int[] keys2 = y.Keys;
			if (keys == null && keys2 == null)
			{
				return 0;
			}
			if (keys == null)
			{
				return 1;
			}
			if (keys2 == null)
			{
				return -1;
			}
			int num = Math.Min(keys.Length, keys2.Length);
			for (int i = 0; i < num; i++)
			{
				int num2 = keys2[i].CompareTo(keys[i]);
				if (num2 != 0)
				{
					return num2;
				}
			}
			return keys.Length.CompareTo(keys2.Length);
		}
	}

	private static List<PriorityCriteria> priorityOrder;

	public static GearDetailsWindow currentWindow;

	private static bool? _batchScrappingPresent;

	private static MethodInfo _isTrashMarkedMethod;

	private static Coroutine _deferredLayoutCoroutine;

	private static bool _deferredLayoutCancelled;

	private static FieldInfo _isGridViewField;

	private static FieldInfo _upgradeListParentField;

	private static bool _layoutLookupsDone;

	public static bool PrioritySortActive { get; private set; }

	public static bool IsWindowOpen { get; private set; }

	static PriorityPatches()
	{
		priorityOrder = new List<PriorityCriteria>();
		priorityOrder = LoadPriorityOrder();
		try
		{
			string value = default(string);
			PrioritySortActive = PlayerOptions.TryGetConfig<string>("SortPriority.Order", ref value) && !string.IsNullOrEmpty(value);
		}
		catch
		{
			PrioritySortActive = false;
		}
	}

	public static bool IsBatchScrappingPresent()
	{
		if (_batchScrappingPresent.HasValue)
		{
			return _batchScrappingPresent.Value;
		}
		try
		{
			foreach (PluginInfo value in Chainloader.PluginInfos.Values)
			{
				object obj;
				if (value == null)
				{
					obj = null;
				}
				else
				{
					BepInPlugin metadata = value.Metadata;
					obj = ((metadata != null) ? metadata.GUID : null);
				}
				if ((string?)obj == "sparroh.batchscrapping")
				{
					_batchScrappingPresent = true;
					CacheTrashApi();
					return true;
				}
			}
		}
		catch
		{
		}
		try
		{
			if (AccessTools.TypeByName("ScrapHandlingMod") != null)
			{
				_batchScrappingPresent = true;
				CacheTrashApi();
				return true;
			}
		}
		catch
		{
		}
		_batchScrappingPresent = false;
		return false;
	}

	private static void CacheTrashApi()
	{
		try
		{
			Type type = AccessTools.TypeByName("ScrapHandlingMod");
			_isTrashMarkedMethod = ((type != null) ? AccessTools.Method(type, "IsTrashMarked", new Type[1] { typeof(UpgradeInstance) }, (Type[])null) : null);
		}
		catch
		{
			_isTrashMarkedMethod = null;
		}
	}

	public static bool IsTrashMarked(UpgradeInstance instance)
	{
		if (instance == null || !IsBatchScrappingPresent())
		{
			return false;
		}
		if (_isTrashMarkedMethod != null)
		{
			try
			{
				return (bool)_isTrashMarkedMethod.Invoke(null, new object[1] { instance });
			}
			catch
			{
			}
		}
		try
		{
			FieldInfo fieldInfo = AccessTools.Field(typeof(UpgradeInstance), "flags");
			if (fieldInfo == null)
			{
				return false;
			}
			return (Convert.ToByte(fieldInfo.GetValue(instance)) & 0x20) != 0;
		}
		catch
		{
			return false;
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(GearDetailsWindow), "OnOpen")]
	public static void OnOpen_Postfix(GearDetailsWindow __instance)
	{
		IsWindowOpen = true;
		currentWindow = __instance;
		if (PrioritySortActive)
		{
			try
			{
				ApplyPrioritySort(__instance, priorityOrder, resetScroll: false);
				return;
			}
			catch (Exception ex)
			{
				UpgradeFilteringPlugin.Logger.LogWarning((object)("Priority sort on open failed: " + ex.Message));
				return;
			}
		}
		try
		{
			FilterState.ApplyToWindow(__instance);
		}
		catch
		{
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(GearDetailsWindow), "OnCloseCallback")]
	public static void OnCloseCallback_Postfix()
	{
		IsWindowOpen = false;
		currentWindow = null;
	}

	public static bool SortUpgradesInt_Prefix(int i)
	{
		if (PrioritySortActive)
		{
			PrioritySortActive = false;
			UpgradeFilteringPlugin.Logger.LogInfo((object)$"Priority sort disabled (vanilla sort button {i}).");
		}
		return true;
	}

	public static bool SortUpgradesMethod_Prefix(GearDetailsWindow __instance, SortingMethod method, bool resetScroll)
	{
		if (!PrioritySortActive)
		{
			return true;
		}
		if (ListRebuildReapply.SuppressNestedReapply)
		{
			return true;
		}
		try
		{
			ApplyPrioritySort(__instance, priorityOrder, resetScroll);
			return false;
		}
		catch (Exception ex)
		{
			UpgradeFilteringPlugin.Logger.LogError((object)("Priority sort prefix failed: " + ex.Message + "\n" + ex.StackTrace));
			return true;
		}
	}

	public static bool SortUpgradesMethodPublic_Prefix(GearDetailsWindow __instance, SortingMethod method)
	{
		if (!PrioritySortActive)
		{
			return true;
		}
		if (ListRebuildReapply.SuppressNestedReapply)
		{
			return true;
		}
		try
		{
			ApplyPrioritySort(__instance, priorityOrder);
			return false;
		}
		catch (Exception ex)
		{
			UpgradeFilteringPlugin.Logger.LogError((object)("Priority sort public prefix failed: " + ex.Message));
			return true;
		}
	}

	public static void Patch(Harmony harmony)
	{
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Expected O, but got Unknown
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Expected O, but got Unknown
		//IL_0118: Unknown result type (might be due to invalid IL or missing references)
		//IL_0126: Expected O, but got Unknown
		MethodInfo methodInfo = AccessTools.Method(typeof(GearDetailsWindow), "SortUpgrades", new Type[1] { typeof(int) }, (Type[])null);
		if (methodInfo != null)
		{
			harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(PriorityPatches), "SortUpgradesInt_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		else
		{
			UpgradeFilteringPlugin.Logger.LogWarning((object)"Could not find SortUpgrades(int).");
		}
		MethodInfo methodInfo2 = AccessTools.Method(typeof(GearDetailsWindow), "SortUpgrades", new Type[2]
		{
			typeof(SortingMethod),
			typeof(bool)
		}, (Type[])null);
		if (methodInfo2 != null)
		{
			harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(PriorityPatches), "SortUpgradesMethod_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			UpgradeFilteringPlugin.Logger.LogInfo((object)"Patched SortUpgrades(SortingMethod, bool) for sticky priority.");
			return;
		}
		MethodInfo methodInfo3 = AccessTools.Method(typeof(GearDetailsWindow), "SortUpgrades", new Type[1] { typeof(SortingMethod) }, (Type[])null);
		if (methodInfo3 != null)
		{
			harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(typeof(PriorityPatches), "SortUpgradesMethodPublic_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		else
		{
			UpgradeFilteringPlugin.Logger.LogWarning((object)"Could not find SortUpgrades(SortingMethod) — sticky priority may not hook vanilla sorts.");
		}
	}

	public static void TriggerPrioritySort(List<PriorityCriteria> order = null)
	{
		if (order != null && order.Count > 0)
		{
			priorityOrder = new List<PriorityCriteria>(order);
		}
		else
		{
			priorityOrder = LoadPriorityOrder();
		}
		PrioritySortActive = true;
		GearDetailsWindow val = ResolveWindow();
		if ((Object)(object)val == (Object)null)
		{
			UpgradeFilteringPlugin.Logger.LogWarning((object)"Priority sort: no GearDetailsWindow found — order saved; will apply next open.");
			return;
		}
		currentWindow = val;
		ApplyPrioritySort(val, priorityOrder);
	}

	public static GearDetailsWindow ResolveWindow()
	{
		if ((Object)(object)currentWindow != (Object)null)
		{
			try
			{
				if ((Object)(object)((Component)currentWindow).gameObject != (Object)null && ((Component)currentWindow).gameObject.activeInHierarchy)
				{
					return currentWindow;
				}
			}
			catch
			{
				currentWindow = null;
			}
		}
		GearDetailsWindow openWindow = FilterState.GetOpenWindow();
		if ((Object)(object)openWindow != (Object)null)
		{
			return openWindow;
		}
		try
		{
			return Object.FindObjectOfType<GearDetailsWindow>();
		}
		catch
		{
			return null;
		}
	}

	public static void ApplyPrioritySort(GearDetailsWindow window, bool resetScroll = true, bool skipDeferred = false)
	{
		ApplyPrioritySort(window, priorityOrder ?? LoadPriorityOrder(), resetScroll, skipDeferred);
	}

	public static void CancelDeferredLayout()
	{
		_deferredLayoutCancelled = true;
		try
		{
			if (_deferredLayoutCoroutine != null && (Object)(object)PriorityGUI.Instance != (Object)null)
			{
				((MonoBehaviour)PriorityGUI.Instance).StopCoroutine(_deferredLayoutCoroutine);
				_deferredLayoutCoroutine = null;
			}
		}
		catch
		{
		}
	}

	public static void ApplyPrioritySort(GearDetailsWindow window, List<PriorityCriteria> order, bool resetScroll = true, bool skipDeferred = false)
	{
		if ((Object)(object)window == (Object)null)
		{
			return;
		}
		PrioritySortActive = true;
		if (order != null && order.Count > 0)
		{
			priorityOrder = new List<PriorityCriteria>(order);
		}
		List<PriorityCriteria> list = FilterOrderForAvailableMods(priorityOrder);
		List<GearUpgradeUI> upgradeUIs = FilterState.GetUpgradeUIs();
		if (upgradeUIs == null || upgradeUIs.Count == 0)
		{
			UpgradeFilteringPlugin.Logger.LogWarning((object)"Priority sort: upgradeUIs empty.");
			return;
		}
		int num = FilterState.GetUpgradeUICount(window);
		if (num <= 0 || num > upgradeUIs.Count)
		{
			num = upgradeUIs.Count;
		}
		UpgradeFilteringPlugin.Logger.LogInfo((object)($"Sort begin (visual-only): window={((Object)window).name}, listCount={upgradeUIs.Count}, uiCount={num}, " + "criteria=[" + string.Join(" > ", list) + "]"));
		ActivateAllLiveSlots(upgradeUIs, num);
		if (!LogUniqueInstanceIds("BEFORE visual sort", upgradeUIs, num) && !TryRepairDuplicateUiRefs(window, upgradeUIs, num))
		{
			UpgradeFilteringPlugin.Logger.LogError((object)"Pool corrupt and repair failed — skip visual reorder; reopen gear window.");
			FilterState.ApplyVisibilityOnly(window);
			return;
		}
		FilterState.ApplyVisibilityOnly(window);
		ApplyVisualPriorityOrder(window, upgradeUIs, num, list);
		LogRowSnapshot("AFTER visual priority+filter", upgradeUIs, num);
		if (resetScroll)
		{
			try
			{
				typeof(GearDetailsWindow).GetMethod("SetUpgradeListScroll", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(float) }, null)?.Invoke(window, new object[1] { 1f });
			}
			catch (Exception ex)
			{
				UpgradeFilteringPlugin.Logger.LogWarning((object)("SetUpgradeListScroll failed: " + ex.Message));
			}
		}
		try
		{
			typeof(GearDetailsWindow).GetMethod("DisableSortButtonContainer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null)?.Invoke(window, null);
		}
		catch
		{
		}
	}

	public static void ClearStalePoolSlots(List<GearUpgradeUI> upgradeUIs, int liveCount)
	{
		if (upgradeUIs == null)
		{
			return;
		}
		liveCount = Mathf.Max(0, liveCount);
		int num = 0;
		for (int i = liveCount; i < upgradeUIs.Count; i++)
		{
			GearUpgradeUI val = upgradeUIs[i];
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			try
			{
				if (((Component)val).gameObject.activeSelf)
				{
					((Component)val).gameObject.SetActive(false);
				}
				if (((HoverInfoUpgrade)val).Upgrade != null)
				{
					((HoverInfoUpgrade)val).Upgrade = null;
					num++;
				}
			}
			catch
			{
				try
				{
					((Component)val).gameObject.SetActive(false);
				}
				catch
				{
				}
			}
		}
		if (num > 0)
		{
			UpgradeFilteringPlugin.Logger.LogInfo((object)$"ClearStalePoolSlots: cleared Upgrade on {num} slots past liveCount={liveCount}");
		}
	}

	public static bool TryRepairDuplicateUiRefs(GearDetailsWindow window, List<GearUpgradeUI> upgradeUIs, int count)
	{
		if (upgradeUIs == null || (Object)(object)window == (Object)null || count <= 0)
		{
			return true;
		}
		count = Mathf.Min(count, upgradeUIs.Count);
		HashSet<GearUpgradeUI> hashSet = new HashSet<GearUpgradeUI>();
		List<int> list = new List<int>();
		for (int i = 0; i < count; i++)
		{
			GearUpgradeUI val = upgradeUIs[i];
			if ((Object)(object)val == (Object)null)
			{
				list.Add(i);
			}
			else if (!hashSet.Add(val))
			{
				list.Add(i);
			}
		}
		if (list.Count == 0)
		{
			return true;
		}
		UpgradeFilteringPlugin.Logger.LogWarning((object)$"Repairing {list.Count} duplicate/null GearUpgradeUI refs in live pool.");
		Queue<GearUpgradeUI> queue = new Queue<GearUpgradeUI>();
		for (int j = 0; j < upgradeUIs.Count; j++)
		{
			GearUpgradeUI val2 = upgradeUIs[j];
			if (!((Object)(object)val2 == (Object)null) && !hashSet.Contains(val2))
			{
				queue.Enqueue(val2);
			}
		}
		RectTransform val3 = null;
		try
		{
			EnsureLayoutLookups();
			object? obj = _upgradeListParentField?.GetValue(window);
			val3 = (RectTransform)((obj is RectTransform) ? obj : null);
		}
		catch
		{
		}
		FieldInfo fieldInfo = null;
		try
		{
			fieldInfo = typeof(GearDetailsWindow).GetField("upgradeUIPrefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		}
		catch
		{
		}
		foreach (int item in list)
		{
			GearUpgradeUI obj4 = upgradeUIs[item];
			UpgradeInstance val4 = ((obj4 != null) ? ((HoverInfoUpgrade)obj4).Upgrade : null);
			GearUpgradeUI val5 = null;
			if (queue.Count > 0)
			{
				val5 = queue.Dequeue();
			}
			else if (fieldInfo != null && (Object)(object)val3 != (Object)null)
			{
				try
				{
					object? value = fieldInfo.GetValue(window);
					GearUpgradeUI val6 = (GearUpgradeUI)((value is GearUpgradeUI) ? value : null);
					if ((Object)(object)val6 != (Object)null)
					{
						val5 = Object.Instantiate<GearUpgradeUI>(val6, (Transform)(object)val3);
						upgradeUIs.Add(val5);
					}
				}
				catch (Exception ex)
				{
					UpgradeFilteringPlugin.Logger.LogWarning((object)("Instantiate repair UI failed: " + ex.Message));
				}
			}
			if ((Object)(object)val5 == (Object)null)
			{
				UpgradeFilteringPlugin.Logger.LogError((object)$"Could not repair duplicate at index {item}");
				return false;
			}
			upgradeUIs[item] = val5;
			hashSet.Add(val5);
			try
			{
				if (val4 != null)
				{
					((Component)val5).gameObject.SetActive(true);
					val5.SetUpgrade(val4, false);
					val5.EnableGridView(GetIsGridView(window));
				}
				else
				{
					((Component)val5).gameObject.SetActive(false);
				}
			}
			catch
			{
			}
		}
		return LogUniqueInstanceIds("AFTER pool ref repair", upgradeUIs, count);
	}

	public static void ActivateAllLiveSlots(List<GearUpgradeUI> upgradeUIs, int count)
	{
		if (upgradeUIs == null)
		{
			return;
		}
		count = Mathf.Min(count, upgradeUIs.Count);
		ClearStalePoolSlots(upgradeUIs, count);
		bool isGridView = GetIsGridView(currentWindow);
		int num = 0;
		for (int i = 0; i < count; i++)
		{
			GearUpgradeUI val = upgradeUIs[i];
			object obj;
			if (val == null)
			{
				obj = null;
			}
			else
			{
				UpgradeInstance upgrade = ((HoverInfoUpgrade)val).Upgrade;
				obj = ((upgrade != null) ? upgrade.Upgrade : null);
			}
			if ((Object)obj == (Object)null)
			{
				continue;
			}
			try
			{
				if (!((Component)val).gameObject.activeSelf)
				{
					((Component)val).gameObject.SetActive(true);
					num++;
				}
				val.EnableGridView(isGridView);
			}
			catch
			{
			}
		}
		UpgradeFilteringPlugin.Logger.LogInfo((object)$"ActivateAllLiveSlots: count={count}, reactivated={num}, isGrid={isGridView}");
	}

	public static void ApplyVisualPriorityOrder(GearDetailsWindow window, List<GearUpgradeUI> upgradeUIs, int count, List<PriorityCriteria> order)
	{
		if ((Object)(object)window == (Object)null || upgradeUIs == null)
		{
			return;
		}
		count = Mathf.Min(count, upgradeUIs.Count);
		List<(GearUpgradeUI, int[])> list = new List<(GearUpgradeUI, int[])>(count);
		for (int i = 0; i < count; i++)
		{
			GearUpgradeUI val = upgradeUIs[i];
			if ((Object)(object)val == (Object)null || !((Component)val).gameObject.activeSelf)
			{
				continue;
			}
			UpgradeInstance upgrade = ((HoverInfoUpgrade)val).Upgrade;
			if ((Object)(object)((upgrade != null) ? upgrade.Upgrade : null) == (Object)null || !FilterState.ShouldShow(val))
			{
				continue;
			}
			int[] array = new int[(order?.Count ?? 0) + 2];
			int num = 0;
			if (order != null)
			{
				foreach (PriorityCriteria item4 in order)
				{
					array[num++] = ScoreCriteria(val, item4);
				}
			}
			array[num++] = ((HoverInfoUpgrade)val).Upgrade.InstanceID;
			array[num] = -i;
			list.Add((val, array));
		}
		list.Sort(delegate((GearUpgradeUI ui, int[] keys) a, (GearUpgradeUI ui, int[] keys) b)
		{
			int[] item2 = a.keys;
			int[] item3 = b.keys;
			int num5 = Math.Min(item2.Length, item3.Length);
			for (int j = 0; j < num5; j++)
			{
				int num6 = item3[j].CompareTo(item2[j]);
				if (num6 != 0)
				{
					return num6;
				}
			}
			return 0;
		});
		EnsureLayoutLookups();
		bool isGridView = GetIsGridView(window);
		RectTransform listParent = null;
		try
		{
			object? obj = _upgradeListParentField?.GetValue(window);
			listParent = (RectTransform)((obj is RectTransform) ? obj : null);
		}
		catch
		{
		}
		for (int num2 = 0; num2 < count; num2++)
		{
			try
			{
				GearUpgradeUI obj3 = upgradeUIs[num2];
				if (obj3 != null)
				{
					((Component)obj3).transform.SetAsLastSibling();
				}
			}
			catch
			{
			}
		}
		for (int num3 = 0; num3 < list.Count; num3++)
		{
			GearUpgradeUI item = list[num3].Item1;
			try
			{
				((Component)item).transform.SetSiblingIndex(num3);
				item.EnableGridView(isGridView);
				SetUpgradeAnchoredPosition(item, num3, isGridView, listParent);
			}
			catch (Exception ex)
			{
				UpgradeFilteringPlugin.Logger.LogWarning((object)("Visual order place failed: " + ex.Message));
			}
		}
		int count2 = list.Count;
		for (int num4 = 0; num4 < count; num4++)
		{
			GearUpgradeUI val2 = upgradeUIs[num4];
			if (!((Object)(object)val2 == (Object)null) && !((Component)val2).gameObject.activeSelf)
			{
				try
				{
					((Component)val2).transform.SetSiblingIndex(count2++);
				}
				catch
				{
				}
			}
		}
		try
		{
			Canvas.ForceUpdateCanvases();
		}
		catch
		{
		}
		UpgradeFilteringPlugin.Logger.LogInfo((object)$"Visual priority order: visiblePlaced={list.Count}, isGrid={isGridView}");
	}

	private static IEnumerator DeferredLayout(GearDetailsWindow window)
	{
		yield return null;
		_deferredLayoutCoroutine = null;
		if (_deferredLayoutCancelled || (Object)(object)window == (Object)null)
		{
			yield break;
		}
		try
		{
			if (FilterState.HasActiveFilters() || PrioritySortActive)
			{
				FilterState.ApplyToWindow(window);
			}
			else
			{
				List<GearUpgradeUI> upgradeUIs = FilterState.GetUpgradeUIs();
				int num = FilterState.GetUpgradeUICount(window);
				if (upgradeUIs == null)
				{
					yield break;
				}
				if (num <= 0 || num > upgradeUIs.Count)
				{
					num = upgradeUIs.Count;
				}
				ForceLayout(window, upgradeUIs, num);
			}
			UpgradeFilteringPlugin.Logger.LogInfo((object)"Deferred layout pass complete.");
		}
		catch (Exception ex)
		{
			UpgradeFilteringPlugin.Logger.LogWarning((object)("Deferred layout failed: " + ex.Message));
		}
	}

	internal static void LogRowSnapshot(string label, List<GearUpgradeUI> upgradeUIs, int count)
	{
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0163: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(label).Append(':');
			int num = 0;
			for (int i = 0; i < count; i++)
			{
				if (num >= 6)
				{
					break;
				}
				GearUpgradeUI val = upgradeUIs[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				string value = "?";
				string value2 = "?";
				try
				{
					UpgradeInstance upgrade = ((HoverInfoUpgrade)val).Upgrade;
					if ((Object)(object)((upgrade != null) ? upgrade.Upgrade : null) != (Object)null)
					{
						value = ((HoverInfoUpgrade)val).Upgrade.Upgrade.Name ?? "?";
						value2 = ((object)((HoverInfoUpgrade)val).Upgrade.Upgrade.Rarity/*cast due to .constrained prefix*/).ToString();
					}
				}
				catch
				{
				}
				Transform transform = ((Component)val).transform;
				RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
				Vector2 val3 = (((Object)(object)val2 != (Object)null) ? val2.anchoredPosition : Vector2.zero);
				int siblingIndex = ((Component)val).transform.GetSiblingIndex();
				string value3 = (((Object)(object)((Component)val).transform.parent != (Object)null) ? ((Object)((Component)val).transform.parent).name : "null");
				stringBuilder.Append("\n  [").Append(i).Append("] ")
					.Append(value2)
					.Append(" | ")
					.Append(value)
					.Append(" | active=")
					.Append(((Component)val).gameObject.activeSelf)
					.Append(" | sib=")
					.Append(siblingIndex)
					.Append(" | pos=")
					.Append(val3)
					.Append(" | parent=")
					.Append(value3);
				num++;
			}
			UpgradeFilteringPlugin.Logger.LogInfo((object)stringBuilder.ToString());
		}
		catch (Exception ex)
		{
			UpgradeFilteringPlugin.Logger.LogWarning((object)("LogRowSnapshot failed: " + ex.Message));
		}
	}

	private static void EnsureLayoutLookups()
	{
		if (!_layoutLookupsDone)
		{
			_layoutLookupsDone = true;
			Type? typeFromHandle = typeof(GearDetailsWindow);
			_isGridViewField = typeFromHandle.GetField("isGridView", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			_upgradeListParentField = typeFromHandle.GetField("upgradeListParent", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			UpgradeFilteringPlugin.Logger.LogInfo((object)($"Layout lookups: isGridView={_isGridViewField != null}, " + $"listParent={_upgradeListParentField != null}"));
		}
	}

	internal static bool GetIsGridView(GearDetailsWindow window)
	{
		EnsureLayoutLookups();
		try
		{
			if (_isGridViewField == null)
			{
				return false;
			}
			return _isGridViewField.IsStatic ? ((bool)_isGridViewField.GetValue(null)) : ((bool)_isGridViewField.GetValue(window));
		}
		catch
		{
			return false;
		}
	}

	internal static void ForceLayout(GearDetailsWindow window, List<GearUpgradeUI> upgradeUIs, int count)
	{
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_0288: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0355: Unknown result type (might be due to invalid IL or missing references)
		//IL_035e: Unknown result type (might be due to invalid IL or missing references)
		if (upgradeUIs == null || (Object)(object)window == (Object)null)
		{
			return;
		}
		count = Mathf.Min(count, upgradeUIs.Count);
		EnsureLayoutLookups();
		bool flag = false;
		try
		{
			if (_isGridViewField != null)
			{
				flag = (_isGridViewField.IsStatic ? ((bool)_isGridViewField.GetValue(null)) : ((bool)_isGridViewField.GetValue(window)));
			}
		}
		catch (Exception ex)
		{
			UpgradeFilteringPlugin.Logger.LogWarning((object)("isGridView read failed: " + ex.Message));
		}
		RectTransform val = null;
		try
		{
			object? obj = _upgradeListParentField?.GetValue(window);
			val = (RectTransform)((obj is RectTransform) ? obj : null);
		}
		catch (Exception ex2)
		{
			UpgradeFilteringPlugin.Logger.LogWarning((object)("upgradeListParent read failed: " + ex2.Message));
		}
		string text = null;
		try
		{
			if (count > 0)
			{
				GearUpgradeUI obj2 = upgradeUIs[0];
				object obj3;
				if (obj2 == null)
				{
					obj3 = null;
				}
				else
				{
					UpgradeInstance upgrade = ((HoverInfoUpgrade)obj2).Upgrade;
					obj3 = ((upgrade != null) ? upgrade.Upgrade : null);
				}
				if ((Object)obj3 != (Object)null)
				{
					text = ((HoverInfoUpgrade)upgradeUIs[0]).Upgrade.Upgrade.Name;
				}
			}
		}
		catch
		{
		}
		Vector2 val2 = default(Vector2);
		if (count > 0 && (Object)(object)upgradeUIs[0] != (Object)null)
		{
			Transform transform = ((Component)upgradeUIs[0]).transform;
			RectTransform val3 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			if ((Object)(object)val3 != (Object)null)
			{
				val2 = val3.anchoredPosition;
			}
		}
		for (int i = 0; i < count; i++)
		{
			GearUpgradeUI val4 = upgradeUIs[i];
			if (!((Object)(object)val4 == (Object)null))
			{
				try
				{
					((Component)val4).transform.SetAsLastSibling();
				}
				catch
				{
				}
			}
		}
		int num = 0;
		for (int j = 0; j < count; j++)
		{
			GearUpgradeUI val5 = upgradeUIs[j];
			if ((Object)(object)val5 == (Object)null)
			{
				continue;
			}
			try
			{
				((Component)val5).transform.SetSiblingIndex(j);
			}
			catch (Exception ex3)
			{
				UpgradeFilteringPlugin.Logger.LogWarning((object)$"Sibling set failed @ {j}: {ex3.Message}");
			}
			if (((Component)val5).gameObject.activeSelf)
			{
				try
				{
					val5.EnableGridView(flag);
					SetUpgradeAnchoredPosition(val5, num, flag, val);
				}
				catch (Exception ex4)
				{
					UpgradeFilteringPlugin.Logger.LogWarning((object)$"Inline pos failed @ {j}: {ex4.Message}");
				}
				num++;
			}
		}
		try
		{
			Canvas.ForceUpdateCanvases();
		}
		catch
		{
		}
		string text2 = null;
		try
		{
			if (count > 0)
			{
				GearUpgradeUI obj7 = upgradeUIs[0];
				object obj8;
				if (obj7 == null)
				{
					obj8 = null;
				}
				else
				{
					UpgradeInstance upgrade2 = ((HoverInfoUpgrade)obj7).Upgrade;
					obj8 = ((upgrade2 != null) ? upgrade2.Upgrade : null);
				}
				if ((Object)obj8 != (Object)null)
				{
					text2 = ((HoverInfoUpgrade)upgradeUIs[0]).Upgrade.Upgrade.Name;
				}
			}
		}
		catch
		{
		}
		Vector2 val6 = default(Vector2);
		if (count > 0 && (Object)(object)upgradeUIs[0] != (Object)null)
		{
			Transform transform2 = ((Component)upgradeUIs[0]).transform;
			RectTransform val7 = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null);
			if ((Object)(object)val7 != (Object)null)
			{
				val6 = val7.anchoredPosition;
			}
		}
		if (text != null && text2 != null && text != text2)
		{
			UpgradeFilteringPlugin.Logger.LogError((object)("ForceLayout mutated list head! '" + text + "' -> '" + text2 + "'"));
		}
		UpgradeFilteringPlugin.Logger.LogInfo((object)(string.Format("ForceLayout done: isGrid={0}, listParent={1}, ", flag, ((Object)(object)val != (Object)null) ? ((Object)val).name : "null") + $"visiblePlaced={num}, head={text2}, firstPos {val2} -> {val6}"));
	}

	private static void SetUpgradeAnchoredPosition(GearUpgradeUI ui, int index, bool isGrid, RectTransform listParent)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		RectTransform val = (RectTransform)((Component)ui).transform;
		Rect rect = val.rect;
		float num;
		if (!(((Rect)(ref rect)).height > 1f))
		{
			num = 52f;
		}
		else
		{
			rect = val.rect;
			num = ((Rect)(ref rect)).height;
		}
		float num2 = num;
		rect = val.rect;
		float num3;
		if (!(((Rect)(ref rect)).width > 1f))
		{
			num3 = 300f;
		}
		else
		{
			rect = val.rect;
			num3 = ((Rect)(ref rect)).width;
		}
		float num4 = num3;
		if (isGrid && (Object)(object)listParent != (Object)null)
		{
			float num5 = num4 + 10f;
			rect = listParent.rect;
			float num6;
			if (!(((Rect)(ref rect)).width > 1f))
			{
				num6 = 400f;
			}
			else
			{
				rect = listParent.rect;
				num6 = ((Rect)(ref rect)).width;
			}
			int num7 = Mathf.Max(Mathf.FloorToInt((num6 - 6f) / num5), 1);
			float num8 = 3f + (float)(index % num7) * (num4 + 10f);
			float num9 = -3f - (float)(index / num7) * (num2 + 10f);
			val.anchoredPosition = new Vector2(num8, num9);
		}
		else
		{
			Vector2 offsetMin = val.offsetMin;
			Vector2 offsetMax = val.offsetMax;
			val.offsetMin = new Vector2(0f, offsetMin.y);
			val.offsetMax = new Vector2(0f, offsetMax.y);
			val.anchoredPosition = new Vector2(0f, -3f - (num2 + 4f) * (float)index);
		}
	}

	public static List<PriorityCriteria> FilterOrderForAvailableMods(List<PriorityCriteria> order)
	{
		if (order == null)
		{
			return new List<PriorityCriteria>();
		}
		List<PriorityCriteria> list = new List<PriorityCriteria>(order.Count);
		bool flag = IsBatchScrappingPresent();
		foreach (PriorityCriteria item in order)
		{
			if (flag || (item != PriorityCriteria.Trashed && item != PriorityCriteria.NotTrashed))
			{
				list.Add(item);
			}
		}
		return MigrateTotalKeysAfterRarities(list);
	}

	public static List<PriorityCriteria> MigrateTotalKeysAfterRarities(List<PriorityCriteria> order)
	{
		if (order == null || order.Count == 0)
		{
			return order ?? new List<PriorityCriteria>();
		}
		int num = -1;
		int num2 = -1;
		for (int i = 0; i < order.Count; i++)
		{
			if (IsRarity(order[i]))
			{
				if (num < 0)
				{
					num = i;
				}
				num2 = i;
			}
		}
		if (num < 0)
		{
			return order;
		}
		bool flag = false;
		for (int j = 0; j < order.Count; j++)
		{
			if (IsTotalKey(order[j]) && j < num2)
			{
				flag = true;
				break;
			}
		}
		if (!flag)
		{
			return order;
		}
		List<PriorityCriteria> list = new List<PriorityCriteria>(order.Count);
		List<PriorityCriteria> list2 = new List<PriorityCriteria>(4);
		foreach (PriorityCriteria item in order)
		{
			if (IsTotalKey(item))
			{
				list2.Add(item);
			}
			else
			{
				list.Add(item);
			}
		}
		list.AddRange(list2);
		UpgradeFilteringPlugin.Logger.LogInfo((object)"Migrated sort order: moved Name/Recently* after rarities so rarity criteria apply.");
		return list;
		static bool IsRarity(PriorityCriteria c)
		{
			if ((uint)(c - 7) <= 4u)
			{
				return true;
			}
			return false;
		}
		static bool IsTotalKey(PriorityCriteria c)
		{
			if ((uint)(c - 4) <= 2u)
			{
				return true;
			}
			return false;
		}
	}

	public static bool TryDecorateSortLiveSlice(List<GearUpgradeUI> upgradeUIs, int count, List<PriorityCriteria> order)
	{
		if (upgradeUIs == null || count <= 0)
		{
			return true;
		}
		count = Mathf.Min(count, upgradeUIs.Count);
		int num = count;
		SortEntry[] array = new SortEntry[num];
		int num2 = (order?.Count ?? 0) + 2;
		for (int i = 0; i < num; i++)
		{
			GearUpgradeUI val = upgradeUIs[i];
			int[] array2 = new int[num2];
			int num3 = 0;
			if (order != null)
			{
				foreach (PriorityCriteria item in order)
				{
					array2[num3++] = ScoreCriteria(val, item);
				}
			}
			array2[num3++] = ((((val != null) ? ((HoverInfoUpgrade)val).Upgrade : null) != null) ? ((HoverInfoUpgrade)val).Upgrade.InstanceID : int.MinValue);
			array2[num3] = -i;
			array[i] = new SortEntry
			{
				Ui = val,
				Keys = array2
			};
		}
		Array.Sort(array, SortEntryComparer.Instance);
		HashSet<int> hashSet = new HashSet<int>();
		HashSet<int> hashSet2 = new HashSet<int>();
		for (int j = 0; j < num; j++)
		{
			GearUpgradeUI obj = upgradeUIs[j];
			if (((obj != null) ? ((HoverInfoUpgrade)obj).Upgrade : null) != null)
			{
				hashSet.Add(((HoverInfoUpgrade)upgradeUIs[j]).Upgrade.InstanceID);
			}
			GearUpgradeUI ui = array[j].Ui;
			if (((ui != null) ? ((HoverInfoUpgrade)ui).Upgrade : null) != null)
			{
				hashSet2.Add(((HoverInfoUpgrade)array[j].Ui).Upgrade.InstanceID);
			}
		}
		if (hashSet.Count != hashSet2.Count || !hashSet.SetEquals(hashSet2))
		{
			UpgradeFilteringPlugin.Logger.LogError((object)$"Decorate-sort validation failed: beforeIds={hashSet.Count} afterIds={hashSet2.Count}");
			return false;
		}
		HashSet<GearUpgradeUI> hashSet3 = new HashSet<GearUpgradeUI>();
		for (int k = 0; k < num; k++)
		{
			GearUpgradeUI ui2 = array[k].Ui;
			if (!((Object)(object)ui2 == (Object)null) && !hashSet3.Add(ui2))
			{
				UpgradeFilteringPlugin.Logger.LogError((object)"Decorate-sort validation failed: duplicate GearUpgradeUI reference.");
				return false;
			}
		}
		for (int l = 0; l < num; l++)
		{
			upgradeUIs[l] = array[l].Ui;
		}
		return true;
	}

	private static int ScoreCriteria(GearUpgradeUI ui, PriorityCriteria criteria)
	{
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Invalid comparison between Unknown and I4
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Invalid comparison between Unknown and I4
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Invalid comparison between Unknown and I4
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Invalid comparison between Unknown and I4
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Invalid comparison between Unknown and I4
		UpgradeInstance val = ((ui != null) ? ((HoverInfoUpgrade)ui).Upgrade : null);
		if ((Object)(object)((val != null) ? val.Upgrade : null) == (Object)null)
		{
			return int.MinValue;
		}
		return criteria switch
		{
			PriorityCriteria.Favorited => val.Favorite ? 1 : 0, 
			PriorityCriteria.NotFavorited => (!val.Favorite) ? 1 : 0, 
			PriorityCriteria.Unlocked => val.IsUnlocked ? 1 : 0, 
			PriorityCriteria.Locked => (!val.IsUnlocked) ? 1 : 0, 
			PriorityCriteria.Turbocharged => val.IsTurbocharged ? 1 : 0, 
			PriorityCriteria.NotTurbocharged => (!val.IsTurbocharged) ? 1 : 0, 
			PriorityCriteria.Trashed => (!IsTrashMarked(val)) ? 1 : 0, 
			PriorityCriteria.NotTrashed => (!IsTrashMarked(val)) ? 1 : 0, 
			PriorityCriteria.RecentlyAcquired => (int)Math.Max(-2147483648L, Math.Min(2147483647L, val.TimeUnlocked)), 
			PriorityCriteria.RecentlyUsed => (int)(val.TimeUnequipped * 1000f), 
			PriorityCriteria.InstanceName => 0, 
			PriorityCriteria.Oddity => ((int)val.Upgrade.Rarity == 4) ? 1 : 0, 
			PriorityCriteria.Exotic => ((int)val.Upgrade.Rarity == 3) ? 1 : 0, 
			PriorityCriteria.Epic => ((int)val.Upgrade.Rarity == 2) ? 1 : 0, 
			PriorityCriteria.Rare => ((int)val.Upgrade.Rarity == 1) ? 1 : 0, 
			PriorityCriteria.Standard => ((int)val.Upgrade.Rarity == 0) ? 1 : 0, 
			_ => 0, 
		};
	}

	public static Comparison<GearUpgradeUI> GetPriorityComparison(List<PriorityCriteria> order)
	{
		return delegate(GearUpgradeUI a, GearUpgradeUI b)
		{
			if (a == b)
			{
				return 0;
			}
			if ((Object)(object)a == (Object)null)
			{
				return 1;
			}
			if ((Object)(object)b == (Object)null)
			{
				return -1;
			}
			if (((HoverInfoUpgrade)a).Upgrade == null && ((HoverInfoUpgrade)b).Upgrade == null)
			{
				return 0;
			}
			if (((HoverInfoUpgrade)a).Upgrade == null)
			{
				return 1;
			}
			if (((HoverInfoUpgrade)b).Upgrade == null)
			{
				return -1;
			}
			if ((Object)(object)((HoverInfoUpgrade)a).Upgrade.Upgrade == (Object)null && (Object)(object)((HoverInfoUpgrade)b).Upgrade.Upgrade == (Object)null)
			{
				return 0;
			}
			if ((Object)(object)((HoverInfoUpgrade)a).Upgrade.Upgrade == (Object)null)
			{
				return 1;
			}
			if ((Object)(object)((HoverInfoUpgrade)b).Upgrade.Upgrade == (Object)null)
			{
				return -1;
			}
			if (order != null)
			{
				foreach (PriorityCriteria item in order)
				{
					int value = ScoreCriteria(a, item);
					int num = ScoreCriteria(b, item).CompareTo(value);
					if (num != 0)
					{
						return num;
					}
				}
			}
			return ((HoverInfoUpgrade)a).Upgrade.InstanceID.CompareTo(((HoverInfoUpgrade)b).Upgrade.InstanceID);
		};
	}

	public static bool LogUniqueInstanceIds(string label, List<GearUpgradeUI> upgradeUIs, int count)
	{
		try
		{
			HashSet<int> hashSet = new HashSet<int>();
			int num = 0;
			for (int i = 0; i < count; i++)
			{
				GearUpgradeUI val = upgradeUIs[i];
				if (((val != null) ? ((HoverInfoUpgrade)val).Upgrade : null) == null)
				{
					num++;
				}
				else
				{
					hashSet.Add(((HoverInfoUpgrade)val).Upgrade.InstanceID);
				}
			}
			if (hashSet.Count + num != count)
			{
				UpgradeFilteringPlugin.Logger.LogError((object)$"{label}: LIST CORRUPTION uniqueIds={hashSet.Count} nulls={num} count={count}");
				return false;
			}
			UpgradeFilteringPlugin.Logger.LogInfo((object)$"{label}: uniqueIds={hashSet.Count} nulls={num} count={count} OK");
			return true;
		}
		catch (Exception ex)
		{
			UpgradeFilteringPlugin.Logger.LogWarning((object)("LogUniqueInstanceIds failed: " + ex.Message));
			return false;
		}
	}

	public static void ForceLayoutVisibleOnly(GearDetailsWindow window, List<GearUpgradeUI> upgradeUIs, int count)
	{
		if ((Object)(object)window == (Object)null || upgradeUIs == null)
		{
			return;
		}
		count = Mathf.Min(count, upgradeUIs.Count);
		EnsureLayoutLookups();
		bool isGridView = GetIsGridView(window);
		RectTransform listParent = null;
		try
		{
			object? obj = _upgradeListParentField?.GetValue(window);
			listParent = (RectTransform)((obj is RectTransform) ? obj : null);
		}
		catch
		{
		}
		int num = 0;
		for (int i = 0; i < count; i++)
		{
			GearUpgradeUI val = upgradeUIs[i];
			if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.activeSelf)
			{
				try
				{
					((Component)val).transform.SetSiblingIndex(num);
					val.EnableGridView(isGridView);
					SetUpgradeAnchoredPosition(val, num, isGridView, listParent);
					num++;
				}
				catch
				{
				}
			}
		}
		try
		{
			Canvas.ForceUpdateCanvases();
		}
		catch
		{
		}
		UpgradeFilteringPlugin.Logger.LogInfo((object)$"ForceLayoutVisibleOnly: visiblePlaced={num}, isGrid={isGridView}");
	}

	public static int CompareByCriteria(GearUpgradeUI a, GearUpgradeUI b, PriorityCriteria criteria)
	{
		//IL_0266: Unknown result type (might be due to invalid IL or missing references)
		//IL_026c: Invalid comparison between Unknown and I4
		//IL_027c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0282: Invalid comparison between Unknown and I4
		//IL_0296: Unknown result type (might be due to invalid IL or missing references)
		//IL_029c: Invalid comparison between Unknown and I4
		//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b2: Invalid comparison between Unknown and I4
		//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cc: Invalid comparison between Unknown and I4
		//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e2: Invalid comparison between Unknown and I4
		//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fc: Invalid comparison between Unknown and I4
		//IL_030c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0312: Invalid comparison between Unknown and I4
		//IL_0326: Unknown result type (might be due to invalid IL or missing references)
		//IL_032c: Invalid comparison between Unknown and I4
		//IL_033c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0342: Invalid comparison between Unknown and I4
		switch (criteria)
		{
		case PriorityCriteria.Favorited:
			return -(((HoverInfoUpgrade)a).Upgrade.Favorite ? 1 : 0).CompareTo(((HoverInfoUpgrade)b).Upgrade.Favorite ? 1 : 0);
		case PriorityCriteria.NotFavorited:
			return -((!((HoverInfoUpgrade)a).Upgrade.Favorite) ? 1 : 0).CompareTo((!((HoverInfoUpgrade)b).Upgrade.Favorite) ? 1 : 0);
		case PriorityCriteria.Unlocked:
			return -((HoverInfoUpgrade)a).Upgrade.IsUnlocked.CompareTo(((HoverInfoUpgrade)b).Upgrade.IsUnlocked);
		case PriorityCriteria.Locked:
			return -((!((HoverInfoUpgrade)a).Upgrade.IsUnlocked) ? 1 : 0).CompareTo((!((HoverInfoUpgrade)b).Upgrade.IsUnlocked) ? 1 : 0);
		case PriorityCriteria.Turbocharged:
		{
			bool isTurbocharged = ((HoverInfoUpgrade)a).Upgrade.IsTurbocharged;
			bool isTurbocharged2 = ((HoverInfoUpgrade)b).Upgrade.IsTurbocharged;
			return -(isTurbocharged ? 1 : 0).CompareTo(isTurbocharged2 ? 1 : 0);
		}
		case PriorityCriteria.Trashed:
		{
			if (!IsBatchScrappingPresent())
			{
				return 0;
			}
			bool num = IsTrashMarked(((HoverInfoUpgrade)a).Upgrade);
			bool flag = IsTrashMarked(((HoverInfoUpgrade)b).Upgrade);
			return (num ? 1 : 0).CompareTo(flag ? 1 : 0);
		}
		case PriorityCriteria.NotTurbocharged:
		{
			bool num3 = !((HoverInfoUpgrade)a).Upgrade.IsTurbocharged;
			bool flag3 = !((HoverInfoUpgrade)b).Upgrade.IsTurbocharged;
			return -(num3 ? 1 : 0).CompareTo(flag3 ? 1 : 0);
		}
		case PriorityCriteria.NotTrashed:
		{
			if (!IsBatchScrappingPresent())
			{
				return 0;
			}
			bool num2 = !IsTrashMarked(((HoverInfoUpgrade)a).Upgrade);
			bool flag2 = !IsTrashMarked(((HoverInfoUpgrade)b).Upgrade);
			return -(num2 ? 1 : 0).CompareTo(flag2 ? 1 : 0);
		}
		case PriorityCriteria.RecentlyAcquired:
			return -((HoverInfoUpgrade)a).Upgrade.TimeUnlocked.CompareTo(((HoverInfoUpgrade)b).Upgrade.TimeUnlocked);
		case PriorityCriteria.RecentlyUsed:
			return -((HoverInfoUpgrade)a).Upgrade.TimeUnequipped.CompareTo(((HoverInfoUpgrade)b).Upgrade.TimeUnequipped);
		case PriorityCriteria.InstanceName:
		{
			string text = ((HoverInfoUpgrade)a).Upgrade.Upgrade.GetInstanceName(((HoverInfoUpgrade)a).Upgrade.Seed);
			if (string.IsNullOrEmpty(text))
			{
				text = ((HoverInfoUpgrade)a).Upgrade.Upgrade.Name;
			}
			string text2 = ((HoverInfoUpgrade)b).Upgrade.Upgrade.GetInstanceName(((HoverInfoUpgrade)b).Upgrade.Seed);
			if (string.IsNullOrEmpty(text2))
			{
				text2 = ((HoverInfoUpgrade)b).Upgrade.Upgrade.Name;
			}
			return string.Compare(text, text2, StringComparison.Ordinal);
		}
		case PriorityCriteria.Oddity:
			return -(((int)((HoverInfoUpgrade)a).Upgrade.Upgrade.Rarity == 4) ? 1 : 0).CompareTo(((int)((HoverInfoUpgrade)b).Upgrade.Upgrade.Rarity == 4) ? 1 : 0);
		case PriorityCriteria.Exotic:
			return -(((int)((HoverInfoUpgrade)a).Upgrade.Upgrade.Rarity == 3) ? 1 : 0).CompareTo(((int)((HoverInfoUpgrade)b).Upgrade.Upgrade.Rarity == 3) ? 1 : 0);
		case PriorityCriteria.Epic:
			return -(((int)((HoverInfoUpgrade)a).Upgrade.Upgrade.Rarity == 2) ? 1 : 0).CompareTo(((int)((HoverInfoUpgrade)b).Upgrade.Upgrade.Rarity == 2) ? 1 : 0);
		case PriorityCriteria.Rare:
			return -(((int)((HoverInfoUpgrade)a).Upgrade.Upgrade.Rarity == 1) ? 1 : 0).CompareTo(((int)((HoverInfoUpgrade)b).Upgrade.Upgrade.Rarity == 1) ? 1 : 0);
		case PriorityCriteria.Standard:
			return -(((int)((HoverInfoUpgrade)a).Upgrade.Upgrade.Rarity == 0) ? 1 : 0).CompareTo(((int)((HoverInfoUpgrade)b).Upgrade.Upgrade.Rarity == 0) ? 1 : 0);
		default:
			return 0;
		}
	}

	public static List<PriorityCriteria> LoadPriorityOrder()
	{
		try
		{
			string json = default(string);
			if (PlayerOptions.TryGetConfig<string>("SortPriority.Order", ref json))
			{
				try
				{
					PriorityData priorityData = PriorityData.FromJson(json);
					List<PriorityCriteria> list = new List<PriorityCriteria>();
					if (priorityData?.order != null)
					{
						foreach (int item in priorityData.order)
						{
							if (Enum.IsDefined(typeof(PriorityCriteria), item))
							{
								list.Add((PriorityCriteria)item);
							}
						}
					}
					if (list.Count > 0)
					{
						return FilterOrderForAvailableMods(list);
					}
				}
				catch (Exception ex)
				{
					UpgradeFilteringPlugin.Logger.LogWarning((object)("Failed to parse priority order from config, using defaults: " + ex.Message));
				}
			}
			return FilterOrderForAvailableMods(new PriorityData().order.ConvertAll((int i) => (PriorityCriteria)i));
		}
		catch (Exception ex2)
		{
			UpgradeFilteringPlugin.Logger.LogError((object)("Critical error loading priority order: " + ex2.Message));
			return FilterOrderForAvailableMods(new PriorityData().order.ConvertAll((int i) => (PriorityCriteria)i));
		}
	}

	public static void SavePriorityOrder(List<PriorityCriteria> order)
	{
		try
		{
			if (order != null)
			{
				priorityOrder = new List<PriorityCriteria>(order);
				string text = new PriorityData
				{
					order = order.ConvertAll((PriorityCriteria c) => (int)c)
				}.ToJson();
				PlayerOptions.SetConfig<string>("SortPriority.Order", text);
				UpgradeFilteringPlugin.Logger.LogInfo((object)$"Saved priority order ({order.Count} criteria).");
			}
		}
		catch (Exception ex)
		{
			UpgradeFilteringPlugin.Logger.LogError((object)("Failed to save priority order: " + ex.Message));
		}
	}
}
public static class StatFormatHandling
{
	public static bool enableStatReformat = true;

	public static void Initialize()
	{
	}

	public static void ReformatStats(Upgrade __instance, ref string text)
	{
		if (!enableStatReformat || string.IsNullOrEmpty(text))
		{
			return;
		}
		try
		{
			string[] array = text.Split(new string[2] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);
			StringBuilder stringBuilder = new StringBuilder();
			string[] array2 = array;
			foreach (string text2 in array2)
			{
				string text3 = text2.Trim();
				if (string.IsNullOrWhiteSpace(text3))
				{
					stringBuilder.AppendLine();
					continue;
				}
				string input = Regex.Replace(text3, "<[^>]*>", "");
				if (Regex.IsMatch(input, "^[-+]?\\d"))
				{
					Match match = Regex.Match(input, "^([-+]?\\d+(?:\\.\\d+)?[%s]?)\\s*(.+)$");
					if (match.Success)
					{
						string value = match.Groups[1].Value;
						string text4 = match.Groups[2].Value.Trim();
						if (!string.IsNullOrEmpty(text4))
						{
							string value2 = text4 + ": <b>" + value + "</b>";
							stringBuilder.AppendLine(value2);
							continue;
						}
					}
				}
				stringBuilder.AppendLine(text2);
			}
			text = stringBuilder.ToString().TrimEnd();
		}
		catch (Exception)
		{
		}
	}

	public static void ReformatUIText(TextMeshProUGUI textComponent, string fieldName = "text")
	{
		if (!enableStatReformat || (Object)(object)textComponent == (Object)null)
		{
			return;
		}
		string text = ((TMP_Text)textComponent).text;
		if (string.IsNullOrEmpty(text))
		{
			return;
		}
		try
		{
			string[] array = text.Split(new string[2] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);
			StringBuilder stringBuilder = new StringBuilder();
			string[] array2 = array;
			foreach (string text2 in array2)
			{
				string text3 = text2.Trim();
				if (string.IsNullOrWhiteSpace(text3))
				{
					stringBuilder.AppendLine();
					continue;
				}
				string input = Regex.Replace(text3, "<[^>]*>", "");
				if (Regex.IsMatch(input, "^[-+]?\\d"))
				{
					Match match = Regex.Match(input, "^([-+]?\\d+(?:\\.\\d+)?[%s]?)\\s*(.+)$");
					if (match.Success)
					{
						string value = match.Groups[1].Value;
						string text4 = match.Groups[2].Value.Trim();
						if (!string.IsNullOrEmpty(text4))
						{
							string value2 = text4 + ": <b>" + value + "</b>";
							stringBuilder.AppendLine(value2);
							continue;
						}
					}
				}
				stringBuilder.AppendLine(text2);
			}
			string text5 = stringBuilder.ToString().TrimEnd();
			((TMP_Text)textComponent).text = text5;
			((TMP_Text)textComponent).ForceMeshUpdate(false, false);
		}
		catch (Exception)
		{
		}
	}
}
[HarmonyPatch(typeof(Upgrade), "GetStatList")]
public static class StatListReformatPatch
{
	private static void Postfix(Upgrade __instance, int seed, ref string __result)
	{
		StatFormatHandling.ReformatStats(__instance, ref __result);
	}
}
[HarmonyPatch(typeof(HoverInfoDisplay), "Activate")]
public static class HoverInfoDisplayReformatPatch
{
	private static void Postfix(HoverInfoDisplay __instance, HoverInfo info, bool resetPosition)
	{
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Expected O, but got Unknown
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Expected O, but got Unknown
		if (!StatFormatHandling.enableStatReformat || (Object)(object)info == (Object)null || ((object)info).GetType().Name == "DirectiveButton")
		{
			return;
		}
		try
		{
			FieldInfo fieldInfo = AccessTools.Field(typeof(HoverInfoDisplay), "text");
			if (fieldInfo != null)
			{
				StatFormatHandling.ReformatUIText((TextMeshProUGUI)fieldInfo.GetValue(__instance), "main text");
			}
			FieldInfo fieldInfo2 = AccessTools.Field(typeof(HoverInfoDisplay), "statsText");
			if (fieldInfo2 != null)
			{
				StatFormatHandling.ReformatUIText((TextMeshProUGUI)fieldInfo2.GetValue(__instance), "statsText");
			}
		}
		catch (Exception ex)
		{
			UpgradeFilteringPlugin.Logger.LogWarning((object)("HoverInfoDisplayReformatPatch: Failed: " + ex.Message));
		}
	}
}
[HarmonyPatch(typeof(HoverInfoDisplay), "Refresh")]
public static class HoverInfoDisplayRefreshReformatPatch
{
	private static void Postfix(HoverInfoDisplay __instance)
	{
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Expected O, but got Unknown
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Expected O, but got Unknown
		FieldInfo fieldInfo = AccessTools.Field(typeof(HoverInfoDisplay), "selectedInfo");
		if (fieldInfo == null)
		{
			return;
		}
		object? value = fieldInfo.GetValue(__instance);
		HoverInfo val = (HoverInfo)((value is HoverInfo) ? value : null);
		if (!StatFormatHandling.enableStatReformat || (Object)(object)val == (Object)null || ((object)val).GetType().Name == "DirectiveButton")
		{
			return;
		}
		try
		{
			FieldInfo fieldInfo2 = AccessTools.Field(typeof(HoverInfoDisplay), "text");
			if (fieldInfo2 != null)
			{
				StatFormatHandling.ReformatUIText((TextMeshProUGUI)fieldInfo2.GetValue(__instance), "main text (refresh)");
			}
			FieldInfo fieldInfo3 = AccessTools.Field(typeof(HoverInfoDisplay), "statsText");
			if (fieldInfo3 != null)
			{
				StatFormatHandling.ReformatUIText((TextMeshProUGUI)fieldInfo3.GetValue(__instance), "statsText (refresh)");
			}
		}
		catch (Exception ex)
		{
			UpgradeFilteringPlugin.Logger.LogWarning((object)("HoverInfoDisplayRefreshReformatPatch: Failed: " + ex.Message));
		}
	}
}
namespace UpgradeFiltering
{
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "UpgradeFiltering";

		public const string PLUGIN_NAME = "UpgradeFiltering";

		public const string PLUGIN_VERSION = "1.1.2";
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}