using ScadaLink.CentralUI.ScriptAnalysis;

namespace ScadaLink.CentralUI.Components.Shared;

/// <summary>
/// Maps the trigger editors' flattened <see cref="AlarmAttributeChoice"/> list
/// into the metadata the <see cref="MonacoEditor"/> uses to drive C# completion
/// inside an expression trigger:
/// <list type="bullet">
///   <item>Direct + Inherited choices become <see cref="AttributeShape"/>s,
///   surfaced under <c>Attributes["..."]</c>.</item>
///   <item>Composed choices — whose canonical name is dotted, e.g.
///   <c>CoolingTank.Temp</c> — are grouped by their composition-instance prefix
///   into <see cref="CompositionContext"/>s, surfaced under
///   <c>Children["..."].Attributes["..."]</c>.</item>
/// </list>
/// </summary>
public static class TriggerAttributeMapper
{
    /// <summary>Direct and inherited attributes, exposed as <c>Attributes["..."]</c>.</summary>
    public static IReadOnlyList<AttributeShape> SelfAttributes(
        IReadOnlyList<AlarmAttributeChoice> choices) =>
        choices
            .Where(c => c.Source is "Direct" or "Inherited")
            .Select(c => new AttributeShape(c.CanonicalName, c.DataType))
            .ToList();

    /// <summary>
    /// Composed attributes grouped by composition-instance name, exposed as
    /// <c>Children["X"].Attributes["Y"]</c>. Entries without a dotted prefix
    /// are skipped (no child scope to attach them to).
    /// </summary>
    public static IReadOnlyList<CompositionContext> Children(
        IReadOnlyList<AlarmAttributeChoice> choices) =>
        choices
            .Where(c => c.Source == "Composed" && c.CanonicalName.Contains('.'))
            .Select(c => new
            {
                Child = c.CanonicalName[..c.CanonicalName.IndexOf('.')],
                Member = c.CanonicalName[(c.CanonicalName.IndexOf('.') + 1)..],
                c.DataType
            })
            .GroupBy(x => x.Child, StringComparer.Ordinal)
            .Select(g => new CompositionContext(
                g.Key,
                g.Select(x => new AttributeShape(x.Member, x.DataType)).ToList(),
                Array.Empty<ScriptShape>()))
            .ToList();
}
