// tooltip — pure implementation. See tooltip.h.

#include "core/ui/tooltip.h"

namespace reasampler::ui {

std::string stripActionPrefix(const std::string& fullName, const std::string& prefix) {
    if (prefix.empty()) return fullName;
    if (fullName.size() >= prefix.size() &&
        fullName.compare(0, prefix.size(), prefix) == 0)
        return fullName.substr(prefix.size());
    return fullName;
}

TooltipBox computeTooltip(int anchorX, int anchorY, int anchorW, int anchorH,
                          int textW, int textH, int clientW, int clientH,
                          const TooltipSpec& spec) {
    TooltipBox box;
    if (textW <= 0 || textH <= 0 || clientW <= 0 || clientH <= 0) return box;

    // Clamp boxW so it never exceeds the available client span; then clamp x so the (possibly
    // reduced) box always sits within [margin, clientW - margin].
    const int maxBoxW = clientW - 2 * spec.margin;
    const int boxW = (textW + 2 * spec.padX < maxBoxW) ? textW + 2 * spec.padX : maxBoxW;
    const int boxH = textH + 2 * spec.padY;

    // Horizontal: centre on the anchor, then clamp within [margin, clientW - margin - boxW].
    int x = anchorX + (anchorW - boxW) / 2;
    const int maxX = clientW - spec.margin - boxW;
    if (x > maxX) x = maxX;
    if (x < spec.margin) x = spec.margin;

    // Vertical: prefer BELOW the anchor; flip ABOVE if it would clip the bottom edge.
    int y = anchorY + anchorH + spec.gap;
    if (y + boxH > clientH - spec.margin) {
        const int above = anchorY - spec.gap - boxH;
        if (above >= spec.margin) {
            y = above;  // fits above — flip
        } else {
            // Fits neither cleanly (tall tooltip / short client): clamp to the bottom margin.
            const int maxY = clientH - spec.margin - boxH;
            y = maxY < spec.margin ? spec.margin : maxY;
        }
    }

    box.x = x;
    box.y = y;
    box.width = boxW;
    box.height = boxH;
    return box;
}

} // namespace reasampler::ui
