Decompiled source of Citizen Database Search v1.0.1

plugins/CitizenDatabaseSearch/SoDCitizenSearch.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
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("SoDCitizenSearch")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("SoDCitizenSearch")]
[assembly: AssemblyTitle("SoDCitizenSearch")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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;
		}
	}
}
namespace SoDCitizenSearch
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("sm3gm.sod.citizensearch", "Citizen Database Search", "0.5.5")]
	public sealed class Plugin : BasePlugin
	{
		public const string VER = "0.5.5";

		internal static ManualLogSource L;

		internal static ConfigEntry<SearchMode> Mode;

		public override void Load()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected O, but got Unknown
			L = ((BasePlugin)this).Log;
			Mode = ((BasePlugin)this).Config.Bind<SearchMode>("Search", "Mode", SearchMode.Open, "Detective: you can only pick traits you have evidence for in the open case (FROM CASE fills them in). Open: every trait can be picked freely.");
			Harmony val = new Harmony("sm3gm.sod.citizensearch");
			if (((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.ContainsKey("CalebScott.GovernmentDatabaseRework"))
			{
				L.LogInfo((object)"[SEARCH] Government Database Rework installed, filtering its list");
				((BasePlugin)this).AddComponent<Poller>();
			}
			else
			{
				val.PatchAll(typeof(SearchPatch));
				val.PatchAll(typeof(ClickPatch));
				val.PatchAll(typeof(AttachPatch));
			}
			ManualLogSource l = L;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(31, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Citizen Database Search ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("0.5.5");
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" loaded");
			}
			l.LogInfo(val2);
		}
	}
	public enum SearchMode
	{
		Detective,
		Open
	}
	internal static class CaseClues
	{
		internal static Dictionary<string, string> Known = new Dictionary<string, string>();

		internal static string Who = "";

		internal static void Read()
		{
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Expected O, but got Unknown
			Known = new Dictionary<string, string>();
			Who = "";
			CasePanelController instance = CasePanelController.Instance;
			Case val = ((instance != null) ? instance.activeCase : null);
			if (((val != null) ? val.caseElements : null) == null)
			{
				return;
			}
			int num = 0;
			Enumerator<CaseElement> enumerator = val.caseElements.GetEnumerator();
			Evidence val2 = default(Evidence);
			bool flag = default(bool);
			while (enumerator.MoveNext())
			{
				CaseElement current = enumerator.Current;
				if (((current != null) ? current.dk : null) == null || string.IsNullOrEmpty(current.id) || !Toolbox.Instance.TryGetEvidence(current.id, ref val2) || val2 == null)
				{
					continue;
				}
				Controller controller = val2.controller;
				Human val3 = ((controller != null) ? ((Il2CppObjectBase)controller).TryCast<Human>() : null);
				if ((Object)(object)val3 == (Object)null)
				{
					continue;
				}
				List<DataKey> list = new List<DataKey>();
				Enumerator<DataKey> enumerator2 = current.dk.GetEnumerator();
				while (enumerator2.MoveNext())
				{
					DataKey current2 = enumerator2.Current;
					list.Add(current2);
				}
				if (list.Contains((DataKey)0) || list.Contains((DataKey)1))
				{
					continue;
				}
				Dictionary<string, string> dictionary = FromKeys(val3, list);
				ManualLogSource l = Plugin.L;
				BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(27, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[SEARCH] case clue person: ");
					((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(string.Join(", ", dictionary.Select((KeyValuePair<string, string> x) => x.Key + "=" + x.Value)));
				}
				l.LogInfo(val4);
				if (dictionary.Count > num)
				{
					num = dictionary.Count;
					Known = dictionary;
					Who = current.n ?? "";
				}
			}
		}

		private static Dictionary<string, string> FromKeys(Human h, List<DataKey> keys)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected I4, but got Unknown
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: 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_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Invalid comparison between Unknown and I4
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Invalid comparison between Unknown and I4
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			Descriptors descriptors = h.descriptors;
			foreach (DataKey key in keys)
			{
				switch (key - 5)
				{
				default:
					if ((int)key != 24)
					{
						if ((int)key != 30)
						{
							break;
						}
						goto case 0;
					}
					goto case 2;
				case 3:
					dictionary["sex"] = ((object)h.gender/*cast due to .constrained prefix*/).ToString();
					break;
				case 0:
					if (descriptors != null)
					{
						dictionary["height"] = ((object)descriptors.height/*cast due to .constrained prefix*/).ToString();
					}
					break;
				case 1:
					if (descriptors != null)
					{
						dictionary["build"] = ((object)descriptors.build/*cast due to .constrained prefix*/).ToString();
					}
					break;
				case 5:
					if (descriptors != null)
					{
						dictionary["eyes"] = ((object)descriptors.eyeColour/*cast due to .constrained prefix*/).ToString();
					}
					break;
				case 4:
					if (descriptors != null)
					{
						dictionary["hair"] = ((object)descriptors.hairColourCategory/*cast due to .constrained prefix*/).ToString();
						dictionary["style"] = ((object)descriptors.hairType/*cast due to .constrained prefix*/).ToString();
					}
					break;
				case 6:
					dictionary["blood"] = ((object)h.bloodType/*cast due to .constrained prefix*/).ToString();
					break;
				case 7:
					if (descriptors != null)
					{
						dictionary["shoes"] = descriptors.shoeSize.ToString();
					}
					break;
				case 2:
					dictionary["age"] = ((object)h.GetAgeGroup()/*cast due to .constrained prefix*/).ToString();
					break;
				case 14:
					dictionary["face"] = "glasses";
					break;
				case 8:
				case 9:
				case 10:
				case 11:
				case 12:
				case 13:
					break;
				}
			}
			return dictionary;
		}
	}
	internal static class Traits
	{
		private static (string label, string key, string[] values)[]? all;

		private static readonly (string label, string key, string[] values)[] Base = new(string, string, string[])[9]
		{
			("SEX", "sex", new string[3] { "male", "female", "nonBinary" }),
			("HEIGHT", "height", new string[5] { "veryShort", "hShort", "hAverage", "tall", "veryTall" }),
			("BUILD", "build", new string[4] { "skinny", "average", "overweight", "muscular" }),
			("EYES", "eyes", new string[4] { "blueEyes", "brownEyes", "greenEyes", "greyEyes" }),
			("HAIR", "hair", new string[11]
			{
				"black", "brown", "blonde", "ginger", "red", "grey", "white", "blue", "green", "purple",
				"pink"
			}),
			("STYLE", "style", new string[3] { "bald", "shortHair", "longHair" }),
			("BLOOD", "blood", new string[8] { "Apos", "Aneg", "Bpos", "Bneg", "Opos", "Oneg", "ABpos", "ABneg" }),
			("AGE", "age", new string[3] { "youngAdult", "adult", "old" }),
			("FACE", "face", new string[7] { "glasses", "beard", "moustache", "tattoo", "piercing", "scaring", "mole" })
		};

		internal static readonly Dictionary<string, string> Chosen = new Dictionary<string, string>();

		internal static (string label, string key, string[] values)[] All => all ?? (all = Base.Append<(string, string, string[])>(("SHOES", "shoes", ShoeSizes())).ToArray());

		internal static bool Any => Chosen.Count > 0;

		private static string[] ShoeSizes()
		{
			SortedSet<int> sortedSet = new SortedSet<int>();
			try
			{
				Enumerator<Citizen> enumerator = CityData.Instance.citizenDirectory.GetEnumerator();
				while (enumerator.MoveNext())
				{
					Citizen current = enumerator.Current;
					if (((current != null) ? ((Human)current).descriptors : null) != null)
					{
						sortedSet.Add(((Human)current).descriptors.shoeSize);
					}
				}
			}
			catch
			{
			}
			return sortedSet.Select((int x) => x.ToString()).ToArray();
		}

		internal static string Describe()
		{
			if (!Any)
			{
				return "none";
			}
			return string.Join(", ", Chosen.Select((KeyValuePair<string, string> k) => k.Key + "=" + k.Value));
		}

		internal static string Pretty(string v)
		{
			switch (v)
			{
			case "veryShort":
				return "VERY SHORT";
			case "hShort":
				return "SHORT";
			case "hAverage":
				return "AVERAGE";
			case "veryTall":
				return "VERY TALL";
			case "nonBinary":
				return "NON-BINARY";
			case "shortHair":
				return "SHORT";
			case "longHair":
				return "LONG";
			case "youngAdult":
				return "YOUNG ADULT";
			case "scaring":
				return "SCARS";
			case "Apos":
				return "A+";
			case "Aneg":
				return "A-";
			case "Bpos":
				return "B+";
			case "Bneg":
				return "B-";
			case "Opos":
				return "O+";
			case "Oneg":
				return "O-";
			case "ABpos":
				return "AB+";
			case "ABneg":
				return "AB-";
			default:
			{
				string result;
				if (!v.EndsWith("Eyes"))
				{
					result = v.ToUpperInvariant();
				}
				else
				{
					result = v.Substring(0, v.Length - 4).ToUpperInvariant();
				}
				return result;
			}
			}
		}

		internal static void Cycle(string key, string[] values)
		{
			if (Plugin.Mode.Value == SearchMode.Detective)
			{
				CaseClues.Read();
				string value;
				if (Chosen.ContainsKey(key))
				{
					Chosen.Remove(key);
				}
				else if (CaseClues.Known.TryGetValue(key, out value))
				{
					Chosen[key] = value;
				}
			}
			else
			{
				string value2;
				int num = (Chosen.TryGetValue(key, out value2) ? (Array.IndexOf(values, value2) + 1) : 0);
				if (num >= values.Length)
				{
					Chosen.Remove(key);
				}
				else
				{
					Chosen[key] = values[num];
				}
			}
		}

		internal static string? Value(Human h, string key)
		{
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			Descriptors descriptors = h.descriptors;
			return key switch
			{
				"sex" => ((object)h.gender/*cast due to .constrained prefix*/).ToString(), 
				"height" => (descriptors != null) ? ((object)descriptors.height/*cast due to .constrained prefix*/).ToString() : null, 
				"build" => (descriptors != null) ? ((object)descriptors.build/*cast due to .constrained prefix*/).ToString() : null, 
				"eyes" => (descriptors != null) ? ((object)descriptors.eyeColour/*cast due to .constrained prefix*/).ToString() : null, 
				"hair" => (descriptors != null) ? ((object)descriptors.hairColourCategory/*cast due to .constrained prefix*/).ToString() : null, 
				"style" => (descriptors != null) ? ((object)descriptors.hairType/*cast due to .constrained prefix*/).ToString() : null, 
				"blood" => ((object)h.bloodType/*cast due to .constrained prefix*/).ToString(), 
				"age" => ((object)h.GetAgeGroup()/*cast due to .constrained prefix*/).ToString(), 
				"shoes" => (descriptors != null) ? descriptors.shoeSize.ToString() : null, 
				_ => null, 
			};
		}

		private unsafe static bool HasFeature(Human h, string feature)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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)
			Descriptors descriptors = h.descriptors;
			List<FacialFeaturesSetting> val = ((descriptors != null) ? descriptors.facialFeatures : null);
			if (val == null)
			{
				return false;
			}
			Enumerator<FacialFeaturesSetting> enumerator = val.GetEnumerator();
			while (enumerator.MoveNext())
			{
				FacialFeaturesSetting current = enumerator.Current;
				FacialFeature feature2 = current.feature;
				if (((object)(*(FacialFeature*)(&feature2))/*cast due to .constrained prefix*/).ToString() == feature)
				{
					return true;
				}
			}
			return false;
		}

		internal static bool Match(Human h)
		{
			foreach (KeyValuePair<string, string> item in Chosen)
			{
				if (item.Key == "face")
				{
					if (!HasFeature(h, item.Value))
					{
						return false;
					}
				}
				else if (Value(h, item.Key) != item.Value)
				{
					return false;
				}
			}
			return true;
		}
	}
	[HarmonyPatch]
	internal static class SearchPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(DatabaseApp), "UpdateSearch")]
		private static void AfterSearch(DatabaseApp __instance)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			bool flag = default(bool);
			try
			{
				Panel.Attach(__instance);
			}
			catch (Exception ex)
			{
				ManualLogSource l = Plugin.L;
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(23, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SEARCH] panel failed: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				l.LogWarning(val);
			}
			try
			{
				Vanilla(__instance);
			}
			catch (Exception ex2)
			{
				ManualLogSource l2 = Plugin.L;
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(24, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SEARCH] filter failed: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex2);
				}
				l2.LogWarning(val);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ComputerOSMultiSelect), "NextPage")]
		private static void AfterPage(ComputerOSMultiSelect __instance)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			if (!Traits.Any || Rework.Owns(__instance))
			{
				return;
			}
			try
			{
				if ((Object)(object)((Component)__instance).GetComponentInParent<DatabaseApp>() != (Object)null && Remove(__instance))
				{
					__instance.SpawnList();
				}
			}
			catch (Exception ex)
			{
				ManualLogSource l = Plugin.L;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(29, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SEARCH] page filter failed: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				l.LogWarning(val);
			}
		}

		internal static void Vanilla(DatabaseApp db)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Expected O, but got Unknown
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Expected O, but got Unknown
			ComputerOSMultiSelect list = db.list;
			if ((Object)(object)list == (Object)null || !Traits.Any)
			{
				return;
			}
			if ((db.searchString?.Length ?? 0) < 2 && (int)db.citizenPool == 0)
			{
				List<Citizen> list2 = new List<Citizen>();
				Enumerator<Citizen> enumerator = CityData.Instance.citizenDirectory.GetEnumerator();
				while (enumerator.MoveNext())
				{
					Citizen current = enumerator.Current;
					if ((Object)(object)current != (Object)null && Traits.Match((Human)(object)current))
					{
						list2.Add(current);
					}
				}
				List<OSMultiOption> val = new List<OSMultiOption>();
				foreach (Citizen item in from c in list2
					orderby ((Human)c).surName, ((Human)c).firstName
					select c)
				{
					val.Add(new OSMultiOption(((Human)item).surName + ", " + ((Human)item).firstName, (Human)(object)item));
				}
				list.allOptions = val;
				list.page = 0;
				list.SpawnList();
				ManualLogSource l = Plugin.L;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(27, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[SEARCH] traits ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(Traits.Describe());
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(val.Count);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" citizens");
				}
				l.LogInfo(val2);
			}
			else if (Remove(list))
			{
				list.page = 0;
				list.SpawnList();
			}
		}

		private static bool Remove(ComputerOSMultiSelect list)
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			List<OSMultiOption> allOptions = list.allOptions;
			if (allOptions == null)
			{
				return false;
			}
			int count = allOptions.Count;
			for (int num = allOptions.Count - 1; num >= 0; num--)
			{
				OSMultiOption obj = allOptions[num];
				if ((Object)(object)((obj != null) ? obj.human : null) == (Object)null || !Traits.Match(allOptions[num].human))
				{
					allOptions.RemoveAt(num);
				}
			}
			if (allOptions.Count != count)
			{
				ManualLogSource l = Plugin.L;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(22, 3, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SEARCH] traits ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Traits.Describe());
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(allOptions.Count);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" of ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(count);
				}
				l.LogInfo(val);
			}
			return allOptions.Count != count;
		}
	}
	[HarmonyPatch(typeof(ComputerOSUIComponent), "OnLeftClick")]
	internal static class ClickPatch
	{
		internal static readonly Dictionary<IntPtr, Action> Actions = new Dictionary<IntPtr, Action>();

		internal static void FromRework(ComputerOSUIComponent __0)
		{
			Postfix(__0);
		}

		private static void Postfix(ComputerOSUIComponent __instance)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			try
			{
				if (Actions.TryGetValue(((Il2CppObjectBase)__instance).Pointer, out var value))
				{
					value();
				}
			}
			catch (Exception ex)
			{
				ManualLogSource l = Plugin.L;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(24, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SEARCH] button failed: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				l.LogWarning(val);
			}
		}
	}
	[HarmonyPatch(typeof(DatabaseApp), "Update")]
	internal static class AttachPatch
	{
		private static float next;

		internal static void FromRework(DatabaseApp __0)
		{
			Postfix(__0);
		}

		private static void Postfix(DatabaseApp __instance)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			if (Time.unscaledTime < next)
			{
				return;
			}
			next = Time.unscaledTime + 0.25f;
			try
			{
				Panel.Attach(__instance);
			}
			catch (Exception ex)
			{
				ManualLogSource l = Plugin.L;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(23, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SEARCH] panel failed: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				l.LogWarning(val);
				next = Time.unscaledTime + 10f;
			}
		}
	}
	public class Poller : MonoBehaviour
	{
		private float next;

		public Poller(IntPtr ptr)
			: base(ptr)
		{
		}

		private void Update()
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			if (Time.unscaledTime < next)
			{
				return;
			}
			next = Time.unscaledTime + 0.5f;
			try
			{
				SessionData instance = SessionData.Instance;
				if ((Object)(object)instance == (Object)null || !instance.startedGame)
				{
					return;
				}
				if (!Rework.Find())
				{
					((Behaviour)this).enabled = false;
					return;
				}
				foreach (DatabaseApp item in Object.FindObjectsOfType<DatabaseApp>())
				{
					Panel.Attach(item);
					Rework.Filter(item);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource l = Plugin.L;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(22, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SEARCH] poll failed: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
				}
				l.LogWarning(val);
				next = Time.unscaledTime + 10f;
			}
		}
	}
	internal static class Panel
	{
		private sealed class State
		{
			public DatabaseApp App;

			public readonly List<GameObject> Keys = new List<GameObject>();

			public readonly List<GameObject> Hide = new List<GameObject>();

			public bool TwoLines;

			public GameObject Grid;

			public TextMeshProUGUI? ToggleText;

			public readonly List<(TextMeshProUGUI? text, string label, string key)> Cells = new List<(TextMeshProUGUI, string, string)>();

			public bool Open;
		}

		private static readonly HashSet<IntPtr> Done = new HashSet<IntPtr>();

		private static readonly Dictionary<IntPtr, State> Built = new Dictionary<IntPtr, State>();

		private static float KeyFont;

		private static string ToggleLabel(State st)
		{
			if (!st.Open)
			{
				if (!Traits.Any)
				{
					return "Traits";
				}
				return "Traits*";
			}
			return "Done";
		}

		private static void KeepLabel(DatabaseApp app)
		{
			if (Built.TryGetValue(((Il2CppObjectBase)app).Pointer, out var value) && !((Object)(object)value.ToggleText == (Object)null))
			{
				string text = ToggleLabel(value);
				if (((TMP_Text)value.ToggleText).text != text)
				{
					((TMP_Text)value.ToggleText).text = text;
				}
			}
		}

		internal static void Attach(DatabaseApp app)
		{
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Expected O, but got Unknown
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Expected O, but got Unknown
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Expected O, but got Unknown
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0402: Unknown result type (might be due to invalid IL or missing references)
			//IL_0407: Unknown result type (might be due to invalid IL or missing references)
			//IL_0456: Unknown result type (might be due to invalid IL or missing references)
			//IL_045d: Expected O, but got Unknown
			//IL_0535: Unknown result type (might be due to invalid IL or missing references)
			//IL_0558: Unknown result type (might be due to invalid IL or missing references)
			//IL_056d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0572: Unknown result type (might be due to invalid IL or missing references)
			//IL_0654: Unknown result type (might be due to invalid IL or missing references)
			//IL_065b: Expected O, but got Unknown
			//IL_06ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b3: Expected O, but got Unknown
			//IL_06dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0703: Unknown result type (might be due to invalid IL or missing references)
			//IL_0699: Unknown result type (might be due to invalid IL or missing references)
			//IL_08bc: Unknown result type (might be due to invalid IL or missing references)
			if (Done.Contains(((Il2CppObjectBase)app).Pointer))
			{
				KeepLabel(app);
				return;
			}
			Transform? obj = Find(((Component)app).transform, "OnscreenKeyboard");
			RectTransform val = ((obj != null) ? ((Il2CppObjectBase)obj).TryCast<RectTransform>() : null);
			if ((Object)(object)val == (Object)null)
			{
				Done.Add(((Il2CppObjectBase)app).Pointer);
				Plugin.L.LogWarning((object)"[SEARCH] no on-screen keyboard found, no trait buttons");
				return;
			}
			State st = new State
			{
				App = app
			};
			RectTransform val2 = null;
			List<Rect> list = new List<Rect>();
			foreach (ComputerOSUIComponent componentsInChild in ((Component)val).GetComponentsInChildren<ComputerOSUIComponent>(true))
			{
				RectTransform val3 = ((Il2CppObjectBase)((Component)componentsInChild).transform).TryCast<RectTransform>();
				if (!((Object)(object)val3 == (Object)null))
				{
					st.Keys.Add(((Component)componentsInChild).gameObject);
					list.Add(LocalRect(val, val3));
					TextMeshProUGUI componentInChildren = ((Component)componentsInChild).GetComponentInChildren<TextMeshProUGUI>(true);
					string text = ((componentInChildren == null) ? null : ((TMP_Text)componentInChildren).text?.Trim());
					if ((Object)(object)val2 == (Object)null && text != null && text.Length == 1 && char.IsLetter(text[0]))
					{
						val2 = val3;
					}
				}
			}
			bool flag = default(bool);
			if ((Object)(object)val2 == (Object)null || list.Count == 0)
			{
				Done.Add(((Il2CppObjectBase)app).Pointer);
				ManualLogSource l = Plugin.L;
				BepInExWarningLogInterpolatedStringHandler val4 = new BepInExWarningLogInterpolatedStringHandler(31, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[SEARCH] no key to copy (");
					((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<int>(list.Count);
					((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" keys)");
				}
				l.LogWarning(val4);
				return;
			}
			Rect keyR = LocalRect(val, val2);
			if (((Rect)(ref keyR)).width < 0.001f || ((Rect)(ref keyR)).height < 0.001f)
			{
				return;
			}
			Done.Add(((Il2CppObjectBase)app).Pointer);
			float minY = list.Min((Rect r) => ((Rect)(ref r)).center.y);
			Rect val5 = (from r in list
				where Mathf.Abs(((Rect)(ref r)).center.y - minY) < ((Rect)(ref keyR)).height * 0.5f
				orderby ((Rect)(ref r)).xMax
				select r).Last();
			TextMeshProUGUI componentInChildren2 = ((Component)val2).GetComponentInChildren<TextMeshProUGUI>(true);
			KeyFont = ((componentInChildren2 != null) ? ((TMP_Text)componentInChildren2).fontSize : 0f);
			ManualLogSource l2 = Plugin.L;
			BepInExInfoLogInterpolatedStringHandler val6 = new BepInExInfoLogInterpolatedStringHandler(18, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("[SEARCH] key font ");
				((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<float>(KeyFont);
			}
			l2.LogInfo(val6);
			ManualLogSource l3 = Plugin.L;
			val6 = new BepInExInfoLogInterpolatedStringHandler(52, 4, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("[SEARCH] keyboard ");
				((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<Rect>(val.rect);
				((BepInExLogInterpolatedStringHandler)val6).AppendLiteral(", ");
				((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<int>(list.Count);
				((BepInExLogInterpolatedStringHandler)val6).AppendLiteral(" keys, key ");
				((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<Vector2>(((Rect)(ref keyR)).size);
				((BepInExLogInterpolatedStringHandler)val6).AppendLiteral(", bottom row ends at ");
				((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<float>(((Rect)(ref val5)).xMax, "0.#");
			}
			l3.LogInfo(val6);
			RectTransform val7 = FindButton(((Component)app).transform, "exit") ?? (((Object)(object)((Component)app).transform.parent != (Object)null) ? FindButton(((Component)app).transform.parent, "exit") : null);
			if ((Object)(object)val7 == (Object)null)
			{
				Plugin.L.LogWarning((object)"[SEARCH] no Exit button found, no Traits button");
				return;
			}
			RectTransform val8 = Clone(val7, ((Transform)val7).parent, "CitizenSearchToggle");
			val8.anchorMin = val7.anchorMin;
			val8.anchorMax = val7.anchorMax;
			val8.pivot = val7.pivot;
			val8.sizeDelta = val7.sizeDelta;
			((Transform)val8).localScale = ((Transform)val7).localScale;
			Vector2 anchoredPosition = val7.anchoredPosition;
			Rect rect = val7.rect;
			val8.anchoredPosition = anchoredPosition - new Vector2(((Rect)(ref rect)).width * 1.08f, 0f);
			st.ToggleText = ((Component)val8).GetComponentInChildren<TextMeshProUGUI>(true);
			if ((Object)(object)st.ToggleText != (Object)null)
			{
				((TMP_Text)st.ToggleText).text = "Traits";
			}
			ManualLogSource l4 = Plugin.L;
			val6 = new BepInExInfoLogInterpolatedStringHandler(37, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("[SEARCH] Traits button beside Exit (");
				((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<string>(((Object)val7).name);
				((BepInExLogInterpolatedStringHandler)val6).AppendLiteral(")");
			}
			l4.LogInfo(val6);
			Bind(val8, delegate
			{
				Toggle(st);
			});
			Rect val9 = Rect.MinMaxRect(list.Min((Rect r) => ((Rect)(ref r)).xMin), list.Min((Rect r) => ((Rect)(ref r)).yMin), list.Max((Rect r) => ((Rect)(ref r)).xMax), list.Max((Rect r) => ((Rect)(ref r)).yMax));
			Transform? obj2 = Find(((Component)app).transform, "DataDisplay");
			RectTransform val10 = ((obj2 != null) ? ((Il2CppObjectBase)obj2).TryCast<RectTransform>() : null);
			Rect val11 = val9;
			Transform val12 = (Transform)(object)val;
			if ((Object)(object)val10 != (Object)null)
			{
				Rect val13 = LocalRect(val, val10);
				if (((Rect)(ref val13)).width > ((Rect)(ref keyR)).width * 3f && ((Rect)(ref val13)).height > ((Rect)(ref keyR)).height * 3f)
				{
					((Rect)(ref val11))..ctor(((Rect)(ref val13)).x + ((Rect)(ref val13)).width * 0.04f, ((Rect)(ref val13)).y + ((Rect)(ref val13)).height * 0.04f, ((Rect)(ref val13)).width * 0.92f, ((Rect)(ref val13)).height * 0.92f);
					val12 = ((Transform)val10).parent;
					st.Hide.Add(((Component)val10).gameObject);
					st.TwoLines = true;
				}
			}
			if (!st.TwoLines)
			{
				st.Hide.AddRange(st.Keys);
			}
			ManualLogSource l5 = Plugin.L;
			val6 = new BepInExInfoLogInterpolatedStringHandler(37, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("[SEARCH] trait panel over the ");
				((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<string>(st.TwoLines ? "preview" : "keyboard");
				((BepInExLogInterpolatedStringHandler)val6).AppendLiteral(", area ");
				((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<Rect>(val11);
			}
			l5.LogInfo(val6);
			GameObject val14 = new GameObject("CitizenSearchTraits");
			RectTransform val15 = val14.AddComponent<RectTransform>();
			((Transform)val15).SetParent(val12, false);
			Vector2 val16 = default(Vector2);
			((Vector2)(ref val16))..ctor(0.5f, 0.5f);
			val15.pivot = val16;
			Vector2 anchorMin = (val15.anchorMax = val16);
			val15.anchorMin = anchorMin;
			val15.sizeDelta = Vector2.zero;
			val15.anchoredPosition = Vector2.zero;
			st.Grid = val14;
			List<(string, string, Action)> list2 = new List<(string, string, Action)>();
			(string, string, string[])[] all = Traits.All;
			for (int num = 0; num < all.Length; num++)
			{
				(string, string, string[]) tuple = all[num];
				string item = tuple.Item2;
				string[] item2 = tuple.Item3;
				string[] values = item2;
				string key = item;
				list2.Add((tuple.Item1, key, delegate
				{
					Traits.Cycle(key, values);
					Changed(st);
				}));
			}
			list2.Add(("FROM CASE", "", delegate
			{
				CaseClues.Read();
				Traits.Chosen.Clear();
				foreach (KeyValuePair<string, string> item3 in CaseClues.Known)
				{
					Traits.Chosen[item3.Key] = item3.Value;
				}
				Changed(st);
			}));
			list2.Add(("CLEAR", "", delegate
			{
				Traits.Chosen.Clear();
				Changed(st);
			}));
			list2.Add((st.TwoLines ? "DONE" : "KEYS", "", delegate
			{
				Toggle(st);
			}));
			int num2 = (list2.Count + 2) / 3;
			float num3 = ((Rect)(ref val11)).width / 3f;
			float num4 = ((Rect)(ref val11)).height / (float)num2;
			for (int num5 = 0; num5 < list2.Count; num5++)
			{
				int num6 = num5 % 3;
				int num7 = num5 / 3;
				RectTransform val18 = Clone(val2, (Transform)(object)val15, "CitizenSearch" + list2[num5].Item1);
				Place(val18, val, new Rect(((Rect)(ref val11)).xMin + (float)num6 * num3 + num3 * 0.04f, ((Rect)(ref val11)).yMax - (float)(num7 + 1) * num4 + num4 * 0.08f, num3 * 0.92f, num4 * 0.84f));
				st.Cells.Add((((Component)val18).GetComponentInChildren<TextMeshProUGUI>(true), list2[num5].Item1, list2[num5].Item2));
				Bind(val18, list2[num5].Item3);
			}
			val14.SetActive(false);
			Refresh(st);
			Built[((Il2CppObjectBase)app).Pointer] = st;
			Plugin.L.LogInfo((object)"[SEARCH] trait buttons added");
		}

		private static void Toggle(State st)
		{
			st.Open = !st.Open;
			foreach (GameObject item in st.Hide)
			{
				if ((Object)(object)item != (Object)null)
				{
					item.SetActive(!st.Open);
				}
			}
			st.Grid.SetActive(st.Open);
			if ((Object)(object)st.ToggleText != (Object)null)
			{
				((TMP_Text)st.ToggleText).text = ToggleLabel(st);
			}
			if (st.Open)
			{
				Diag(st);
			}
		}

		private static void Diag(State st)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_0079: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0344: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Expected O, but got Unknown
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Expected O, but got Unknown
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				bool flag = default(bool);
				Rect rect;
				BepInExInfoLogInterpolatedStringHandler val2;
				for (int i = 0; i < Math.Min(2, st.Cells.Count); i++)
				{
					TextMeshProUGUI item = st.Cells[i].text;
					if ((Object)(object)item == (Object)null)
					{
						continue;
					}
					Transform parent = ((TMP_Text)item).transform.parent;
					RectTransform val = ((parent != null) ? ((Il2CppObjectBase)parent).TryCast<RectTransform>() : null);
					ManualLogSource l = Plugin.L;
					val2 = new BepInExInfoLogInterpolatedStringHandler(119, 12, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[SEARCH] diag cell ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(i);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": text rect ");
						BepInExInfoLogInterpolatedStringHandler obj = val2;
						rect = ((TMP_Text)item).rectTransform.rect;
						((BepInExLogInterpolatedStringHandler)obj).AppendFormatted<Vector2>(((Rect)(ref rect)).size);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", cell rect ");
						BepInExInfoLogInterpolatedStringHandler obj2 = val2;
						object obj3;
						if (!((Object)(object)val != (Object)null))
						{
							obj3 = "?";
						}
						else
						{
							rect = val.rect;
							obj3 = ((object)((Rect)(ref rect)).size/*cast due to .constrained prefix*/).ToString();
						}
						((BepInExLogInterpolatedStringHandler)obj2).AppendFormatted<string>((string)obj3);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", ");
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("font ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(((TMP_Text)item).fontSize);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" (auto ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(((TMP_Text)item).enableAutoSizing);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", max ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(((TMP_Text)item).fontSizeMax);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", min ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(((TMP_Text)item).fontSizeMin);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("), scale ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Vector3>(((TMP_Text)item).transform.lossyScale);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", ");
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("local ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Vector3>(((TMP_Text)item).transform.localScale);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", parent local ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)(object)val != (Object)null) ? ((object)((Transform)val).localScale/*cast due to .constrained prefix*/).ToString() : "?");
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", wrap ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(((TMP_Text)item).enableWordWrapping);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", overflow ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<TextOverflowModes>(((TMP_Text)item).overflowMode);
					}
					l.LogInfo(val2);
				}
				foreach (GameObject key in st.Keys)
				{
					TextMeshProUGUI val3 = (((Object)(object)key != (Object)null) ? key.GetComponentInChildren<TextMeshProUGUI>(true) : null);
					if (!((Object)(object)val3 == (Object)null) && ((TMP_Text)val3).text != null && ((TMP_Text)val3).text.Trim().Length == 1)
					{
						ManualLogSource l2 = Plugin.L;
						val2 = new BepInExInfoLogInterpolatedStringHandler(61, 6, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[SEARCH] diag key '");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((TMP_Text)val3).text);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("': text rect ");
							BepInExInfoLogInterpolatedStringHandler obj4 = val2;
							rect = ((TMP_Text)val3).rectTransform.rect;
							((BepInExLogInterpolatedStringHandler)obj4).AppendFormatted<Vector2>(((Rect)(ref rect)).size);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", font ");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(((TMP_Text)val3).fontSize);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" (auto ");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(((TMP_Text)val3).enableAutoSizing);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", max ");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(((TMP_Text)val3).fontSizeMax);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("), scale ");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Vector3>(((TMP_Text)val3).transform.lossyScale);
						}
						l2.LogInfo(val2);
						break;
					}
				}
				ManualLogSource l3 = Plugin.L;
				val2 = new BepInExInfoLogInterpolatedStringHandler(22, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[SEARCH] diag KeyFont ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(KeyFont);
				}
				l3.LogInfo(val2);
			}
			catch (Exception ex)
			{
				Plugin.L.LogWarning((object)("[SEARCH] diag " + ex.Message));
			}
		}

		private static void Changed(State st)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			Refresh(st);
			ManualLogSource l = Plugin.L;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(20, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SEARCH] traits now ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Traits.Describe());
			}
			l.LogInfo(val);
			if (!Rework.Refresh(st.App))
			{
				st.App.UpdateSearch();
			}
		}

		private static void Refresh(State st)
		{
			bool flag = Plugin.Mode.Value == SearchMode.Detective;
			if (flag)
			{
				CaseClues.Read();
			}
			foreach (var cell in st.Cells)
			{
				TextMeshProUGUI item = cell.text;
				string item2 = cell.label;
				string item3 = cell.key;
				string value;
				string text = (Traits.Chosen.TryGetValue(item3, out value) ? Traits.Pretty(value) : ((flag && item3.Length > 0 && !CaseClues.Known.ContainsKey(item3)) ? "NO CLUE" : "ANY"));
				SetText(item, (item3.Length == 0) ? item2 : (st.TwoLines ? (item2 + "\n" + text) : (item2 + ": " + text)));
			}
		}

		private static void SetText(TextMeshProUGUI? t, string s)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)t == (Object)null))
			{
				((TMP_Text)t).text = s;
				((TMP_Text)t).enableWordWrapping = false;
				if (KeyFont <= 0f)
				{
					KeyFont = ((TMP_Text)t).fontSize;
				}
				RectTransform rectTransform = ((TMP_Text)t).rectTransform;
				rectTransform.anchorMin = Vector2.zero;
				rectTransform.anchorMax = Vector2.one;
				rectTransform.offsetMin = Vector2.zero;
				rectTransform.offsetMax = Vector2.zero;
				((TMP_Text)t).margin = Vector4.zero;
				((TMP_Text)t).enableAutoSizing = false;
				int num = 0;
				string[] array = s.Split('\n');
				foreach (string text in array)
				{
					num = Math.Max(num, text.Length);
				}
				bool flag = s.Contains('\n');
				float num2 = KeyFont * (flag ? 0.72f : 1f);
				int num3 = (flag ? 8 : 6);
				if (num > num3)
				{
					num2 *= (float)num3 / (float)num;
				}
				((TMP_Text)t).fontSize = num2;
				((TMP_Text)t).lineSpacing = (flag ? (-25f) : 0f);
			}
		}

		private static void Bind(RectTransform b, Action a)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			ComputerOSUIComponent component = ((Component)b).GetComponent<ComputerOSUIComponent>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			if ((Object)(object)component.button != (Object)null)
			{
				component.button.onClick = new ButtonClickedEvent();
				if (Rework.Present)
				{
					((UnityEvent)component.button.onClick).AddListener(UnityAction.op_Implicit((Action)delegate
					{
						//IL_0018: Unknown result type (might be due to invalid IL or missing references)
						//IL_001e: Expected O, but got Unknown
						try
						{
							a();
						}
						catch (Exception ex)
						{
							ManualLogSource l = Plugin.L;
							bool flag = default(bool);
							BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(24, 1, ref flag);
							if (flag)
							{
								((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SEARCH] button failed: ");
								((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
							}
							l.LogWarning(val);
						}
					}));
				}
			}
			ClickPatch.Actions[((Il2CppObjectBase)component).Pointer] = a;
		}

		private static RectTransform Clone(RectTransform src, Transform parent, string name)
		{
			GameObject obj = Object.Instantiate<GameObject>(((Component)src).gameObject);
			((Object)obj).name = name;
			obj.transform.SetParent(parent, false);
			obj.SetActive(true);
			return ((Il2CppObjectBase)obj.transform).Cast<RectTransform>();
		}

		private static void Place(RectTransform b, RectTransform kb, Rect r)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0.5f, 0.5f);
			b.pivot = val;
			Vector2 anchorMin = (b.anchorMax = val);
			b.anchorMin = anchorMin;
			((Transform)b).localScale = Vector3.one;
			b.sizeDelta = ((Rect)(ref r)).size;
			((Transform)b).position = ((Transform)kb).TransformPoint(new Vector3(((Rect)(ref r)).center.x, ((Rect)(ref r)).center.y, 0f));
		}

		private static Rect LocalRect(RectTransform space, RectTransform rt)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			Il2CppStructArray<Vector3> val = new Il2CppStructArray<Vector3>(4L);
			rt.GetWorldCorners(val);
			Vector3 val2 = ((Transform)space).InverseTransformPoint(((Il2CppArrayBase<Vector3>)(object)val)[0]);
			Vector3 val3 = ((Transform)space).InverseTransformPoint(((Il2CppArrayBase<Vector3>)(object)val)[2]);
			return Rect.MinMaxRect(Mathf.Min(val2.x, val3.x), Mathf.Min(val2.y, val3.y), Mathf.Max(val2.x, val3.x), Mathf.Max(val2.y, val3.y));
		}

		private static RectTransform? FindButton(Transform root, string word)
		{
			foreach (ComputerOSUIComponent componentsInChild in ((Component)root).GetComponentsInChildren<ComputerOSUIComponent>(true))
			{
				TextMeshProUGUI componentInChildren = ((Component)componentsInChild).GetComponentInChildren<TextMeshProUGUI>(true);
				if (componentInChildren != null && ((TMP_Text)componentInChildren).text != null && ((TMP_Text)componentInChildren).text.Trim().Equals(word, StringComparison.OrdinalIgnoreCase))
				{
					return ((Il2CppObjectBase)((Component)componentsInChild).transform).TryCast<RectTransform>();
				}
			}
			return null;
		}

		private static Transform? Find(Transform t, string name)
		{
			if (((Object)t).name == name)
			{
				return t;
			}
			for (int i = 0; i < t.childCount; i++)
			{
				Transform val = Find(t.GetChild(i), name);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}
	}
	internal static class Rework
	{
		private static Type? listing;

		private static Type? registry;

		private static FieldInfo? matches;

		private static FieldInfo? citizen;

		private static FieldInfo? lastSearch;

		private static FieldInfo? pageIndex;

		private static FieldInfo? resultCount;

		private static bool looked;

		internal static bool Present => listing != null;

		internal static bool Find()
		{
			if (looked)
			{
				return Present;
			}
			looked = true;
			Assembly? assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "GovernmentDatabaseRework");
			listing = assembly?.GetType("GovernmentDatabaseRework.DatabaseListing");
			registry = assembly?.GetType("GovernmentDatabaseRework.AppRegistry");
			Type type = assembly?.GetType("GovernmentDatabaseRework.AppState");
			Type type2 = assembly?.GetType("GovernmentDatabaseRework.DirectoryEntry");
			if (listing == null || registry == null || type == null || type2 == null)
			{
				listing = (registry = null);
				Plugin.L.LogWarning((object)"[SEARCH] Government Database Rework types not found, no filtering");
				return false;
			}
			matches = AccessTools.Field(type, "Matches");
			lastSearch = AccessTools.Field(type, "LastSearch");
			pageIndex = AccessTools.Field(type, "PageIndex");
			resultCount = AccessTools.Field(type, "LastResultCount");
			citizen = AccessTools.Field(type2, "Citizen");
			Plugin.L.LogInfo((object)"[SEARCH] Government Database Rework types found");
			return true;
		}

		internal static bool Owns(ComputerOSMultiSelect list)
		{
			if (registry != null)
			{
				return AccessTools.Method(registry, "ForList", (Type[])null, (Type[])null)?.Invoke(null, new object[1] { list }) != null;
			}
			return false;
		}

		private static object? StateOf(DatabaseApp app)
		{
			if (!(registry == null) && !((Object)(object)app.list == (Object)null))
			{
				return AccessTools.Method(registry, "ForList", (Type[])null, (Type[])null)?.Invoke(null, new object[1] { app.list });
			}
			return null;
		}

		internal static bool Refresh(DatabaseApp app)
		{
			object obj = StateOf(app);
			if (obj == null || matches.GetValue(obj) == null)
			{
				return false;
			}
			lastSearch.SetValue(obj, null);
			app.UpdateSearch();
			Filter(app);
			return true;
		}

		internal static void Filter(DatabaseApp app)
		{
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Expected O, but got Unknown
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Expected O, but got Unknown
			if (!Present || !Traits.Any)
			{
				return;
			}
			bool flag = default(bool);
			try
			{
				object obj = StateOf(app);
				if (obj == null || !(matches.GetValue(obj) is IList { Count: var count } list))
				{
					return;
				}
				for (int num = list.Count - 1; num >= 0; num--)
				{
					object? value = citizen.GetValue(list[num]);
					Human val = (Human)((value is Human) ? value : null);
					if (val == null || !Traits.Match(val))
					{
						list.RemoveAt(num);
					}
				}
				if (list.Count != count)
				{
					resultCount.SetValue(obj, list.Count);
					pageIndex.SetValue(obj, 0);
					AccessTools.Method(listing, "ShowPage", (Type[])null, (Type[])null).Invoke(null, new object[1] { obj });
					AccessTools.Method(listing, "UpdateSearchLine", (Type[])null, (Type[])null).Invoke(null, new object[3]
					{
						app,
						(lastSearch.GetValue(obj) as string) ?? "",
						list.Count
					});
					ManualLogSource l = Plugin.L;
					BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(27, 4, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[SEARCH] rework \"");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<object>(lastSearch.GetValue(obj));
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("\" + ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(Traits.Describe());
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(list.Count);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" of ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(count);
					}
					l.LogInfo(val2);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource l2 = Plugin.L;
				BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(31, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[SEARCH] rework filter failed: ");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<Exception>(ex);
				}
				l2.LogWarning(val3);
			}
		}
	}
}