import { createAbortHandle } from '../common/abort-handler.js';
import { addWeakEventListener, getElementByIdFromRoot, isString, } from '../common/util.js';
import service from './service.js';
class TooltipController {
    static { this._listeners = [
        'pointerenter',
        'pointerleave',
    ]; }
    get open() {
        return this._open;
    }
    set open(value) {
        this._open = value;
        if (this._open) {
            this._addTooltipListeners();
            service.add(this._host, this._options.onEscape);
        }
        else {
            if (this._isTransient) {
                this._isTransient = false;
                this.setAnchor(this._initialAnchor?.deref());
            }
            this._hostAbortHandle.abort();
            service.remove(this._host);
        }
    }
    get anchor() {
        return this._isTransient
            ? this._anchor?.deref()
            : this._initialAnchor?.deref();
    }
    get hideTriggers() {
        return Array.from(this._hideTriggers).join();
    }
    set hideTriggers(value) {
        this._hideTriggers = parseTriggers(value);
        this._anchorAbortHandle.abort();
        this._addAnchorListeners();
    }
    get showTriggers() {
        return Array.from(this._showTriggers).join();
    }
    set showTriggers(value) {
        this._showTriggers = parseTriggers(value);
        this._anchorAbortHandle.abort();
        this._addAnchorListeners();
    }
    constructor(tooltip, options) {
        this._hostAbortHandle = createAbortHandle();
        this._anchorAbortHandle = createAbortHandle();
        this._showTriggers = new Set(['pointerenter']);
        this._hideTriggers = new Set(['pointerleave', 'click']);
        this._anchor = null;
        this._initialAnchor = null;
        this._isTransient = false;
        this._open = false;
        this._host = tooltip;
        this._options = options;
        this._host.addController(this);
    }
    _addAnchorListeners() {
        const anchor = this.anchor;
        if (!anchor) {
            return;
        }
        const { signal } = this._anchorAbortHandle;
        for (const each of this._showTriggers) {
            addWeakEventListener(anchor, each, this, { passive: true, signal });
        }
        for (const each of this._hideTriggers) {
            addWeakEventListener(anchor, each, this, { passive: true, signal });
        }
    }
    _addTooltipListeners() {
        const { signal } = this._hostAbortHandle;
        for (const event of TooltipController._listeners) {
            this._host.addEventListener(event, this, { passive: true, signal });
        }
    }
    async _handleTooltipEvent(event) {
        switch (event.type) {
            case 'pointerenter':
                await this._options.onShow.call(this._host);
                break;
            case 'pointerleave':
                await this._options.onHide.call(this._host);
                break;
            default:
                return;
        }
    }
    async _handleAnchorEvent(event) {
        if (!this._open && this._showTriggers.has(event.type)) {
            await this._options.onShow.call(this._host);
        }
        if (this._open && this._hideTriggers.has(event.type)) {
            await this._options.onHide.call(this._host);
        }
    }
    handleEvent(event) {
        if (event.target === this._host) {
            this._handleTooltipEvent(event);
        }
        else if (event.target === this._anchor?.deref()) {
            this._handleAnchorEvent(event);
        }
        else if (event.target === this._initialAnchor?.deref()) {
            this.open = false;
            this._handleAnchorEvent(event);
        }
    }
    _dispose() {
        this._anchorAbortHandle.abort();
        this._hostAbortHandle.abort();
        service.remove(this._host);
        this._anchor = null;
        this._initialAnchor = null;
    }
    setAnchor(value, transient = false) {
        const newAnchor = isString(value)
            ? getElementByIdFromRoot(this._host, value)
            : value;
        if (this._anchor?.deref() === newAnchor) {
            return;
        }
        if (transient && this._open) {
            this.open = false;
        }
        if (this._anchor?.deref() !== this._initialAnchor?.deref()) {
            this._anchorAbortHandle.abort();
        }
        this._anchor = newAnchor ? new WeakRef(newAnchor) : null;
        this._isTransient = transient;
        this._addAnchorListeners();
    }
    resolveAnchor(value) {
        const resolvedElement = isString(value)
            ? getElementByIdFromRoot(this._host, value)
            : value;
        this._initialAnchor = resolvedElement ? new WeakRef(resolvedElement) : null;
        this.setAnchor(resolvedElement);
    }
    hostConnected() {
        this.resolveAnchor(this._host.anchor);
    }
    hostDisconnected() {
        this._dispose();
    }
}
function parseTriggers(string) {
    return new Set((string ?? '').split(TooltipRegexes.triggers).filter((s) => s.trim()));
}
export const TooltipRegexes = Object.freeze({
    triggers: /[,\s]+/,
    horizontalStart: /^(left|right)-start$/,
    horizontalEnd: /^(left|right)-end$/,
    start: /start$/,
    end: /end$/,
});
export function addTooltipController(host, options) {
    return new TooltipController(host, options);
}
//# sourceMappingURL=controller.js.map