using RioJoy.Core.Mapping;
using Xunit;

namespace RioJoy.Core.Tests.Mapping;

public class RioMapEntryTests
{
    [Fact]
    public void Keyboard_NoRoutingFlags_DecodesModifiersAndValue()
    {
        // 0x8749 = hasLamp + alt + ctrl + shift, VK 0x49 ('I')
        var e = new RioMapEntry(0x8749);
        Assert.Equal(RioRouteKind.Keyboard, e.Kind);
        Assert.True(e.HasLamp);
        Assert.True(e.Alt);
        Assert.True(e.Ctrl);
        Assert.True(e.Shift);
        Assert.False(e.Extended);
        Assert.Equal(0x49, e.Value);
    }

    [Fact]
    public void Extended_FlagDecodes()
    {
        // 0x88BE = hasLamp + extended, VK 0xBE
        var e = new RioMapEntry(0x88BE);
        Assert.Equal(RioRouteKind.Keyboard, e.Kind);
        Assert.True(e.HasLamp);
        Assert.True(e.Extended);
        Assert.Equal(0xBE, e.Value);
    }

    [Theory]
    [InlineData(0x1009, RioRouteKind.Joystick)] // joy flag
    [InlineData(0x2003, RioRouteKind.Hat)]      // hat flag
    [InlineData(0x4002, RioRouteKind.Mouse)]    // mouse flag
    [InlineData(0x7005, RioRouteKind.RioCommand)] // joy+hat+mouse → command
    [InlineData(0x0041, RioRouteKind.Keyboard)] // none → keyboard
    public void Kind_FollowsPrecedence(ushort raw, RioRouteKind expected)
    {
        Assert.Equal(expected, new RioMapEntry(raw).Kind);
    }

    [Fact]
    public void Joystick_BeatsHatAndMouse_WhenMultipleSet()
    {
        // joy + hat set (but not mouse) → joystick wins
        Assert.Equal(RioRouteKind.Joystick, new RioMapEntry(0x3001).Kind);
        // hat + mouse set (but not joy) → hat wins
        Assert.Equal(RioRouteKind.Hat, new RioMapEntry(0x6001).Kind);
    }

    [Fact]
    public void Unmapped_IsZero()
    {
        Assert.True(new RioMapEntry(0).IsUnmapped);
        Assert.False(new RioMapEntry(0x0041).IsUnmapped);
    }
}
