using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Client.Guidebook.Richtext;
using Content.Shared.Chemistry.Reagent;
using JetBrains.Annotations;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
namespace Content.Client.Guidebook.Controls;
///
/// Control for embedding a reagent into a guidebook.
///
[UsedImplicitly, GenerateTypedNameReferences]
public sealed partial class GuideReagentGroupEmbed : BoxContainer, IDocumentTag
{
[Dependency] private readonly ILogManager _logManager = default!;
[Dependency] private readonly IPrototypeManager _prototype = default!;
private readonly ISawmill _sawmill;
public GuideReagentGroupEmbed()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
_sawmill = _logManager.GetSawmill("guidebook.reagent_group");
MouseFilter = MouseFilterMode.Stop;
}
public GuideReagentGroupEmbed(string group) : this()
{
var prototypes = _prototype.EnumeratePrototypes()
.Where(p => ReagentBelongsToGroup(p, group)).OrderBy(p => p.LocalizedName);
foreach (var reagent in prototypes)
{
var embed = new GuideReagentEmbed(reagent);
GroupContainer.AddChild(embed);
}
}
public bool TryParseTag(Dictionary args, [NotNullWhen(true)] out Control? control)
{
control = null;
if (!args.TryGetValue("Group", out var group))
{
_sawmill.Error("Reagent group embed tag is missing group argument");
return false;
}
try
{
var prototypes = _prototype.EnumeratePrototypes()
.Where(p => ReagentBelongsToGroup(p, group)).OrderBy(p => p.LocalizedName).ToList();
foreach (var reagent in prototypes)
{
try
{
var embed = new GuideReagentEmbed(reagent);
GroupContainer.AddChild(embed);
}
catch (Exception e)
{
_sawmill.Error($"Failed to create GuideReagentEmbed for reagent '{reagent.ID}': {e}");
}
}
}
catch (Exception e)
{
_sawmill.Error($"Failed to enumerate reagents for group '{group}': {e}");
return false;
}
control = this;
return true;
}
///
/// Horizon: Checks if a reagent belongs to a group, including inherited groups from parent prototypes.
///
private bool ReagentBelongsToGroup(ReagentPrototype reagent, string group)
{
// Check direct group
if (reagent.Group.Equals(group))
return true;
// Check parent prototypes for inherited group
if (reagent.Parents == null || reagent.Parents.Length == 0)
return false;
foreach (var parentId in reagent.Parents)
{
// Use Index instead of TryIndex since abstract prototypes should still be accessible
if (!_prototype.HasIndex(parentId))
continue;
var parent = _prototype.Index(parentId);
if (ReagentBelongsToGroup(parent, group))
return true;
}
return false;
}
}