'use strict';

var EventBus = require('../core/EventBus.js');

/* ────────────────────────────────────────────────────────────────
   GameUI — In-game UI system (HUD, menus, dialogs, focus nav)
──────────────────────────────────────────────────────────────── */
/* ── Default theme ────────────────────────────────────────────── */
const DEFAULT_THEME = {
    name: 'default',
    fontFamily: 'monospace',
    fontSize: 16,
    textColor: { r: 1, g: 1, b: 1, a: 1 },
    panelColor: { r: 0.1, g: 0.1, b: 0.15, a: 0.85 },
    panelBorder: { r: 0.3, g: 0.3, b: 0.4, a: 1 },
    accentColor: { r: 0.2, g: 0.6, b: 1, a: 1 },
    focusColor: { r: 1, g: 0.85, b: 0, a: 1 },
    disabledColor: { r: 0.4, g: 0.4, b: 0.4, a: 0.6 },
    buttonColor: { r: 0.2, g: 0.25, b: 0.35, a: 1 },
    buttonHoverColor: { r: 0.25, g: 0.35, b: 0.55, a: 1 },
    barFillColor: { r: 0.2, g: 0.8, b: 0.3, a: 1 },
    barBgColor: { r: 0.15, g: 0.15, b: 0.2, a: 1 },
};
/* ── GameUI Manager ───────────────────────────────────────────── */
class GameUI {
    constructor() {
        this.events = new EventBus.EventBus();
        this.elements = new Map();
        this.layers = []; // ordered render layers
        this._theme = { ...DEFAULT_THEME };
        this._focusedId = null;
        this._focusOrder = [];
        this._screenSize = { x: 1280, y: 720 };
    }
    get theme() {
        return this._theme;
    }
    set theme(t) {
        Object.assign(this._theme, t);
    }
    get focusedElement() {
        return this._focusedId;
    }
    setScreenSize(w, h) {
        this._screenSize = { x: w, y: h };
    }
    /* ── Element CRUD ───────────────────────────────────────────── */
    addElement(el, layerIndex = 0) {
        this.elements.set(el.id, el);
        while (this.layers.length <= layerIndex)
            this.layers.push([]);
        this.layers[layerIndex].push(el.id);
        if (el.focusable)
            this._focusOrder.push(el.id);
        this.events.emit('ui:element:added', el.id);
    }
    removeElement(id) {
        this.elements.delete(id);
        for (const layer of this.layers) {
            const idx = layer.indexOf(id);
            if (idx >= 0)
                layer.splice(idx, 1);
        }
        this._focusOrder = this._focusOrder.filter(fid => fid !== id);
        if (this._focusedId === id)
            this._focusedId = null;
        this.events.emit('ui:element:removed', id);
    }
    getElement(id) {
        return this.elements.get(id);
    }
    clear() {
        this.elements.clear();
        this.layers.length = 0;
        this._focusedId = null;
        this._focusOrder.length = 0;
    }
    /* ── Focus navigation (gamepad/keyboard) ────────────────────── */
    focusNext() {
        if (this._focusOrder.length === 0)
            return;
        const idx = this._focusedId ? this._focusOrder.indexOf(this._focusedId) : -1;
        const next = (idx + 1) % this._focusOrder.length;
        this.setFocus(this._focusOrder[next]);
    }
    focusPrev() {
        if (this._focusOrder.length === 0)
            return;
        const idx = this._focusedId ? this._focusOrder.indexOf(this._focusedId) : 0;
        const prev = (idx - 1 + this._focusOrder.length) % this._focusOrder.length;
        this.setFocus(this._focusOrder[prev]);
    }
    setFocus(id) {
        const old = this._focusedId;
        this._focusedId = id;
        if (old !== id) {
            if (old)
                this.events.emit('ui:blur', old);
            if (id)
                this.events.emit('ui:focus', id);
        }
    }
    /** Activate (select/click) the currently focused element. */
    activateFocused() {
        if (!this._focusedId)
            return;
        const el = this.elements.get(this._focusedId);
        if ((el === null || el === void 0 ? void 0 : el.action) && el.enabled) {
            this.events.emit('ui:action', { elementId: el.id, action: el.action });
        }
    }
    /* ── HUD helpers ────────────────────────────────────────────── */
    createText(id, text, anchor = 'top-left', pos, style) {
        const el = {
            id,
            type: 'text',
            text,
            position: pos !== null && pos !== void 0 ? pos : { x: 10, y: 10 },
            anchor,
            size: { width: 0, height: 0 },
            style: { fontSize: this._theme.fontSize, fontFamily: this._theme.fontFamily, color: this._theme.textColor, ...style },
            enabled: true,
            visible: true,
        };
        this.addElement(el);
        return el;
    }
    createBar(id, value, anchor = 'top-left', pos, size) {
        const el = {
            id,
            type: 'bar',
            value: Math.max(0, Math.min(1, value)),
            position: pos !== null && pos !== void 0 ? pos : { x: 10, y: 10 },
            anchor,
            size: size !== null && size !== void 0 ? size : { width: 200, height: 20 },
            style: { backgroundColor: this._theme.barBgColor, color: this._theme.barFillColor, borderRadius: 3 },
            enabled: true,
            visible: true,
        };
        this.addElement(el);
        return el;
    }
    createButton(id, text, action, anchor = 'center', pos) {
        const el = {
            id,
            type: 'button',
            text,
            action,
            position: pos !== null && pos !== void 0 ? pos : { x: 0, y: 0 },
            anchor,
            size: { width: 200, height: 40 },
            style: { backgroundColor: this._theme.buttonColor, color: this._theme.textColor, borderRadius: 6, padding: 8 },
            focusable: true,
            enabled: true,
            visible: true,
        };
        this.addElement(el);
        return el;
    }
    createPanel(id, anchor = 'center', pos, size) {
        const el = {
            id,
            type: 'panel',
            position: pos !== null && pos !== void 0 ? pos : { x: 0, y: 0 },
            anchor,
            size: size !== null && size !== void 0 ? size : { width: 400, height: 300 },
            style: { backgroundColor: this._theme.panelColor, borderColor: this._theme.panelBorder, borderWidth: 2, borderRadius: 8, padding: 16 },
            children: [],
            enabled: true,
            visible: true,
        };
        this.addElement(el, 1);
        return el;
    }
    /* ── Rendering ──────────────────────────────────────────────── */
    render(ctx) {
        var _a;
        for (const layer of this.layers) {
            for (const id of layer) {
                const el = this.elements.get(id);
                if (!el || !el.visible)
                    continue;
                const style = el.style;
                const pos = this.resolveAnchorPosition(el);
                ctx.save();
                ctx.globalAlpha = (_a = style.opacity) !== null && _a !== void 0 ? _a : 1;
                switch (el.type) {
                    case 'text':
                        this.renderText(ctx, el, pos);
                        break;
                    case 'bar':
                        this.renderBar(ctx, el, pos);
                        break;
                    case 'button':
                        this.renderButton(ctx, el, pos);
                        break;
                    case 'panel':
                        this.renderPanel(ctx, el, pos);
                        break;
                }
                ctx.restore();
            }
        }
    }
    renderText(ctx, el, pos) {
        var _a, _b, _c, _d;
        const s = el.style;
        ctx.font = `${(_a = s.fontSize) !== null && _a !== void 0 ? _a : 16}px ${(_b = s.fontFamily) !== null && _b !== void 0 ? _b : 'monospace'}`;
        ctx.fillStyle = colorToCSS((_c = s.color) !== null && _c !== void 0 ? _c : this._theme.textColor);
        ctx.textBaseline = 'top';
        ctx.fillText((_d = el.text) !== null && _d !== void 0 ? _d : '', pos.x, pos.y);
    }
    renderBar(ctx, el, pos) {
        var _a, _b, _c, _d;
        const { width, height } = el.size;
        const r = (_a = el.style.borderRadius) !== null && _a !== void 0 ? _a : 0;
        // BG
        ctx.fillStyle = colorToCSS((_b = el.style.backgroundColor) !== null && _b !== void 0 ? _b : this._theme.barBgColor);
        roundRect(ctx, pos.x, pos.y, width, height, r);
        ctx.fill();
        // Fill
        const fill = Math.max(0, Math.min(1, (_c = el.value) !== null && _c !== void 0 ? _c : 0));
        if (fill > 0) {
            ctx.fillStyle = colorToCSS((_d = el.style.color) !== null && _d !== void 0 ? _d : this._theme.barFillColor);
            roundRect(ctx, pos.x, pos.y, width * fill, height, r);
            ctx.fill();
        }
    }
    renderButton(ctx, el, pos) {
        var _a, _b, _c, _d, _e, _f;
        const { width, height } = el.size;
        const r = (_a = el.style.borderRadius) !== null && _a !== void 0 ? _a : 0;
        const isFocused = el.id === this._focusedId;
        // Background
        const bg = isFocused ? this._theme.buttonHoverColor : ((_b = el.style.backgroundColor) !== null && _b !== void 0 ? _b : this._theme.buttonColor);
        ctx.fillStyle = colorToCSS(el.enabled ? bg : this._theme.disabledColor);
        roundRect(ctx, pos.x, pos.y, width, height, r);
        ctx.fill();
        // Focus ring
        if (isFocused) {
            ctx.strokeStyle = colorToCSS(this._theme.focusColor);
            ctx.lineWidth = 2;
            roundRect(ctx, pos.x - 2, pos.y - 2, width + 4, height + 4, r + 2);
            ctx.stroke();
        }
        // Label
        ctx.font = `${(_c = el.style.fontSize) !== null && _c !== void 0 ? _c : this._theme.fontSize}px ${(_d = el.style.fontFamily) !== null && _d !== void 0 ? _d : this._theme.fontFamily}`;
        ctx.fillStyle = colorToCSS((_e = el.style.color) !== null && _e !== void 0 ? _e : this._theme.textColor);
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.fillText((_f = el.text) !== null && _f !== void 0 ? _f : '', pos.x + width / 2, pos.y + height / 2);
        ctx.textAlign = 'left';
    }
    renderPanel(ctx, el, pos) {
        var _a, _b;
        const { width, height } = el.size;
        const s = el.style;
        const r = (_a = s.borderRadius) !== null && _a !== void 0 ? _a : 0;
        ctx.fillStyle = colorToCSS((_b = s.backgroundColor) !== null && _b !== void 0 ? _b : this._theme.panelColor);
        roundRect(ctx, pos.x, pos.y, width, height, r);
        ctx.fill();
        if (s.borderWidth && s.borderColor) {
            ctx.strokeStyle = colorToCSS(s.borderColor);
            ctx.lineWidth = s.borderWidth;
            roundRect(ctx, pos.x, pos.y, width, height, r);
            ctx.stroke();
        }
    }
    /* ── Anchor resolution ──────────────────────────────────────── */
    resolveAnchorPosition(el) {
        const sw = this._screenSize.x;
        const sh = this._screenSize.y;
        const ew = el.size.width;
        const eh = el.size.height;
        let ax = 0;
        let ay = 0;
        const a = el.anchor;
        if (a.includes('center') && !a.includes('left') && !a.includes('right')) {
            ax = (sw - ew) / 2;
        }
        else if (a.includes('right')) {
            ax = sw - ew;
        }
        if (a === 'center' || a === 'center-left' || a === 'center-right') {
            ay = (sh - eh) / 2;
        }
        else if (a.includes('bottom')) {
            ay = sh - eh;
        }
        return { x: ax + el.position.x, y: ay + el.position.y };
    }
}
/* ── Canvas helpers ───────────────────────────────────────────── */
function colorToCSS(c) {
    return `rgba(${(c.r * 255) | 0},${(c.g * 255) | 0},${(c.b * 255) | 0},${c.a})`;
}
function roundRect(ctx, x, y, w, h, r) {
    ctx.beginPath();
    ctx.moveTo(x + r, y);
    ctx.lineTo(x + w - r, y);
    ctx.quadraticCurveTo(x + w, y, x + w, y + r);
    ctx.lineTo(x + w, y + h - r);
    ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
    ctx.lineTo(x + r, y + h);
    ctx.quadraticCurveTo(x, y + h, x, y + h - r);
    ctx.lineTo(x, y + r);
    ctx.quadraticCurveTo(x, y, x + r, y);
    ctx.closePath();
}

exports.GameUI = GameUI;
//# sourceMappingURL=GameUI.js.map
