using Content.Client.UserInterface.Controls;
using Content.Shared.DeltaV.VendingMachines;
using Content.Shared.Stacks;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics;
using Robust.Client.Player;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using System.Numerics;
namespace Content.Client.DeltaV.VendingMachines.UI;
[GenerateTypedNameReferences]
public sealed partial class ShopVendorWindow : FancyWindow
{
[Dependency] private readonly IComponentFactory _factory = default!;
[Dependency] private readonly IEntityManager _entMan = default!;
[Dependency] private readonly IPlayerManager _player = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
private readonly ShopVendorSystem _vendor;
///
/// Event fired with the listing index to purchase.
///
public event Action? OnItemSelected;
private EntityUid _owner;
private readonly StyleBoxFlat _style = new() { BackgroundColor = new Color(70, 73, 102) };
private readonly StyleBoxFlat _styleBroke = new() { BackgroundColor = Color.FromHex("#303133") };
private readonly List _buttons = new();
private uint _balance = 1;
public ShopVendorWindow()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
_vendor = _entMan.System();
VendingContents.SearchBar = SearchBar;
VendingContents.DataFilterCondition += DataFilterCondition;
VendingContents.GenerateItem += GenerateButton;
VendingContents.ItemKeyBindDown += (args, data) => OnItemSelected?.Invoke(((ShopVendorListingData) data).Index);
}
public void SetEntity(EntityUid owner)
{
_owner = owner;
if (!_entMan.TryGetComponent(owner, out var comp))
return;
var pack = _proto.Index(comp.Pack);
Populate(pack.Listings);
UpdateBalance();
}
private void UpdateBalance(uint balance)
{
if (_balance == balance)
return;
_balance = balance;
BalanceLabel.Text = Loc.GetString("shop-vendor-balance", ("points", balance));
// disable items that are too expensive to buy
foreach (var button in _buttons)
{
if (button.Data is ShopVendorListingData data)
button.Disabled = data.Cost > balance;
button.StyleBoxOverride = button.Disabled ? _styleBroke : _style;
}
}
private void UpdateBalance()
{
if (_player.LocalEntity is {} user)
UpdateBalance(_vendor.GetBalance(_owner, user));
}
private bool DataFilterCondition(string filter, ListData data)
{
if (data is not ShopVendorListingData { Text: var text })
return false;
if (string.IsNullOrEmpty(filter))
return true;
return text.Contains(filter, StringComparison.CurrentCultureIgnoreCase);
}
private void GenerateButton(ListData data, ListContainerButton button)
{
if (data is not ShopVendorListingData cast)
return;
_buttons.Add(button);
button.AddChild(new ShopVendorItem(cast.ItemId, cast.Text, cast.Cost));
button.ToolTip = cast.Text;
button.Disabled = cast.Cost > _balance;
button.StyleBoxOverride = button.Disabled ? _styleBroke : _style;
}
public void Populate(List listings)
{
var longestEntry = string.Empty;
var listData = new List();
for (var i = 0; i < listings.Count; i++)
{
var listing = listings[i];
var proto = _proto.Index(listing.Id);
var text = proto.Name;
if (proto.TryGetComponent(out var stack, _factory) && stack.Count > 1)
{
text += " ";
text += Loc.GetString("shop-vendor-stack-suffix", ("count", stack.Count));
}
listData.Add(new ShopVendorListingData(i, listing.Id, text, listing.Cost));
}
_buttons.Clear();
VendingContents.PopulateList(listData);
SetSizeAfterUpdate(longestEntry.Length, listings.Count);
}
private void SetSizeAfterUpdate(int longestEntryLength, int contentCount)
{
SetSize = new Vector2(Math.Clamp((longestEntryLength + 2) * 12, 250, 400),
Math.Clamp(contentCount * 50, 150, 350));
}
protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
UpdateBalance();
}
}
public record ShopVendorListingData(int Index, EntProtoId ItemId, string Text, uint Cost) : ListData;