#pragma once
#include "core/ui/rect.h"
// tab_strip — layout + hit-test for the bank_panel's named-banks tab strip: a LICE-drawn strip
// (not a SWELL tab control) that scrolls via chevrons when tabs overflow the strip width.

#include <vector>

namespace reasampler::ui {

// The strip the tabs draw into, top-left origin.
using TabStripRect = Rect;

// tabWidth is fixed per tab so the strip reads as a uniform segmented control and overflow math
// stays simple (labels ellipsize, they don't resize the tab). chevronWidth is reserved at each
// end only when tabs overflow.
struct TabStripSpec {
    int tabWidth = 96;
    int chevronWidth = 20;
};

// One tab's rect, already translated by scroll offset and clipped to the visible track. A tab
// scrolled fully out of view is omitted from computeTabRects's result.
struct TabRect {
    int index = 0;
    int x = 0;
    int y = 0;
    int width = 0;
    int height = 0;

    bool operator==(const TabRect& o) const {
        return index == o.index && x == o.x && y == o.y &&
               width == o.width && height == o.height;
    }
};

// Scrollable track geometry, shared by layout + hit-test so both agree.
struct TabStripLayout {
    bool overflow = false;
    int  trackX = 0;
    int  trackWidth = 0;
    int  maxScroll = 0;
    bool leftChevron = false;
    bool rightChevron = false;
};

// Layout for `tabCount` tabs of `spec.tabWidth` in `strip`. No overflow: track == strip, no
// chevrons, maxScroll 0. Overflow: both chevrons always reserved together (simpler than hiding
// one at a scroll limit — a chevron click there is a harmless no-op the shell clamps); track is
// the strip minus both chevrons; maxScroll is how far the tab run exceeds the track.
// tabCount <= 0 or non-positive strip width returns a zeroed layout.
TabStripLayout computeTabStripLayout(const TabStripRect& strip, int tabCount,
                                     const TabStripSpec& spec, int scrollOffset);

// Clamps a desired scroll offset into [0, maxScroll]; always 0 when tabs fit.
int clampTabScroll(int desiredOffset, const TabStripLayout& layout);

// Tiles tabCount fixed-width tabs into the track, shifted by scrollOffset, returning only
// partially-or-fully visible rects (clipped to the track so a scrolled tab never draws under a
// chevron). Caller must pass the same scrollOffset used for computeTabStripLayout.
std::vector<TabRect> computeTabRects(const TabStripRect& strip, int tabCount,
                                     const TabStripSpec& spec, int scrollOffset);

enum class TabHitKind {
    None,
    Tab,
    ScrollLeft,
    ScrollRight,
};

// index is the tab's index for Tab, -1 for chevrons/None.
struct TabHit {
    TabHitKind kind = TabHitKind::None;
    int index = -1;

    bool operator==(const TabHit& o) const {
        return kind == o.kind && index == o.index;
    }
};

// Hit-tests a point against the strip laid out for `tabCount` tabs at `scrollOffset`. Chevrons
// take precedence at the strip ends. Half-open bounds match computeTabRects.
TabHit hitTestTabStrip(int px, int py, const TabStripRect& strip, int tabCount,
                       const TabStripSpec& spec, int scrollOffset);

} // namespace reasampler::ui
