namespace RioJoy.Core.Overlay;

/// <summary>
/// Point → region hit-testing over a template, for the wallpaper maker's clickable
/// preview. Because the cockpit wallpaper feeds six chroma-split displays, regions
/// for <em>different</em> buttons legitimately sit at the same pixels, so a click
/// resolves to a <em>stack</em> of candidate cells rather than one; repeated clicks
/// cycle through the stack via <see cref="NextAt"/>.
/// </summary>
public static class OverlayHitTester
{
    /// <summary>
    /// The regions containing the template-space point, smallest area first (the
    /// most specific cell wins), ties in template order. Empty when nothing is hit.
    /// A region's rectangle is its stored cell geometry; label rotation does not
    /// affect hit-testing.
    /// </summary>
    public static IList<OverlayRegion> RegionsAt(OverlayTemplate template, double x, double y)
    {
        if (template is null) throw new ArgumentNullException(nameof(template));

        return template.Regions
            .Where(r => Contains(r, x, y))
            .OrderBy(r => r.Width * r.Height)
            .ToList();
    }

    /// <summary>
    /// The region a click at the point should select: the first hit when
    /// <paramref name="currentName"/> is not among the hits, otherwise the hit
    /// after it (wrapping) — so clicking a stacked cell repeatedly cycles through
    /// every region at that spot. Null when nothing is hit.
    /// </summary>
    public static OverlayRegion? NextAt(OverlayTemplate template, double x, double y, string? currentName)
    {
        IList<OverlayRegion> hits = RegionsAt(template, x, y);
        if (hits.Count == 0)
            return null;

        for (int i = 0; i < hits.Count; i++)
        {
            if (string.Equals(hits[i].Name, currentName, StringComparison.OrdinalIgnoreCase))
                return hits[(i + 1) % hits.Count];
        }

        return hits[0];
    }

    private static bool Contains(OverlayRegion r, double x, double y) =>
        x >= r.X && x < r.X + r.Width &&
        y >= r.Y && y < r.Y + r.Height;
}
