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). Length matches
    /// <see cref="RioCommandTable.PayloadLength(RioCommand)"/>.
    /// </summary>
    public ReadOnlyMemory<byte> Payload { get; }

    public RioPacket(RioCommand command, ReadOnlyMemory<byte> 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 = Convert.ToHexString(Payload.Span);
        return Payload.IsEmpty ? Command.ToString() : $"{Command} [{hex}]";
    }
}
