using System;

namespace HellionChat._Helpers;

// Extracted history-navigation cursor math from CompactCallback to allow unit
// testing without ImGuiInputTextCallbackData (DeleteChars/InsertChars).
// Buffer mutation stays at the call site; only the cursor/replacement decision lives here.
//
// Index semantics match InputHistoryService:
//   index 0        = oldest entry
//   index Count-1  = newest entry
//   cursor == -1   = not browsing history
//
// replacement == null: caller must NOT touch the buffer (cursor unchanged).
// replacement != null: write it to the buffer (including "" to clear it).
//
// TEST-MIRROR: ../../../Hellion Build test/Ui/CompactInputHistoryNavigatorTests.cs
public static class CompactInputHistoryNavigator
{
    public enum Direction
    {
        Up,
        Down,
    }

    public static (int cursor, string? replacement) Navigate(
        Direction direction,
        int currentCursor,
        string currentBuffer,
        Func<int> getCount,
        Action<string> push,
        Func<int, string?> getByCursor
    )
    {
        ArgumentNullException.ThrowIfNull(getCount);
        ArgumentNullException.ThrowIfNull(push);
        ArgumentNullException.ThrowIfNull(getByCursor);

        var next = currentCursor;

        switch (direction)
        {
            case Direction.Up:
                if (currentCursor == -1)
                {
                    // Stash current input so the user can recover it after browsing.
                    var offset = 0;
                    if (!string.IsNullOrWhiteSpace(currentBuffer))
                    {
                        push(currentBuffer);
                        offset = 1;
                    }
                    next = getCount() - 1 - offset;
                }
                else if (currentCursor > 0)
                    next--;
                break;

            case Direction.Down:
                if (currentCursor != -1)
                {
                    next++;
                    if (next >= getCount())
                        next = -1;
                }
                break;
        }

        if (next == currentCursor)
            return (next, null);

        return (next, getByCursor(next) ?? string.Empty);
    }
}
