namespace RioJoy.Core.Serial;

/// <summary>Tunables for <see cref="RioSerialLink"/>.</summary>
public sealed record RioSerialLinkOptions
{
    /// <summary>
    /// How often to request an analog update while the link runs. The legacy
    /// watch thread polls on a ~55 ms timeout (riovjoy2.cpp#L1069).
    /// </summary>
    public TimeSpan AnalogPollInterval { get; init; } = TimeSpan.FromMilliseconds(55);

    /// <summary>
    /// If no <see cref="Protocol.RioCommand.AnalogReply"/> arrives within this
    /// window, issue a general reset to recover (legacy &gt;5 s rule,
    /// riovjoy2.cpp#L1096).
    /// </summary>
    public TimeSpan AnalogRecoveryTimeout { get; init; } = TimeSpan.FromSeconds(5);

    /// <summary>Whether the link should automatically poll for analog updates.</summary>
    public bool AutoPollAnalog { get; init; } = true;

    /// <summary>
    /// When <see langword="true"/>, a button packet that fails its checksum is
    /// NAK'd (the documented protocol). When <see langword="false"/> (default),
    /// every framed packet is ACK'd regardless of checksum, matching the legacy
    /// receive path which force-accepts (see docs/PROTOCOL.md §2 ⚠️).
    /// </summary>
    public bool VerifyInboundChecksum { get; init; }

    /// <summary>Read buffer size for the receive loop.</summary>
    public int ReadBufferSize { get; init; } = 256;

    /// <summary>
    /// How many times a command packet is retransmitted when the board NAKs it
    /// or the ACK never arrives (0 = fire-and-forget, the pre-2026-07 behavior).
    /// Commands use stop-and-wait: ONE command in flight, resolved by
    /// ACK / NAK / <see cref="AckTimeout"/> before the next is written. The
    /// first (NAK-race) design resent "the most recent" packet and misfired
    /// under mash bursts — by the time a NAK crossed USB, a newer command was
    /// already the latest, so the corrupted write stayed lost (bench
    /// 2026-07-19); with one-in-flight the attribution is exact, and the
    /// timeout also catches corruptions so complete the board never NAKs.
    /// </summary>
    public int CommandRetransmitLimit { get; init; } = 2;

    /// <summary>
    /// How long to wait for the board's ACK/NAK of a command before treating it
    /// as lost (stop-and-wait; see <see cref="CommandRetransmitLimit"/>). Board
    /// turnaround is ~1-4 ms; 50 ms is generous without stalling the 55 ms
    /// analog poll cadence on a healthy link.
    /// </summary>
    public TimeSpan AckTimeout { get; init; } = TimeSpan.FromMilliseconds(50);
}
