// mode_switch — pure implementation. See mode_switch.h. NO REAPER / SWELL / vendor.

#include "mode_switch.h"

#include <cstddef>

namespace reasampler {

namespace {

// The left edge of segment i in a header of the given x-origin and width divided
// into `count` segments. Boundary i is x + (i * width) / count, so segment i spans
// [edge(i), edge(i+1)). Because every boundary is derived from the same formula,
// consecutive segments share an exact edge (no gap, no overlap) and edge(count)
// == x + width precisely. count assumed >= 1 by callers.
int segmentEdge(int x, int width, int i, int count) {
    return x + (i * width) / count;
}

} // namespace

std::vector<SegmentRect> computeSegmentRects(const HeaderRect& header,
                                             int segmentCount) {
    std::vector<SegmentRect> rects;
    if (segmentCount <= 0 || header.width <= 0) return rects;

    rects.reserve(static_cast<std::size_t>(segmentCount));
    for (int i = 0; i < segmentCount; ++i) {
        const int left = segmentEdge(header.x, header.width, i, segmentCount);
        const int right = segmentEdge(header.x, header.width, i + 1, segmentCount);
        SegmentRect r;
        r.x = left;
        r.y = header.y;
        r.width = right - left;   // absorbs rounding; adjacent segments abut exactly
        r.height = header.height;
        rects.push_back(r);
    }
    return rects;
}

int hitTestSegment(int px, int py, const HeaderRect& header, int segmentCount) {
    if (segmentCount <= 0 || header.width <= 0 || header.height <= 0) return -1;

    // Reject anything outside the header band first (half-open bounds match the
    // segment rects). Below the header is where the grid lives — the panel falls
    // through to grid handling on a -1.
    if (px < header.x || px >= header.x + header.width ||
        py < header.y || py >= header.y + header.height)
        return -1;

    // Inside the band: find the segment whose [edge(i), edge(i+1)) contains px.
    // Linear over N (N is tiny — one per mode); mirrors the boundary formula so the
    // hit matches the drawn segment exactly.
    for (int i = 0; i < segmentCount; ++i) {
        const int left = segmentEdge(header.x, header.width, i, segmentCount);
        const int right = segmentEdge(header.x, header.width, i + 1, segmentCount);
        if (px >= left && px < right) return i;
    }
    // Guard: px == header.x + header.width would fail the < above but was already
    // excluded by the band check. Any residual falls to -1 (defensive, unreachable).
    return -1;
}

} // namespace reasampler
