


class UIElement {
    constructor(x, y, w, h, tooltipText = null) {
        this.x = x; this.y = y;
        this.w = w; this.h = h;
        this.hovered = false;
        this.active = false;

        
        this.tooltipDelay = 1000; // ms before showing
        this.hoverStart = null;   // timestamp when hover began
        this.tooltip = tooltipText ? new Tooltip(tooltipText) : null;

    }

    contains(px, py) {
        return px >= this.x && px <= this.x + this.w &&
            py >= this.y && py <= this.y + this.h;
    }

    handlePointerEvent(event, px, py) {
        switch (event.type) {
            case 'pointermove':
                this.onPointerMove(px, py);
                break;
            case 'pointerdown':
                this.onPointerDown(px, py);
                break;
            case 'pointerup':
                this.onPointerUp(px, py);
                break;
            case 'click':
                // optional: treat click as pointerup for convenience
                if (this.contains(px, py)) {
                    this.onClick?.(); // if subclass defines onClick
                }
                break;
        }

    }


    onPointerMove(px, py) {
        const inside = this.contains(px, py);

        // detect entering hover
        if (inside && !this.hovered) {
            this.hoverStart = performance.now();
        }

        // detect leaving hover
        if (!inside && this.hovered) {
            this.hoverStart = null;
        }

        this.hovered = inside;
    }


    onPointerDown(px, py) {
        if (this.contains(px, py)) {
            this.active = true;
            return true;
        }
        return false;
    }

    onPointerUp(px, py) {
        if (this.active && this.contains(px, py)) {
            this.active = false;
            return true;
        }
        this.active = false;
        return false;
    }

    draw(ctx) {
        if (this.tooltip && this.hovered && this.hoverStart) {
            const elapsed = performance.now() - this.hoverStart;
            if (elapsed >= this.tooltipDelay) {
                this.tooltip.show(this.x + 100, this.y + this.h*2);
                this.tooltip.draw(ctx);
            } else {
                this.tooltip.hide();
            }
        }
    }
}

export class Label extends UIElement {
    constructor(x, y, text, font = '14px monospace', color = '#fff', tooltipText = null) {
        // width/height are optional for labels, but we can set them to 0
        super(x, y, 0, 0, tooltipText);
        this.text = text;
        this.font = font;
        this.color = color;
    }

    draw(ctx) {
        ctx.fillStyle = this.color;
        ctx.font = this.font;
        ctx.fillText(this.text, this.x, this.y);
    }

    // labels don’t need pointer/key handling, so we leave defaults
}


export class Panel extends UIElement {
    constructor(x, y, w, h, title = '', tooltipText = null) {
        super(x, y, w, h, tooltipText);
        this.title = title;
        this.elements = [];
    }

    addElement(el) { this.elements.push(el); }

    draw(ctx) {
        ctx.fillStyle = 'rgba(0,0,0,0.5)';
        ctx.fillRect(this.x, this.y, this.w, this.h);
        ctx.strokeStyle = '#fff';
        ctx.strokeRect(this.x, this.y, this.w, this.h);

        if (this.title) {
            ctx.fillStyle = '#fff';
            ctx.font = '16px monospace';
            ctx.fillText(this.title, this.x + 10, this.y + 20);
        }

        this.elements.forEach(el => el.draw(ctx));
    }

    handlePointerEvent(event, px, py) {
        super.handlePointerEvent(event, px, py); // panel itself
        this.elements.forEach(el => el.handlePointerEvent(event, px, py));
    }


    handleKeyEvent(event) {
        this.elements.forEach(el => {
            if (el.onKeyDown) el.onKeyDown(event);
        });
    }
}



export class Button extends UIElement {
    constructor(x, y, w, h, label, onClick, tooltipText = null) {
        super(x, y, w, h, tooltipText);
        this.label = label;
        this.onClick = onClick;
    }

    draw(ctx) {
        // ctx.fillStyle = this.active ? '#225433' :
        //     this.hovered ? '#666' : '#333';
        // ctx.fillRect(this.x, this.y, this.w, this.h);

        ctx.fillStyle = '#fff';
        if (this.hovered) {
            ctx.fillStyle = '#00a808ff';

        }
        ctx.font = '14px monospace';
        ctx.fillText(this.label, this.x + 10, this.y + this.h - 8);
        super.draw(ctx);
    }


    onPointerUp(px, py) {
        const clicked = super.onPointerUp(px, py);
        if (clicked && this.onClick) this.onClick();
        return clicked;
    }
}

export class Textbox extends UIElement {
    constructor(x, y, w, h, initialValue = '', tooltipText = null) {
        super(x, y, w, h, tooltipText);
        this.value = initialValue;
        this.focused = false;
    }

    draw(ctx) {
        ctx.fillStyle = '#000';
        ctx.fillRect(this.x, this.y, this.w, this.h);

        ctx.strokeStyle = this.focused ? '#0f0' : '#aaa';
        ctx.strokeRect(this.x, this.y, this.w, this.h);

        ctx.fillStyle = '#fff';
        ctx.font = '14px monospace';
        ctx.fillText(this.value, this.x + 5, this.y + this.h - 8);
    }

    onPointerUp(px, py) {
        const clicked = super.onPointerUp(px, py);
        this.focused = clicked;
        return clicked;
    }

    onKeyDown(event) {
        if (!this.focused) return;
        if (event.key >= '0' && event.key <= '9') {
            this.value += event.key;
        } else if (event.key === 'Backspace') {
            this.value = this.value.slice(0, -1);
        }
    }
}

export class Checkbox extends UIElement {
    constructor(x, y, size = 16, label = '', initialChecked = false, onChange = null, tooltipText = null) {
        super(x, y, size, size, tooltipText);
        this.checked = initialChecked;
        this.label = label;
        this.onChange = onChange;
    }

    draw(ctx) {
        // box
        ctx.fillStyle = '#000';
        ctx.fillRect(this.x, this.y, this.w, this.h);

        ctx.strokeStyle = this.hovered ? '#0f0' : '#aaa';
        ctx.strokeRect(this.x, this.y, this.w, this.h);

        // check mark
        if (this.checked) {
            ctx.fillStyle = '#0f0';
            ctx.fillRect(this.x + 3, this.y + 3, this.w - 6, this.h - 6);
        }

        // label text
        if (this.label) {
            ctx.fillStyle = '#fff';
            ctx.font = '14px monospace';
            ctx.fillText(this.label, this.x + this.w + 8, this.y + this.h - 4);
        }
    }

    onPointerUp(px, py) {
        const clicked = super.onPointerUp(px, py);
        if (clicked) {
            this.checked = !this.checked;
            if (this.onChange) this.onChange(this.checked);
        }
        return clicked;
    }
}

export class RadioButton extends UIElement {
    constructor(x, y, size = 16, label = '', group = null, initialSelected = false, onChange = null, tooltipText) {
        super(x, y, size, size, tooltipText);
        this.selected = initialSelected;
        this.label = label;
        this.group = group;   // reference to RadioGroup
        this.onChange = onChange;
    }

    draw(ctx) {
        // outer circle
        ctx.strokeStyle = this.hovered ? '#0f0' : '#aaa';
        ctx.beginPath();
        ctx.arc(this.x + this.w / 2, this.y + this.h / 2, this.w / 2, 0, Math.PI * 2);
        ctx.stroke();

        // inner dot if selected
        if (this.selected) {
            ctx.fillStyle = '#0f0';
            ctx.beginPath();
            ctx.arc(this.x + this.w / 2, this.y + this.h / 2, this.w / 2 - 4, 0, Math.PI * 2);
            ctx.fill();
        }

        // label text
        if (this.label) {
            ctx.fillStyle = '#fff';
            ctx.font = '14px monospace';
            ctx.fillText(this.label, this.x + this.w + 8, this.y + this.h - 4);
        }
        super.draw(ctx);
    }

    onPointerUp(px, py) {
        const clicked = super.onPointerUp(px, py);
        if (clicked) {
            if (this.group) {
                this.group.select(this); // delegate exclusivity
            } else {
                this.selected = !this.selected;
            }
            if (this.onChange) this.onChange(this.selected);
        }
        return clicked;
    }
}

export class RadioGroup {
    constructor() {
        this.buttons = [];
    }

    addButton(btn) {
        btn.group = this;
        this.buttons.push(btn);
    }

    select(selectedBtn) {
        this.buttons.forEach(btn => btn.selected = (btn === selectedBtn));
    }

    getSelected() {
        return this.buttons.find(btn => btn.selected);
    }
}

export class Tooltip {
    constructor(text) {
        this.text = text;
        this.visible = false;
        this.x = 0;
        this.y = 0;
    }

    show(x, y) {
        this.visible = true;
        this.x = x;
        this.y = y;
    }

    hide() {
        this.visible = false;
    }

    draw(ctx) {
        if (!this.visible) return;

        ctx.font = '12px monospace';
        const padding = 6;
        const metrics = ctx.measureText(this.text);
        const w = metrics.width + padding * 2;
        const h = 20;

        ctx.fillStyle = 'rgba(0,0,0,0.8)';
        ctx.fillRect(this.x, this.y - h, w, h);

        ctx.strokeStyle = '#fff';
        ctx.strokeRect(this.x, this.y - h, w, h);

        ctx.fillStyle = '#fff';
        ctx.fillText(this.text, this.x + padding, this.y - 6);
    }
}




