Decompiled source of OrderTabletAssistant v1.0.0

OrderTabletAssistant.dll

Decompiled 8 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
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("OrderTabletAssistant")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("OrderTabletAssistant")]
[assembly: AssemblyTitle("OrderTabletAssistant")]
[assembly: AssemblyVersion("1.0.0.0")]
[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;
		}
	}
}
namespace OrderTabletAssistant
{
	[BepInPlugin("acesgaminguk.supermarkettogether.ordertabletassistant", "OrderTabletAssistant", "1.0.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		internal static Plugin Instance;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<PopulateMode> Mode;

		internal static ConfigEntry<KeyCode> PopulateHotkey;

		internal static ConfigEntry<string> WhereToCheck;

		internal static ConfigEntry<bool> ShowManualPanel;

		internal static ConfigEntry<float> PanelScale;

		internal static ConfigEntry<string> PromptColourChoice;

		internal static ConfigEntry<Color> CustomPromptColour;

		internal static ConfigEntry<float> PanelX;

		internal static ConfigEntry<float> PanelY;

		private Harmony _harmony;

		private OrderingDevice _activeDevice;

		private float _lastPopulateTime;

		private bool _scanInProgress;

		private GameObject _nativePanel;

		private RectTransform _nativePanelRect;

		private TextMeshProUGUI _nativePanelText;

		private Image _nativePanelImage;

		private Color _nativePanelOriginalColour;

		private bool _draggingPanel;

		private Vector3 _lastMousePosition;

		private static readonly MethodInfo AddProductBaseMethod = AccessTools.Method(typeof(OrderingDevice), "AddProductbase", (Type[])null, (Type[])null);

		private static readonly MethodInfo RetrievePricePerBoxMethod = AccessTools.Method(typeof(OrderingDevice), "RetrievePricePerBox", (Type[])null, (Type[])null);

		private static readonly MethodInfo DestroyUiObjectsMethod = AccessTools.Method(typeof(OrderingDevice), "DestroyUIObjects", (Type[])null, (Type[])null);

		private static readonly MethodInfo CalculateShoppingListTotalMethod = AccessTools.Method(typeof(OrderingDevice), "CalculateShoppingListTotal", (Type[])null, (Type[])null);

		private void Awake()
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Expected O, but got Unknown
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Expected O, but got Unknown
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cb: Expected O, but got Unknown
			Instance = this;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("# General #", "Enable Mod", true, "Turns Order Tablet Assistant on or off.");
			Mode = ((BaseUnityPlugin)this).Config.Bind<PopulateMode>("# Order Tablet #", "How to Fill the Order", PopulateMode.Manual, "Manual = press the chosen key. Automatic = fill the order when the tablet opens.");
			WhereToCheck = ((BaseUnityPlugin)this).Config.Bind<string>("# Order Tablet #", "Where to Check", "Shop Shelves Only", new ConfigDescription("Choose which shelves should be used when creating the order.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[3] { "Shop Shelves Only", "Shop and Storage Shelves", "Storage Shelves Only" }), Array.Empty<object>()));
			PopulateHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("# Controls #", "Manual Fill Key", (KeyCode)114, "The key used to create the order in Manual mode.");
			ShowManualPanel = ((BaseUnityPlugin)this).Config.Bind<bool>("# Display #", "Show Prompt", true, "Shows the Auto Fill prompt while using the tablet in Manual mode.");
			PanelScale = ((BaseUnityPlugin)this).Config.Bind<float>("# Display #", "Prompt Size", 1f, new ConfigDescription("Changes the size of the prompt.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>()));
			PromptColourChoice = ((BaseUnityPlugin)this).Config.Bind<string>("# Display #", "Prompt Colour", "Game Default", new ConfigDescription("Changes the prompt background colour. Game Default keeps the original in-game colour.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[8] { "Game Default", "Purple", "Blue", "Orange", "Green", "Red", "Demo Red", "Custom" }), Array.Empty<object>()));
			CustomPromptColour = ((BaseUnityPlugin)this).Config.Bind<Color>("# Display #", "Custom Prompt Colour", new Color(0.36f, 0.16f, 0.46f, 1f), "Used only when Prompt Colour is set to Custom.");
			PanelX = ((BaseUnityPlugin)this).Config.Bind<float>("# Display #", "Prompt Position X", 28f, "Saved horizontal position of the prompt.");
			PanelY = ((BaseUnityPlugin)this).Config.Bind<float>("# Display #", "Prompt Position Y", 270f, "Saved vertical position of the prompt.");
			((BaseUnityPlugin)this).Logger.LogWarning((object)"=============================================");
			((BaseUnityPlugin)this).Logger.LogMessage((object)string.Format("{0} v{1} Initializing...", "Order Tablet Assistant", ((BaseUnityPlugin)this).Info.Metadata.Version));
			((BaseUnityPlugin)this).Logger.LogWarning((object)"=============================================");
			((BaseUnityPlugin)this).Logger.LogMessage((object)"Author: AcesGamingUK");
			((BaseUnityPlugin)this).Logger.LogMessage((object)"GitHub: https://github.com/AcesGamingUK/Order-Tablet-Assistant");
			((BaseUnityPlugin)this).Logger.LogMessage((object)("Fill mode: " + Mode.Value));
			((BaseUnityPlugin)this).Logger.LogMessage((object)("Manual fill key: " + ((object)PopulateHotkey.Value/*cast due to .constrained prefix*/).ToString()));
			((BaseUnityPlugin)this).Logger.LogMessage((object)("Where to check: " + WhereToCheck.Value));
			((BaseUnityPlugin)this).Logger.LogWarning((object)"=============================================");
			((BaseUnityPlugin)this).Logger.LogMessage((object)"Order Tablet Assistant Initialized successfully!");
			((BaseUnityPlugin)this).Logger.LogWarning((object)"=============================================");
			PanelScale.SettingChanged += delegate
			{
				ApplyPanelScale();
			};
			PromptColourChoice.SettingChanged += delegate
			{
				ApplyPanelColour();
			};
			CustomPromptColour.SettingChanged += delegate
			{
				ApplyPanelColour();
			};
			PopulateHotkey.SettingChanged += delegate
			{
				RefreshPanelText();
			};
			Mode.SettingChanged += delegate
			{
				UpdatePanelVisibility();
			};
			ShowManualPanel.SettingChanged += delegate
			{
				UpdatePanelVisibility();
			};
			Enabled.SettingChanged += delegate
			{
				UpdatePanelVisibility();
			};
			_harmony = new Harmony("acesgaminguk.supermarkettogether.ordertabletassistant");
			_harmony.PatchAll();
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			if (Object.op_Implicit((Object)(object)_nativePanel))
			{
				Object.Destroy((Object)(object)_nativePanel);
			}
			if (Instance == this)
			{
				Instance = null;
			}
		}

		internal void SetActiveDevice(OrderingDevice device)
		{
			_activeDevice = device;
			EnsureNativePanel();
			UpdatePanelVisibility();
			if (Enabled.Value && Mode.Value == PopulateMode.Automatic)
			{
				((MonoBehaviour)this).StartCoroutine(AutoPopulateNextFrame(device));
			}
		}

		private IEnumerator AutoPopulateNextFrame(OrderingDevice device)
		{
			yield return (object)new WaitForEndOfFrame();
			if (Object.op_Implicit((Object)(object)device) && ((Behaviour)device).isActiveAndEnabled)
			{
				RequestPopulate(device);
			}
		}

		private void Update()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			UpdatePanelVisibility();
			if (Enabled.Value && Mode.Value == PopulateMode.Manual && Object.op_Implicit((Object)(object)_activeDevice) && ((Behaviour)_activeDevice).isActiveAndEnabled)
			{
				if (Input.GetKeyDown(PopulateHotkey.Value))
				{
					RequestPopulate(_activeDevice);
				}
				HandlePanelDragging();
			}
		}

		private void EnsureNativePanel()
		{
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)_nativePanel) || (Object)(object)GameCanvas.Instance == (Object)null)
			{
				return;
			}
			Transform val = ((Component)GameCanvas.Instance).transform.Find("InteractableShowInfo/Container/TitleBCK");
			if (!Object.op_Implicit((Object)(object)val))
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not find the native HUD source: InteractableShowInfo/Container/TitleBCK");
				return;
			}
			_nativePanel = Object.Instantiate<GameObject>(((Component)val).gameObject, ((Component)GameCanvas.Instance).transform);
			((Object)_nativePanel).name = "OrderTabletAssistantPanel";
			_nativePanelRect = _nativePanel.GetComponent<RectTransform>();
			_nativePanelRect.anchorMin = new Vector2(0f, 1f);
			_nativePanelRect.anchorMax = new Vector2(0f, 1f);
			_nativePanelRect.pivot = new Vector2(0f, 1f);
			_nativePanelRect.sizeDelta = new Vector2(320f, 60f);
			_nativePanelRect.anchoredPosition = new Vector2(PanelX.Value, 0f - PanelY.Value);
			_nativePanelImage = _nativePanel.GetComponent<Image>();
			if (Object.op_Implicit((Object)(object)_nativePanelImage))
			{
				_nativePanelOriginalColour = ((Graphic)_nativePanelImage).color;
			}
			Transform obj = _nativePanel.transform.Find("Title_Text");
			_nativePanelText = ((obj != null) ? ((Component)obj).GetComponent<TextMeshProUGUI>() : null);
			if (!Object.op_Implicit((Object)(object)_nativePanelText))
			{
				_nativePanelText = _nativePanel.GetComponentInChildren<TextMeshProUGUI>(true);
			}
			if (Object.op_Implicit((Object)(object)_nativePanelText))
			{
				RectTransform rectTransform = ((TMP_Text)_nativePanelText).rectTransform;
				rectTransform.anchorMin = Vector2.zero;
				rectTransform.anchorMax = Vector2.one;
				rectTransform.offsetMin = new Vector2(10f, 4f);
				rectTransform.offsetMax = new Vector2(-10f, -4f);
				((TMP_Text)_nativePanelText).alignment = (TextAlignmentOptions)514;
				((TMP_Text)_nativePanelText).textWrappingMode = (TextWrappingModes)0;
				((TMP_Text)_nativePanelText).enableAutoSizing = true;
				((TMP_Text)_nativePanelText).fontSizeMin = 12f;
				((TMP_Text)_nativePanelText).fontSizeMax = 28f;
			}
			Graphic[] componentsInChildren = _nativePanel.GetComponentsInChildren<Graphic>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].raycastTarget = false;
			}
			ApplyPanelScale();
			ApplyPanelColour();
			RefreshPanelText();
			UpdatePanelVisibility();
		}

		private void ApplyPanelScale()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)_nativePanelRect))
			{
				float num = Mathf.Clamp(PanelScale.Value, 0.5f, 2f);
				((Transform)_nativePanelRect).localScale = new Vector3(num, num, 1f);
			}
		}

		private void ApplyPanelColour()
		{
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: 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_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: 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_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)_nativePanelImage))
			{
				Image nativePanelImage = _nativePanelImage;
				((Graphic)nativePanelImage).color = (Color)(PromptColourChoice.Value switch
				{
					"Purple" => new Color(0.36f, 0.16f, 0.46f, _nativePanelOriginalColour.a), 
					"Blue" => new Color(0f, 0.69f, 0.94f, _nativePanelOriginalColour.a), 
					"Orange" => new Color(0.93f, 0.49f, 0.19f, _nativePanelOriginalColour.a), 
					"Green" => new Color(0.18f, 0.65f, 0.31f, _nativePanelOriginalColour.a), 
					"Red" => new Color(0.85f, 0.1f, 0.1f, _nativePanelOriginalColour.a), 
					"Demo Red" => Color32.op_Implicit(new Color32((byte)64, (byte)2, (byte)2, (byte)Mathf.RoundToInt(_nativePanelOriginalColour.a * 255f))), 
					"Custom" => CustomPromptColour.Value, 
					_ => _nativePanelOriginalColour, 
				});
			}
		}

		private void RefreshPanelText()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)_nativePanelText))
			{
				((TMP_Text)_nativePanelText).text = $"Press {PopulateHotkey.Value} to Auto Fill";
			}
		}

		private void UpdatePanelVisibility()
		{
			if (!Object.op_Implicit((Object)(object)_nativePanel))
			{
				if ((Object)(object)GameCanvas.Instance != (Object)null)
				{
					EnsureNativePanel();
				}
				return;
			}
			bool flag = Enabled.Value && ShowManualPanel.Value && Mode.Value == PopulateMode.Manual && Object.op_Implicit((Object)(object)_activeDevice) && ((Behaviour)_activeDevice).isActiveAndEnabled;
			if (_nativePanel.activeSelf != flag)
			{
				_nativePanel.SetActive(flag);
			}
		}

		private void HandlePanelDragging()
		{
			//IL_0037: 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_0051: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//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_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)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)_nativePanel) || !_nativePanel.activeInHierarchy || !Cursor.visible)
			{
				_draggingPanel = false;
				return;
			}
			if (Input.GetMouseButtonDown(0) && RectTransformUtility.RectangleContainsScreenPoint(_nativePanelRect, Vector2.op_Implicit(Input.mousePosition), (Camera)null))
			{
				_draggingPanel = true;
				_lastMousePosition = Input.mousePosition;
			}
			if (_draggingPanel && Input.GetMouseButton(0))
			{
				Vector3 val = Input.mousePosition - _lastMousePosition;
				_lastMousePosition = Input.mousePosition;
				RectTransform nativePanelRect = _nativePanelRect;
				nativePanelRect.anchoredPosition += new Vector2(val.x, val.y);
				PanelX.Value = _nativePanelRect.anchoredPosition.x;
				PanelY.Value = 0f - _nativePanelRect.anchoredPosition.y;
			}
			if (Input.GetMouseButtonUp(0))
			{
				_draggingPanel = false;
			}
		}

		internal void RequestPopulate(OrderingDevice device)
		{
			if (!_scanInProgress && !(Time.unscaledTime - _lastPopulateTime < 0.5f) && Object.op_Implicit((Object)(object)device) && !((Object)(object)NPC_Manager.Instance == (Object)null) && !((Object)(object)ProductListing.Instance == (Object)null) && !((Object)(object)GameData.Instance == (Object)null))
			{
				((MonoBehaviour)this).StartCoroutine(ClearRefreshAndPopulate(device));
			}
		}

		private IEnumerator ClearRefreshAndPopulate(OrderingDevice device)
		{
			_scanInProgress = true;
			_lastPopulateTime = Time.unscaledTime;
			try
			{
				ClearShoppingListUiAndManager(device);
				yield return (object)new WaitForEndOfFrame();
				yield return null;
				if (Object.op_Implicit((Object)(object)device) && ((Behaviour)device).isActiveAndEnabled)
				{
					PopulateCleanTablet(device);
				}
			}
			finally
			{
				_scanInProgress = false;
			}
		}

		private void PopulateCleanTablet(OrderingDevice device)
		{
			if (AddProductBaseMethod == null || RetrievePricePerBoxMethod == null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Could not find the ordering tablet list methods. A game update may have changed OrderingDevice.");
				return;
			}
			try
			{
				int coveredByStorage = 0;
				Dictionary<int, int> dictionary;
				if (WhereToCheck.Value == "Storage Shelves Only")
				{
					dictionary = CountEmptyLabelledStorageSlots();
				}
				else
				{
					Dictionary<int, int> missingItems = CalculateMissingItemsByProduct();
					Dictionary<int, int> storageStock = CountStorageShelfItems();
					coveredByStorage = ApplyStorageStockToMissingItems(missingItems, storageStock);
					dictionary = ConvertMissingItemsToBoxes(missingItems);
					if (WhereToCheck.Value == "Shop and Storage Shelves")
					{
						MergeBoxCounts(dictionary, CountEmptyLabelledStorageSlots());
					}
				}
				int num = 0;
				foreach (KeyValuePair<int, int> item in dictionary)
				{
					for (int i = 0; i < item.Value; i++)
					{
						AddProductToOrderWithoutRefresh(device, item.Key);
						num++;
					}
				}
				RefreshOrderTotals(device);
				string text = BuildModeNotification(WhereToCheck.Value, num, coveredByStorage);
				ShowNativeNotification(text);
				((BaseUnityPlugin)this).Logger.LogMessage((object)("Order Tablet Assistant: " + text.Replace("\n", " | ")));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Failed to fill ordering tablet: " + ex));
				ShowNativeNotification("ORDER TABLET ASSISTANT\nAUTO FILL FAILED - CHECK LOG");
			}
		}

		private static void AddProductToOrderWithoutRefresh(OrderingDevice device, int productId)
		{
			AddProductBaseMethod.Invoke(device, new object[1] { productId });
			float num = (float)RetrievePricePerBoxMethod.Invoke(device, new object[1] { productId });
			((Component)GameData.Instance).GetComponent<ManagerBlackboard>().AddShoppingListProduct(productId, num);
		}

		private static void RefreshOrderTotals(OrderingDevice device)
		{
			if (CalculateShoppingListTotalMethod != null)
			{
				((MonoBehaviour)device).StartCoroutine((IEnumerator)CalculateShoppingListTotalMethod.Invoke(device, Array.Empty<object>()));
			}
		}

		private static string BuildModeNotification(string mode, int boxesAdded, int coveredByStorage)
		{
			if (mode == "Storage Shelves Only")
			{
				if (boxesAdded <= 0)
				{
					return "ORDER TABLET ASSISTANT\nNO EMPTY LABELLED STORAGE SLOTS";
				}
				return $"ORDER TABLET ASSISTANT\nADDED {boxesAdded} BOXES FOR STORAGE";
			}
			if (mode == "Shop and Storage Shelves")
			{
				if (boxesAdded > 0)
				{
					return $"ORDER TABLET ASSISTANT\nADDED {boxesAdded} BOXES FOR SHOP AND STORAGE\n{coveredByStorage} PRODUCTS COVERED BY STORAGE";
				}
				if (coveredByStorage > 0)
				{
					return $"ORDER TABLET ASSISTANT\nNO BOXES ADDED\n{coveredByStorage} SHOP PRODUCTS COVERED BY STORAGE";
				}
				return "ORDER TABLET ASSISTANT\nSHOP AND STORAGE ARE ALREADY COVERED";
			}
			if (boxesAdded > 0)
			{
				return $"ORDER TABLET ASSISTANT\nADDED {boxesAdded} BOXES FOR SHOP SHELVES\n{coveredByStorage} PRODUCTS COVERED BY STORAGE";
			}
			if (coveredByStorage > 0)
			{
				return $"ORDER TABLET ASSISTANT\nNO BOXES ADDED\n{coveredByStorage} SHOP PRODUCTS COVERED BY STORAGE";
			}
			return "ORDER TABLET ASSISTANT\nSHOP SHELVES ARE ALREADY COVERED";
		}

		private static Dictionary<int, int> CalculateMissingItemsByProduct()
		{
			Dictionary<int, int> dictionary = new Dictionary<int, int>();
			GameObject shelvesOBJ = NPC_Manager.Instance.shelvesOBJ;
			for (int i = 0; i < shelvesOBJ.transform.childCount; i++)
			{
				Data_Container component = ((Component)shelvesOBJ.transform.GetChild(i)).GetComponent<Data_Container>();
				if (!Object.op_Implicit((Object)(object)component) || component.productInfoArray == null)
				{
					continue;
				}
				int num = component.productInfoArray.Length / 2;
				for (int j = 0; j < num; j++)
				{
					int num2 = component.productInfoArray[j * 2];
					int num3 = component.productInfoArray[j * 2 + 1];
					if (num2 >= 0 && num3 >= 0)
					{
						int maxProductsPerRow = NPC_Manager.Instance.GetMaxProductsPerRow(i, num2);
						int num4 = Mathf.Max(0, maxProductsPerRow - num3);
						if (num4 > 0)
						{
							AddDictionaryValue(dictionary, num2, num4);
						}
					}
				}
			}
			return dictionary;
		}

		private static int ApplyStorageStockToMissingItems(Dictionary<int, int> missingItems, Dictionary<int, int> storageStock)
		{
			int num = 0;
			foreach (int item in new List<int>(missingItems.Keys))
			{
				int num2 = missingItems[item];
				int dictionaryValue = GetDictionaryValue(storageStock, item);
				if (dictionaryValue >= num2 && num2 > 0)
				{
					missingItems[item] = 0;
					num++;
				}
				else if (dictionaryValue > 0)
				{
					missingItems[item] = num2 - dictionaryValue;
				}
			}
			return num;
		}

		private static Dictionary<int, int> CountEmptyLabelledStorageSlots()
		{
			Dictionary<int, int> dictionary = new Dictionary<int, int>();
			GameObject storageOBJ = NPC_Manager.Instance.storageOBJ;
			if (!Object.op_Implicit((Object)(object)storageOBJ))
			{
				return dictionary;
			}
			for (int i = 0; i < storageOBJ.transform.childCount; i++)
			{
				Data_Container component = ((Component)storageOBJ.transform.GetChild(i)).GetComponent<Data_Container>();
				if (!Object.op_Implicit((Object)(object)component) || component.productInfoArray == null)
				{
					continue;
				}
				int num = component.productInfoArray.Length / 2;
				for (int j = 0; j < num; j++)
				{
					int num2 = component.productInfoArray[j * 2];
					int num3 = component.productInfoArray[j * 2 + 1];
					if (num2 >= 0 && num3 < 0)
					{
						AddDictionaryValue(dictionary, num2, 1);
					}
				}
			}
			return dictionary;
		}

		private static void MergeBoxCounts(Dictionary<int, int> target, Dictionary<int, int> extra)
		{
			foreach (KeyValuePair<int, int> item in extra)
			{
				AddDictionaryValue(target, item.Key, item.Value);
			}
		}

		private static Dictionary<int, int> CountStorageShelfItems()
		{
			Dictionary<int, int> dictionary = new Dictionary<int, int>();
			GameObject storageOBJ = NPC_Manager.Instance.storageOBJ;
			if (!Object.op_Implicit((Object)(object)storageOBJ))
			{
				return dictionary;
			}
			for (int i = 0; i < storageOBJ.transform.childCount; i++)
			{
				Data_Container component = ((Component)storageOBJ.transform.GetChild(i)).GetComponent<Data_Container>();
				if (!Object.op_Implicit((Object)(object)component) || component.productInfoArray == null)
				{
					continue;
				}
				int num = component.productInfoArray.Length / 2;
				for (int j = 0; j < num; j++)
				{
					int num2 = component.productInfoArray[j * 2];
					int num3 = component.productInfoArray[j * 2 + 1];
					if (num2 >= 0 && num3 > 0)
					{
						AddDictionaryValue(dictionary, num2, num3);
					}
				}
			}
			return dictionary;
		}

		private static Dictionary<int, int> ConvertMissingItemsToBoxes(Dictionary<int, int> missingItems)
		{
			Dictionary<int, int> dictionary = new Dictionary<int, int>();
			foreach (KeyValuePair<int, int> missingItem in missingItems)
			{
				if (missingItem.Value > 0)
				{
					int maxItemsPerBox = ProductListing.Instance.productsData[missingItem.Key].maxItemsPerBox;
					if (maxItemsPerBox > 0)
					{
						dictionary[missingItem.Key] = Mathf.CeilToInt((float)missingItem.Value / (float)maxItemsPerBox);
					}
				}
			}
			return dictionary;
		}

		private static void ClearShoppingListUiAndManager(OrderingDevice device)
		{
			ManagerBlackboard component = ((Component)GameData.Instance).GetComponent<ManagerBlackboard>();
			GameObject shoppingListParent = component.shoppingListParent;
			for (int num = (Object.op_Implicit((Object)(object)shoppingListParent) ? shoppingListParent.transform.childCount : 0) - 1; num >= 0; num--)
			{
				component.RemoveShoppingListProduct(num);
			}
			DestroyUiObjectsMethod?.Invoke(device, Array.Empty<object>());
		}

		private static void ShowNativeNotification(string message)
		{
			if ((Object)(object)GameCanvas.Instance == (Object)null)
			{
				return;
			}
			GameObject val = (Object.op_Implicit((Object)(object)GameCanvas.Instance.importantNotificationPrefab) ? GameCanvas.Instance.importantNotificationPrefab : GameCanvas.Instance.notificationPrefab);
			Transform val2 = (Object.op_Implicit((Object)(object)GameCanvas.Instance.importantNotificationPrefab) ? GameCanvas.Instance.importantNotificationParentTransform : GameCanvas.Instance.notificationParentTransform);
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val2))
			{
				Plugin instance = Instance;
				if (instance != null)
				{
					((BaseUnityPlugin)instance).Logger.LogWarning((object)"Could not find the game's notification prefab or parent.");
				}
				return;
			}
			GameObject val3 = Object.Instantiate<GameObject>(val, val2);
			TextMeshProUGUI val4 = val3.GetComponent<TextMeshProUGUI>();
			if (!Object.op_Implicit((Object)(object)val4))
			{
				val4 = val3.GetComponentInChildren<TextMeshProUGUI>(true);
			}
			if (Object.op_Implicit((Object)(object)val4))
			{
				((TMP_Text)val4).text = message;
			}
			val3.SetActive(true);
		}

		private static void AddDictionaryValue(Dictionary<int, int> dictionary, int key, int value)
		{
			if (!dictionary.ContainsKey(key))
			{
				dictionary[key] = 0;
			}
			dictionary[key] += value;
		}

		private static int GetDictionaryValue(Dictionary<int, int> dictionary, int key)
		{
			if (!dictionary.TryGetValue(key, out var value))
			{
				return 0;
			}
			return value;
		}
	}
	public enum PopulateMode
	{
		Manual,
		Automatic
	}
	[HarmonyPatch(typeof(OrderingDevice), "OnEnable")]
	internal static class OrderingDevice_OnEnable_Patch
	{
		private static void Postfix(OrderingDevice __instance)
		{
			if (!((Object)(object)Plugin.Instance == (Object)null) && Plugin.Enabled.Value)
			{
				Plugin.Instance.SetActiveDevice(__instance);
			}
		}
	}
	internal static class PluginInfo
	{
		public const string Guid = "acesgaminguk.supermarkettogether.ordertabletassistant";

		public const string Name = "OrderTabletAssistant";

		public const string DisplayName = "Order Tablet Assistant";

		public const string Version = "1.0.0";

		public const string Author = "AcesGamingUK";

		public const string Website = "https://github.com/AcesGamingUK/Order-Tablet-Assistant";
	}
}