// ============================================================
// IconSelect: visual icon-grid selector (replaces <select>)
// Ported from wled-screen-controller (TypeScript → vanilla JS)
//
// Trigger replaces the <select> inline. Popup is absolutely
// positioned inside a wrapper that sits next to the trigger.
// Works inside <dialog showModal()> — dialog must have
// overflow: visible.
// ============================================================

const POPUP_CLASS = 'icon-select-popup';

let _globalListenerAdded = false;

export function closeAllIconSelects() {
    document.querySelectorAll(`.${POPUP_CLASS}.open`).forEach(p => {
        p.classList.remove('open');
    });
}

function _ensureGlobalListener() {
    if (_globalListenerAdded) return;
    _globalListenerAdded = true;
    document.addEventListener('click', (e) => {
        if (!e.target.closest(`.${POPUP_CLASS}`) && !e.target.closest('.icon-select-trigger')) {
            closeAllIconSelects();
        }
    });
    document.addEventListener('keydown', (e) => {
        if (e.key === 'Escape') closeAllIconSelects();
    });
}

export class IconSelect {
    constructor({ target, items, onChange, columns = 2, placeholder = '', horizontal = false }) {
        _ensureGlobalListener();

        this._select = target;
        this._items = items;
        this._onChange = onChange;
        this._columns = columns;
        this._placeholder = placeholder;
        this._horizontal = horizontal;

        // Hide native select
        this._select.style.display = 'none';

        // Trigger button (replaces select visually)
        this._trigger = document.createElement('button');
        this._trigger.type = 'button';
        this._trigger.className = 'icon-select-trigger';
        this._trigger.addEventListener('click', (e) => {
            e.stopPropagation();
            this._toggle();
        });
        this._select.parentNode.insertBefore(this._trigger, this._select.nextSibling);

        // Popup — absolutely positioned, appended to dialog (overflow:visible)
        // or body, escaping any scrollable ancestors
        this._popup = document.createElement('div');
        this._popup.className = POPUP_CLASS;
        this._popup.addEventListener('click', (e) => e.stopPropagation());
        this._popup.innerHTML = this._buildGrid();

        const portal = this._select.closest('dialog') || document.body;
        portal.appendChild(this._popup);

        this._bindCells();
        this._syncTrigger();
    }

    _buildGrid() {
        const cells = this._items.map(item =>
            `<div class="icon-select-cell" data-value="${item.value}">
                <span class="icon-select-cell-icon">${item.icon}</span>
                <span class="icon-select-cell-label">${item.label}</span>
                ${item.desc ? `<span class="icon-select-cell-desc">${item.desc}</span>` : ''}
            </div>`
        ).join('');

        const cls = 'icon-select-grid' + (this._horizontal ? ' icon-select-grid--horizontal' : '');
        return `<div class="${cls}" style="grid-template-columns:repeat(${this._columns},1fr)">${cells}</div>`;
    }

    _bindCells() {
        this._popup.querySelectorAll('.icon-select-cell').forEach(cell => {
            cell.addEventListener('click', () => {
                this.setValue(cell.dataset.value, true);
                this._popup.classList.remove('open');
            });
        });
    }

    _syncTrigger() {
        const val = this._select.value;
        const item = this._items.find(i => i.value === val);
        if (item) {
            this._trigger.innerHTML =
                `<span class="icon-select-trigger-icon">${item.icon}</span>` +
                `<span class="icon-select-trigger-label">${item.label}</span>` +
                `<span class="icon-select-trigger-arrow">&#x25BE;</span>`;
        } else if (this._placeholder) {
            this._trigger.innerHTML =
                `<span class="icon-select-trigger-label">${this._placeholder}</span>` +
                `<span class="icon-select-trigger-arrow">&#x25BE;</span>`;
        }
        this._popup.querySelectorAll('.icon-select-cell').forEach(cell => {
            cell.classList.toggle('active', cell.dataset.value === val);
        });
    }

    _positionPopup() {
        // Get trigger position relative to the popup's offset parent
        // (the dialog or body). Use getBoundingClientRect for both and
        // compute the offset.
        const triggerRect = this._trigger.getBoundingClientRect();
        const parentRect = this._popup.offsetParent
            ? this._popup.offsetParent.getBoundingClientRect()
            : { left: 0, top: 0 };

        const relTop = triggerRect.bottom - parentRect.top;
        const relLeft = triggerRect.left - parentRect.left;
        const popupW = Math.max(triggerRect.width, 200);

        this._popup.style.left = relLeft + 'px';
        this._popup.style.top = (relTop + 4) + 'px';
        this._popup.style.width = popupW + 'px';
    }

    _toggle() {
        const wasOpen = this._popup.classList.contains('open');
        closeAllIconSelects();
        if (!wasOpen) {
            this._positionPopup();
            this._popup.classList.add('open');
        }
    }

    setValue(value, fireChange = false) {
        this._select.value = value;
        this._syncTrigger();
        if (fireChange) {
            this._select.dispatchEvent(new Event('change', { bubbles: true }));
            if (this._onChange) this._onChange(value);
        }
    }

    updateItems(items) {
        this._items = items;
        this._popup.innerHTML = this._buildGrid();
        this._bindCells();
        this._syncTrigger();
    }

    destroy() {
        this._trigger.remove();
        this._popup.remove();
        this._select.style.display = '';
    }
}
