package dev.photosync.ui.widget;

import dev.photosync.mcapi.render.RenderBridge;
import dev.photosync.ui.Chrome;
import dev.photosync.ui.Rect;
import dev.photosync.ui.Theme;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;

/**
 * A rectangle that draws itself and may react to input.
 *
 * <p>The input methods mirror {@code ScreenModel}'s and answer the same
 * question -- "did you consume this?" -- so a screen can hand an event to its
 * widgets and pass the answer straight back to the game.
 */
@Getter
@Accessors(fluent = true)
public abstract class Widget {

    protected final Chrome chrome;

    @Setter
    private Rect bounds = Rect.EMPTY;

    @Setter
    private boolean enabled = true;

    @Setter
    private boolean visible = true;

    private boolean focused;

    protected Widget(Chrome chrome) {
        this.chrome = chrome;
    }

    protected Theme theme() {
        return chrome.theme();
    }

    /** Visible and enabled: the only state in which a widget takes input. */
    public boolean active() {
        return visible && enabled;
    }

    public abstract void render(RenderBridge render, int mouseX, int mouseY);

    /** Whether keyboard focus can land here. Only text entry says yes. */
    public boolean focusable() {
        return false;
    }

    /** Called by {@link WidgetList} when focus arrives or leaves. */
    public void focus(boolean value) {
        this.focused = value;
    }

    public boolean mouseClicked(double mouseX, double mouseY, int button) {
        return false;
    }

    public boolean mouseReleased(double mouseX, double mouseY, int button) {
        return false;
    }

    public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
        return false;
    }

    public boolean mouseScrolled(double mouseX, double mouseY, double amount) {
        return false;
    }

    public boolean keyPressed(int key, int scanCode, int modifiers) {
        return false;
    }

    public boolean charTyped(char character, int modifiers) {
        return false;
    }

    public void tick() {
    }

    protected boolean hovering(double mouseX, double mouseY) {
        return active() && bounds.contains(mouseX, mouseY);
    }
}
