package dev.photosync.ui;

/**
 * An axis-aligned rectangle in GUI space.
 *
 * <p>Layout in this module is arithmetic on these rather than a constraint
 * solver: the screens are simple enough that a solver would be more machinery
 * than the problem deserves, and every position stays inspectable in a debugger.
 */
public record Rect(int x, int y, int width, int height) {

    public static final Rect EMPTY = new Rect(0, 0, 0, 0);

    public int right() {
        return x + width;
    }

    public int bottom() {
        return y + height;
    }

    public int centerX() {
        return x + width / 2;
    }

    public int centerY() {
        return y + height / 2;
    }

    public boolean isEmpty() {
        return width <= 0 || height <= 0;
    }

    /** Mouse coordinates arrive as doubles, so this takes them as they come. */
    public boolean contains(double pointX, double pointY) {
        return pointX >= x && pointX < right() && pointY >= y && pointY < bottom();
    }

    /** Shrinks on all four sides. A negative amount grows instead. */
    public Rect inset(int amount) {
        return inset(amount, amount, amount, amount);
    }

    public Rect inset(int left, int top, int right, int bottom) {
        return new Rect(x + left, y + top, width - left - right, height - top - bottom);
    }

    public Rect translate(int deltaX, int deltaY) {
        return new Rect(x + deltaX, y + deltaY, width, height);
    }

    public Rect withHeight(int newHeight) {
        return new Rect(x, y, width, newHeight);
    }

    public Rect withWidth(int newWidth) {
        return new Rect(x, y, newWidth, height);
    }

    /** The top strip of this rectangle. */
    public Rect top(int amount) {
        return new Rect(x, y, width, Math.min(amount, height));
    }

    /** The bottom strip of this rectangle. */
    public Rect bottom(int amount) {
        int taken = Math.min(amount, height);
        return new Rect(x, bottom() - taken, width, taken);
    }

    /** The left column of this rectangle. */
    public Rect left(int amount) {
        return new Rect(x, y, Math.min(amount, width), height);
    }

    /** The right column of this rectangle. */
    public Rect right(int amount) {
        int taken = Math.min(amount, width);
        return new Rect(right() - taken, y, taken, height);
    }

    /** What is left after taking {@code amount} off the top. */
    public Rect dropTop(int amount) {
        return new Rect(x, y + amount, width, Math.max(0, height - amount));
    }

    /** What is left after taking {@code amount} off the bottom. */
    public Rect dropBottom(int amount) {
        return new Rect(x, y, width, Math.max(0, height - amount));
    }

    /** What is left after taking {@code amount} off the left. */
    public Rect dropLeft(int amount) {
        return new Rect(x + amount, y, Math.max(0, width - amount), height);
    }

    /** What is left after taking {@code amount} off the right. */
    public Rect dropRight(int amount) {
        return new Rect(x, y, Math.max(0, width - amount), height);
    }
}
