using RioJoy.Core.Protocol;
using Xunit;

namespace RioJoy.Core.Tests.Protocol;

public class RioCommandTableTests
{
    [Theory]
    [InlineData(RioCommand.CheckRequest, 0)]
    [InlineData(RioCommand.VersionRequest, 0)]
    [InlineData(RioCommand.AnalogRequest, 0)]
    [InlineData(RioCommand.ResetRequest, 1)]
    [InlineData(RioCommand.LampRequest, 2)]
    [InlineData(RioCommand.CheckReply, 2)]
    [InlineData(RioCommand.VersionReply, 2)]
    [InlineData(RioCommand.AnalogReply, 10)]
    [InlineData(RioCommand.ButtonPressed, 1)]
    [InlineData(RioCommand.ButtonReleased, 1)]
    [InlineData(RioCommand.KeyPressed, 2)]
    [InlineData(RioCommand.KeyReleased, 2)]
    [InlineData(RioCommand.TestModeChange, 1)]
    public void PayloadLengths_MatchProtocol(RioCommand command, int expected)
    {
        Assert.Equal(expected, RioCommandTable.PayloadLength(command));
    }

    [Fact]
    public void Bounds_AreInclusive()
    {
        Assert.Equal(0x80, RioCommandTable.Base);
        Assert.Equal(0x8C, RioCommandTable.Max);
        Assert.Equal(13, RioCommandTable.Count);
    }

    [Theory]
    [InlineData(0x7F, false)]
    [InlineData(0x80, true)]
    [InlineData(0x8C, true)]
    [InlineData(0x8D, false)]
    [InlineData(0xFC, false)]
    public void IsCommand_RespectsRange(byte b, bool expected)
    {
        Assert.Equal(expected, RioCommandTable.IsCommand(b));
    }

    [Fact]
    public void PayloadLength_ThrowsForNonCommand()
    {
        Assert.Throws<ArgumentOutOfRangeException>(() => RioCommandTable.PayloadLength((byte)0x8D));
    }
}
