namespace RioJoy.Core.Protocol;

/// <summary>
/// A fully-framed RIO packet: a command plus its fixed-length payload (the
/// 7-bit data bytes between the command byte and the checksum). The checksum
/// itself is not stored — it is validated/derived at the framing boundary.
/// </summary>
public readonly struct RioPacket
{
    /// <summary>The command byte.</summary>
    public RioCommand Command { get; }

    /// <summary>
    /// The payload bytes (high bit always clear; treat as read-only). Length
    /// matches <see cref="RioCommandTable.PayloadLength(RioCommand)"/>.
    /// </summary>
    public byte[] Payload { get; }

    public RioPacket(RioCommand command, byte[] payload)
    {
        if (payload is null) throw new ArgumentNullException(nameof(payload));
        int expected = RioCommandTable.PayloadLength(command);
        if (payload.Length != expected)
            throw new ArgumentException(
                $"{command} expects a {expected}-byte payload, got {payload.Length}.",
                nameof(payload));

        Command = command;
        Payload = payload;
    }

    public override string ToString()
    {
        var hex = BitConverter.ToString(Payload).Replace("-", string.Empty);
        return Payload.Length == 0 ? Command.ToString() : $"{Command} [{hex}]";
    }
}
