namespace ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Wire;

/// <summary>
///     Return envelope over a parsed wire response. <see cref="Rc"/> carries the FOCAS
///     <c>EW_*</c> code from the response block — <c>0</c> / <see cref="IsOk"/> means the
///     call succeeded and <see cref="Value"/> is populated; non-zero means the CNC rejected
///     the call and <see cref="Value"/> is <c>default</c>. Callers use the RC to distinguish
///     "feature missing on this series" (<c>EW_FUNC</c> / <c>EW_NOOPT</c>) from genuine
///     failures.
/// </summary>
public readonly record struct FocasResult<T>(short Rc, T? Value)
{
    /// <summary>True when <see cref="Rc"/> is zero (<c>EW_OK</c>).</summary>
    public bool IsOk => Rc == 0;
}

/// <summary>CNC identity payload returned by <c>cnc_sysinfo</c>.</summary>
public sealed record WireSysInfo(
    short AddInfo,
    short MaxAxis,
    string CncType,
    string MachineType,
    string Series,
    string Version,
    string Axes);

/// <summary>Coarse CNC state bits returned by <c>cnc_statinfo</c> — the seven-word status block plus TM mode.</summary>
public sealed record WireStatus(
    short Auto,
    short Run,
    short Motion,
    short Mstb,
    short Emergency,
    short Alarm,
    short Edit,
    short TmMode);

/// <summary>Four-slot position quadruple for one axis: absolute / machine / relative / distance-to-go.</summary>
public sealed record WireAxisPosition(
    int Absolute,
    int Machine,
    int Relative,
    int Distance);

/// <summary>
///     Fast-poll bundle for one axis from <c>cnc_rddynamic2</c> — alarm flags, active program
///     numbers, sequence number, actual feed rate, actual spindle speed, and the position
///     quadruple.
/// </summary>
public sealed record WireDynamic(
    int Alarm,
    int ProgramNumber,
    int MainProgramNumber,
    int SequenceNumber,
    int FeedRate,
    int SpindleSpeed,
    WireAxisPosition Axis);

/// <summary>One servo-meter entry from <c>cnc_rdsvmeter</c> — per-axis load percentage (scale by 10^<see cref="Decimal"/>).</summary>
public sealed record WireServoMeter(
    short Index,
    string Name,
    int Value,
    short Decimal,
    short Unit);

/// <summary>One spindle metric slot from <c>cnc_rdspload</c> / <c>cnc_rdspmaxrpm</c>.</summary>
public sealed record WireSpindleMetric(
    short Index,
    int Value);

/// <summary>
///     One axis-name slot from <c>cnc_rdaxisname</c>. <see cref="Index"/> is the 1-based
///     axis index (preserved even when the name is empty so callers can pass it to
///     <c>cnc_rddynamic2</c>).
/// </summary>
public readonly record struct WireAxisRecord(short Index, string Name);

/// <summary>One spindle-name slot from <c>cnc_rdspdlname</c>.</summary>
public readonly record struct WireSpindleRecord(short Index, string Name);

/// <summary>Parameter value returned by <c>cnc_rdparam</c>, interpreted as a scalar Int32.</summary>
public sealed record WireParameter(
    short DataNumber,
    short Type,
    int Value);

/// <summary>
///     Macro variable from <c>cnc_rdmacro</c>. Scaled decimal: the callable value is
///     <c>Value / 10^Decimal</c>.
/// </summary>
public sealed record WireMacro(
    short Number,
    int Value,
    short Decimal);

/// <summary>PMC range read-back from <c>pmc_rdpmcrng</c>: one or more values of the requested width.</summary>
public sealed record WirePmcRange(
    short Area,
    short DataType,
    ushort Start,
    ushort End,
    IReadOnlyList<long> Values);

/// <summary>
///     One active alarm from <c>cnc_rdalmmsg2</c>. Mirrors the vendor <c>ODBALMMSG2</c>
///     layout; <see cref="AlarmGroup"/> is populated when the wire responder carries it
///     (currently <c>null</c> for both the 76-byte vendor shape and the 80-byte legacy
///     shape).
/// </summary>
public sealed record WireAlarm(
    int AlarmNumber,
    short Type,
    short Axis,
    short MessageLength,
    string Message,
    int? AlarmGroup = null);

/// <summary>
///     Executing-program identity from <c>cnc_exeprgname2</c>: the NUL-terminated name and
///     the trailing 32-bit O-number (null when the wire responder omits the trailing int).
/// </summary>
public sealed record WireProgramName(
    string Name,
    int? ONumber);

/// <summary>One cumulative timer reading from <c>cnc_rdtimer</c> (minutes + fractional milliseconds).</summary>
public sealed record WireTimer(
    short Type,
    int Minutes,
    int Milliseconds);
