using System.Globalization;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using ZB.MOM.WW.ScadaBridge.Commons.Types.Debugging;
namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Shared;
///
/// Vertical trace list over a (Flow Debugger mockup Direction B, Gitea #53): the
/// steps in display order with the lane as a column, filterable by lane and to failures only.
///
public partial class FlowTraceList : ComponentBase
{
/// The real graph (from a run or a replay); null before a run.
[Parameter] public FlowGraph? Graph { get; set; }
/// The selected step's event id.
[Parameter] public Guid? SelectedEventId { get; set; }
/// Raised when a row is clicked or activated with Enter/Space.
[Parameter] public EventCallback OnSelect { get; set; }
private string _laneFilter = "";
private bool _failedOnly;
private IReadOnlyList<(FlowStep Step, int Index)> Rows()
{
if (Graph == null) return Array.Empty<(FlowStep, int)>();
// The ordinal is the step's position in the whole flow, so it stays stable while filtering.
IEnumerable<(FlowStep, int)> q = Graph.Steps.Select((s, i) => (s, i));
if (Enum.TryParse(_laneFilter, out var lane)) q = q.Where(t => t.Item1.Lane == lane);
if (_failedOnly) q = q.Where(t => IsFailure(t.Item1));
return q.ToList();
}
internal static bool IsFailure(FlowStep s) => s.Outcome is FlowStepOutcome.Failed or FlowStepOutcome.TimedOut;
private string Offset(FlowStep s)
{
var first = Graph!.Steps[0].OccurredAtUtc;
var ms = (s.OccurredAtUtc - first).TotalMilliseconds;
return "+" + ms.ToString("0", CultureInfo.InvariantCulture) + " ms";
}
private async Task OnKeyAsync(KeyboardEventArgs e, FlowStep s)
{
if (e.Key is "Enter" or " ") await OnSelect.InvokeAsync(s);
}
private static string PillClass(FlowStepOutcome outcome) => outcome switch
{
FlowStepOutcome.Ok => "ft-pill ok",
FlowStepOutcome.Pending => "ft-pill pending",
FlowStepOutcome.Parked => "ft-pill parked",
FlowStepOutcome.Failed or FlowStepOutcome.TimedOut => "ft-pill failed",
_ => "ft-pill",
};
internal static string KindLabel(FlowStepKind kind) => kind switch
{
FlowStepKind.InboundRequest => "Request",
FlowStepKind.RouteCall => "Route call",
FlowStepKind.ScriptRun => "Script run",
FlowStepKind.AttributeWrite => "Write",
FlowStepKind.AttributeWait => "Wait",
FlowStepKind.Response => "Response",
FlowStepKind.ApiCall => "API call",
FlowStepKind.DbCall => "Database",
FlowStepKind.Notify => "Notify",
_ => "Step",
};
}