namespace RioJoy.Core.Mapping;

/// <summary>
/// Translates raw RIO events into an <c>iRIO</c> table address. The 72 digital
/// buttons map to <c>0x00–0x47</c> directly; keypad 0 is offset by <c>0x50</c>
/// and keypad 1 by <c>0x60</c> (port of <c>KeypadEvent</c>, riovjoy2.cpp#L1185);
/// see docs/PROTOCOL.md §5.
/// </summary>
public static class RioAddress
{
    /// <summary>Number of digital button inputs (addresses 0x00–0x47).</summary>
    public const int ButtonCount = 72;

    /// <summary>Address offset added to keypad-0 key indices.</summary>
    public const int Keypad0Base = 0x50;

    /// <summary>Address offset added to keypad-1 key indices.</summary>
    public const int Keypad1Base = 0x60;

    /// <summary>Highest valid address (keypad 1, index 0x0F).</summary>
    public const int MaxAddress = Keypad1Base + 0x0F; // 0x6F

    /// <summary>Size of the <c>iRIO</c> table (addresses 0x00..0x6F inclusive).</summary>
    public const int TableSize = MaxAddress + 1; // 112

    /// <summary>Address for a digital button event (<paramref name="index"/> 0x00–0x47).</summary>
    public static int FromButton(byte index)
    {
        if (index >= ButtonCount)
            throw new ArgumentOutOfRangeException(
                nameof(index), $"Button index must be 0..{ButtonCount - 1}.");
        return index;
    }

    /// <summary>
    /// Address for a keypad key event: <paramref name="pad"/> 0 or 1,
    /// <paramref name="index"/> 0x00–0x0F. Mirrors the legacy offsets (+0x50 / +0x60).
    /// </summary>
    public static int FromKeypad(byte pad, byte index)
    {
        if (index > 0x0F)
            throw new ArgumentOutOfRangeException(nameof(index), "Keypad index must be 0..0x0F.");

        return pad switch
        {
            0 => Keypad0Base + index,
            1 => Keypad1Base + index,
            _ => throw new ArgumentOutOfRangeException(nameof(pad), "Keypad must be 0 or 1."),
        };
    }
}
