using RioJoy.Core.Editing;
using Xunit;

namespace RioJoy.Core.Tests.Editing;

public class SheetLayoutTests
{
    [Theory]
    [InlineData("0F", 0x0F)]
    [InlineData("50", 0x50)]
    [InlineData("6F", 0x6F)]
    [InlineData("00", 0x00)]
    public void AddressFromText_ParsesHexCells(string text, int expected)
    {
        Assert.Equal(expected, SheetLayout.AddressFromText(text));
    }

    [Theory]
    [InlineData("HOME")]
    [InlineData("RIO_0")]
    [InlineData("70")]   // > 0x6F
    [InlineData("M U")]
    [InlineData("0")]    // single digit
    public void AddressFromText_RejectsNonAddresses(string text)
    {
        Assert.Null(SheetLayout.AddressFromText(text));
    }

    [Theory]
    [InlineData(0x00, SheetSection.Contacts)]
    [InlineData(0x10, SheetSection.Secondary)]
    [InlineData(0x18, SheetSection.Screen)]
    [InlineData(0x2F, SheetSection.Letters)]
    [InlineData(0x38, SheetSection.Throttle)]
    [InlineData(0x40, SheetSection.Joystick)]
    [InlineData(0x50, SheetSection.Keypad)]
    [InlineData(0x6F, SheetSection.ExtKeypad)]
    public void SectionForAddress_Classifies(int address, SheetSection expected)
    {
        Assert.Equal(expected, SheetLayout.SectionForAddress(address));
    }

    [Fact]
    public void Parse_BuildsCellsWithGridPositions()
    {
        const string csv =
            "\"\",\"IsLit\",\"\",\"\",\"0F\"\n" +
            "\"\",\"\",\"\",\"\",\"HOME\"";

        IList<SheetCell> cells = SheetLayout.Parse(csv);

        SheetCell addr = Assert.Single(cells, c => c.Text == "0F");
        Assert.Equal(0x0F, addr.Address);
        Assert.Equal(SheetSection.Contacts, addr.Section);
        Assert.Equal(0, addr.Row);
        Assert.Equal(4, addr.Col);

        SheetCell key = Assert.Single(cells, c => c.Text == "HOME");
        Assert.Null(key.Address);
        Assert.Equal(1, key.Row);
        Assert.Equal(4, key.Col);
    }

    [Fact]
    public void Parse_RealSheet_HasFullAddressMap()
    {
        IList<SheetCell> cells = SheetLayout.Load(
            TestRepo.CustomBackground("config-sheet.csv"));

        // Every RIO address 0x00..0x6F that exists should appear exactly once as a cell.
        var addresses = cells.Where(c => c.Address is not null).Select(c => c.Address!.Value).ToHashSet();
        Assert.Contains(0x00, addresses);
        Assert.Contains(0x2F, addresses); // a letter button
        Assert.Contains(0x50, addresses); // keypad
        Assert.Contains(0x6F, addresses); // ext keypad
        Assert.True(addresses.Count >= 100, $"expected most of the address map, got {addresses.Count}");
    }
}
