#pragma once
#include "core/ui/rect.h"
// action_bar — layout + hit-test for the bank_panel's task-grouped toolbars: buttons cluster by
// task (Capture/Placement/Maintenance/Tagging/Switching); on a narrow panel, whole trailing
// buttons drop rather than shrink or clip. The destructive Prune button lives separately in
// prune_button, kept out of this cluster on purpose.

#include <vector>

namespace reasampler::ui {

// Task cluster a button belongs to. Cluster order is caller-supplied via ClusterSpec, not fixed
// here; a slot just carries which cluster it landed in.
enum class ActionCluster {
    Capture,
    Placement,
    Maintenance,
    Tagging,
    Switching,
};

using ActionBarRect = Rect;

// One visible button's placement, top-left origin. `index` is its position in the caller's flat
// action list (cluster order), so index also selects the action to fire on a hit. Only buttons
// that fit get a slot — overflow is dropped whole, never clipped.
struct ActionBarSlot {
    int index = 0;
    ActionCluster cluster = ActionCluster::Capture;
    int x = 0;
    int y = 0;
    int width = 0;
    int height = 0;
    // Label sub-rect, full button height, horizontally inset so text clears the edge.
    int labelX = 0, labelY = 0, labelW = 0, labelH = 0;

    bool operator==(const ActionBarSlot& o) const {
        return index == o.index && cluster == o.cluster &&
               x == o.x && y == o.y && width == o.width && height == o.height &&
               labelX == o.labelX && labelY == o.labelY &&
               labelW == o.labelW && labelH == o.labelH;
    }
};

// One cluster's button count, in the order the caller wants it drawn. count == 0 skips the
// cluster (no gap emitted). Flat action indices run cluster-by-cluster in this order.
struct ClusterSpec {
    ActionCluster cluster = ActionCluster::Capture;
    int count = 0;
};

// Layout inputs, in pixels; defaults are the bank_panel action-bar metrics.
struct ActionBarSpec {
    int buttonWidth = 108;
    int buttonGap = 4;
    int clusterGap = 16;
    int sidePad = 8;
    int verticalInset = 3;
};

// How many buttons (from the front) fit at spec.buttonWidth. Split out so the shell can size an
// overflow affordance without re-deriving it. A bar too narrow for even one button yields 0.
struct BarFit {
    int visibleCount = 0;
    int hiddenCount = 0;
};

BarFit computeBarFit(const ActionBarRect& bar, const std::vector<ClusterSpec>& clusters,
                     const ActionBarSpec& spec);

// Lays out the visible buttons (per computeBarFit) left-to-right in cluster order.
std::vector<ActionBarSlot> computeBarSlots(const ActionBarRect& bar,
                                           const std::vector<ClusterSpec>& clusters,
                                           const ActionBarSpec& spec);

// Flat action index under (px, py), or -1 for a miss (outside the bar, in a gap, or past the
// last visible button). Gaps are real dead-zones here, not resolved to the nearest button.
int hitTestActionBar(int px, int py, const ActionBarRect& bar,
                     const std::vector<ClusterSpec>& clusters, const ActionBarSpec& spec);

} // namespace reasampler::ui
