UI/Components/UpgradeShop.razor
@using Sandbox.UI;
@inherits Panel
@namespace PlanetMeat

<root>
	@if (CategoryOrder.Count >= 5)
	{
		<div class="catnav">
			@foreach (var category in CategoryOrder)
			{
				var cat = Catalogue.Current.GetCategory(category);
				<button class="click-active" onclick=@(() => ScrollToCategory(cat))>
					<span>@(cat.DisplayIcon)</span>
				</button>
			}
		</div>
	}
	<div class="shop scroll-v pm-inset" @ref="ScrollDiv">
		@foreach (var category in CategoryOrder)
		{
			var cat = Catalogue.Current.GetCategory(category);
			<div id="@(cat.Ident)" class="category">
				<span class="mat-icon">@(cat.DisplayIcon)</span>
				<span class="cat-name">#@(cat.DisplayName)</span>
			</div>

			foreach (var item in Items[category])
			{
				<UpgradeShopItem Currency=@Currency Upgrade=@item OnBeginBuy=@(() => BeginBuying(item)) OnEndBuy=@EndBuying>
				</UpgradeShopItem>
			}
		}
	</div>
</root>

@code
{
	private const float BUY_RATE_INITIAL = 0.3f;
	private const float BUY_RATE_FASTER = 0.15f;
	private const float BUY_RATE_FASTEST = 0.075f;

	public Dictionary<string, List<IPurchaseableUpgrade>> Items { get => field ??= Catalogue.Current.Upgrades; }
	public List<string> CategoryOrder { get => field ??= Catalogue.Current.CategoryOrder; }
	public string Currency { get; set; } = "goop";

	private IPurchaseableUpgrade BuyingUpgrade { get; set; }
	private int UntilBuyRateIncrease { get; set; }
	private float BuyRate = BUY_RATE_INITIAL;
	private float BuyProgress = 0.0f;

	private Panel ScrollDiv { get; set; }

	private void ScrollToCategory(Catalogue.Category cat)
	{
		if (ScrollDiv.Children.FirstOrDefault(c => c.Id == cat.Ident, null) is Panel p)
			ScrollDiv.ScrollTo(ScrollDiv.ScrollOffset + p.Box.Rect.Position - ScrollDiv.Box.RectInner.Position);
	}

	private void BeginBuying(IPurchaseableUpgrade up)
	{
		if (up is null)
			return;

		up.TryPurchase();
		BuyRate = BUY_RATE_INITIAL;
		BuyingUpgrade = up;
		UntilBuyRateIncrease = 3;
		BuyProgress = 0.0f;
	}

	private void EndBuying()
	{
		BuyingUpgrade = null;
	}

	private void MakeHeldPurchase()
	{
		var br = BuyRate;
		BuyProgress -= br;
		BuyingUpgrade.TryPurchase();

		if (UntilBuyRateIncrease > 0)
		{
			UntilBuyRateIncrease--;
			if (UntilBuyRateIncrease <= 0)
			{
				if (br.AlmostEqual(BUY_RATE_INITIAL))
				{
					BuyRate = BUY_RATE_FASTER;
					UntilBuyRateIncrease = 10;
				}
				else if (br.AlmostEqual(BUY_RATE_FASTER))
				{
					BuyRate = BUY_RATE_FASTEST;
				}
			}
		}
	}
	public override void Tick()
	{
		base.Tick();
		if (BuyingUpgrade is not null)
		{
			BuyProgress += Time.Delta;
			while (BuyProgress >= BuyRate)
				MakeHeldPurchase();
		}
	}

	protected override int BuildHash() => System.HashCode.Combine(
		Items.HashContents(),
		CategoryOrder.HashContents(),
		Currency
	);
}