import { __decorate, __metadata } from "tslib";
import { createPopper } from "@popperjs/core";
import { h, Host, } from "@stencil/core";
import { BEM } from "../../utils/bem";
import { balBreakpoints, ListenToBreakpoints } from "../../utils/breakpoints";
import { balBrowser } from "../../utils/browser";
import { Logger } from "../../utils/log";
export class Popover {
    constructor() {
        this.popoverId = `bal-po-${PopoverIds++}`;
        this.isTouch = balBreakpoints.isTouch;
        this.isInMainNav = false;
        this.backdropHeight = 0;
        /**
         * PUBLIC PROPERTY API
         * ------------------------------------------------------
         */
        /**
         * If `true` the popover automatically opens on a click
         */
        this.autoTrigger = false;
        /**
         * If `true` the popover has max-width on tablet and desktop. On mobile it uses the whole viewport.
         */
        this.hint = false;
        /**
         * If `true` the popover shows on hover
         */
        this.hover = false;
        /**
         * If `true` a little arrow is added, which points to the trigger element
         */
        this.arrow = false;
        /**
         * If `true` a backdrop is added
         */
        this.backdrop = false;
        /**
         * If `true` the popover is shown as a tooltip
         */
        this.tooltip = false;
        /**
         * Define the offset of the popover content.
         */
        this.offsetX = 0;
        /**
         * Define the offset of the popover content.
         */
        this.offsetY = 0;
        /**
         * Define padding of the overflow
         */
        this.padding = 0;
        /**
         * Define the position of the popover content.
         */
        this.position = 'bottom-start';
        /**
         * If `true` the popover content is open.
         */
        this.active = false;
        /**
         * If `true` there will be no backdrop
         */
        this.mobileTop = false;
    }
    createLogger(log) {
        this.log = log;
    }
    /**
     * Update the native input element when the value changes
     */
    async activeChanged(newValue, oldValue) {
        if (newValue === true && newValue !== oldValue) {
            this.present({ force: true });
        }
        else {
            this.dismiss({ force: true });
        }
    }
    /**
     * LIFECYCLE
     * ------------------------------------------------------
     */
    componentWillLoad() {
        this.backdropHeight = this.getBackdropHeight();
        this.triggerElement.setAttribute('aria-haspopup', 'true');
    }
    componentDidLoad() {
        this.isInMainNav = this.footMobileNav !== null;
        if (this.triggerElement && this.menuElement) {
            this.popperInstance = createPopper(this.triggerElement, this.menuElement, {
                placement: this.tooltip ? 'bottom' : this.position,
                modifiers: [this.modifierOffset, this.modifierPreventOverflow],
            });
            let showEvents = [];
            let hideEvents = [];
            if (this.autoTrigger) {
                showEvents = ['click'];
            }
            if (this.tooltip) {
                showEvents = ['mouseenter', 'focus'];
                hideEvents = ['mouseleave', 'blur'];
            }
            showEvents.forEach(event => {
                if (this.triggerElement) {
                    if (event === 'click') {
                        this.triggerElement.addEventListener(event, () => this.toggle());
                    }
                    else {
                        this.triggerElement.addEventListener(event, () => this.present());
                    }
                }
            });
            hideEvents.forEach(event => {
                if (this.triggerElement) {
                    this.triggerElement.addEventListener(event, () => this.dismiss());
                }
            });
        }
    }
    componentDidRender() {
        if (this.popperInstance) {
            this.popperInstance.setOptions((options) => (Object.assign(Object.assign({}, options), { placement: this.tooltip ? 'bottom' : this.position, modifiers: [
                    ...options.modifiers.filter((m) => m.name !== 'offset' && m.name !== 'preventOverflow'),
                    this.modifierOffset,
                    this.modifierPreventOverflow,
                ] })));
            this.updatePopper();
        }
        // Bug fix for https://github.com/baloise/design-system/issues/551
        if (balBrowser.isSafari && !this.isTouch) {
            clearTimeout(this.componentDidRenderTimer);
            this.componentDidRenderTimer = setTimeout(() => {
                var _a;
                const triggerWidth = (_a = this.el) === null || _a === void 0 ? void 0 : _a.clientWidth;
                if (triggerWidth) {
                    this.el.style.maxWidth = `${triggerWidth}px`;
                }
                else {
                    this.el.style.maxWidth = `initial`;
                }
            });
        }
    }
    /**
     * LISTENERS
     * ------------------------------------------------------
     */
    handlePopoverPrepare(ev) {
        const popoverId = ev.detail;
        if (this.popoverId !== popoverId) {
            this.dismiss();
        }
    }
    async clickOnOutside(ev) {
        var _a;
        if (this.active) {
            if (!this.el.contains(ev.target)) {
                this.active = false;
            }
            if ((_a = this.backdropElement) === null || _a === void 0 ? void 0 : _a.isEqualNode(ev.target)) {
                this.active = false;
            }
        }
    }
    handleKeyUp(ev) {
        if (this.active && (ev.key === 'Escape' || ev.key === 'Esc')) {
            ev.preventDefault();
            this.dismiss();
        }
    }
    async tabOutside(ev) {
        if (ev.key === 'Tab' && !this.el.contains(document.activeElement) && this.active) {
            await this.toggle();
        }
    }
    breakpointListener(breakpoints) {
        this.isTouch = breakpoints.touch;
        this.isInMainNav = this.footMobileNav !== null;
        this.backdropHeight = this.getBackdropHeight();
    }
    /**
     * PUBLIC METHODS
     * ------------------------------------------------------
     */
    /**
     * Open the popover
     */
    async present(options = { force: false }) {
        var _a, _b;
        if (!this.active || options.force) {
            (_a = this.menuElement) === null || _a === void 0 ? void 0 : _a.setAttribute('data-show', '');
            (_b = this.menuElement) === null || _b === void 0 ? void 0 : _b.setAttribute('aria-hidden', 'false');
            if (this.menuInnerElement) {
                this.menuInnerElement.scrollTo(0, 0);
            }
            this.balPopoverPrepare.emit(this.popoverId);
            this.balWillAnimate.emit(this.active);
            this.active = true;
            this.popperInstance.setOptions((options) => (Object.assign(Object.assign({}, options), { modifiers: [...options.modifiers, { name: 'eventListeners', enabled: true }] })));
            this.updatePopper();
            this.balChange.emit(this.active);
            this.balDidAnimate.emit(this.active);
        }
    }
    /**
     * Closes the popover
     */
    async dismiss(options = { force: false }) {
        var _a, _b;
        if (this.active || options.force) {
            (_a = this.menuElement) === null || _a === void 0 ? void 0 : _a.removeAttribute('data-show');
            (_b = this.menuElement) === null || _b === void 0 ? void 0 : _b.setAttribute('aria-hidden', 'true');
            this.balWillAnimate.emit(this.active);
            this.active = false;
            this.popperInstance.setOptions((options) => (Object.assign(Object.assign({}, options), { modifiers: [...options.modifiers, { name: 'eventListeners', enabled: false }] })));
            this.updatePopper();
            this.balChange.emit(this.active);
            this.balDidAnimate.emit(this.active);
        }
    }
    /**
     * Open or closes the popover
     */
    async toggle(options = { force: false }) {
        if (this.active) {
            await this.dismiss(options);
        }
        else {
            await this.present(options);
        }
    }
    /**
     * GETTERS
     * ------------------------------------------------------
     */
    get footMobileNav() {
        return this.el.closest('[slot="meta-mobile-foot"]');
    }
    get modifierOffset() {
        return {
            name: 'offset',
            options: {
                offset: [this.offsetX, this.offsetY + (this.tooltip || this.arrow ? 8 : 0)],
            },
        };
    }
    get modifierPreventOverflow() {
        return {
            name: 'preventOverflow',
            options: {
                padding: this.arrow || this.tooltip ? 8 : this.padding,
                altAxis: true,
            },
        };
    }
    get triggerElement() {
        return this.el.querySelector('[bal-popover-trigger]');
    }
    get menuElement() {
        return this.el.querySelector('bal-popover-content');
    }
    get menuInnerElement() {
        return this.el.querySelector('.bal-popover__content__inner');
    }
    getBackdropHeight() {
        if (balBrowser.hasWindow) {
            return this.isInMainNav ? (window.innerHeight - (this.isTouch ? 64 : 48)) / 16 : window.innerHeight / 16;
        }
        return 0;
    }
    /**
     * PRIVATE METHODS
     * ------------------------------------------------------
     */
    updatePopper() {
        this.popperInstance.update();
    }
    /**
     * RENDER
     * ------------------------------------------------------
     */
    render() {
        const block = BEM.block('popover');
        return (h(Host, { key: 'f4b281b4ca30365ec4b279c3e219a0109edc173d', "aria-presented": this.active ? 'true' : null, "data-id": this.popoverId, class: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, block.class()), block.modifier('active').class(this.active)), block.modifier('tooltip').class(this.tooltip)), block.modifier('arrow').class(this.arrow)), block.modifier('hint').class(this.hint)), block.modifier('backdrop').class(this.backdrop)) }, !this.mobileTop && (h("div", { key: 'd40df31685649965a301ada5e1c7e7f2a629596c', ref: el => {
                this.backdropElement = el;
            }, class: Object.assign({}, block.element('backdrop').class(this.backdrop && this.active)), style: {
                '--bal-popover-backdrop-height': `${this.backdropHeight}rem`,
            } })), h("slot", { key: '04ec4d9a6c214d1c14a436906e80dc721349ab78' })));
    }
    static get is() { return "bal-popover"; }
    static get originalStyleUrls() {
        return {
            "$": ["bal-popover.sass"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["bal-popover.css"]
        };
    }
    static get properties() {
        return {
            "autoTrigger": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true` the popover automatically opens on a click"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "auto-trigger",
                "defaultValue": "false"
            },
            "hint": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true` the popover has max-width on tablet and desktop. On mobile it uses the whole viewport."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "hint",
                "defaultValue": "false"
            },
            "hover": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true` the popover shows on hover"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "hover",
                "defaultValue": "false"
            },
            "arrow": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true` a little arrow is added, which points to the trigger element"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "arrow",
                "defaultValue": "false"
            },
            "backdrop": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true` a backdrop is added"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "backdrop",
                "defaultValue": "false"
            },
            "tooltip": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true` the popover is shown as a tooltip"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "tooltip",
                "defaultValue": "false"
            },
            "offsetX": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Define the offset of the popover content."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "offset-x",
                "defaultValue": "0"
            },
            "offsetY": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Define the offset of the popover content."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "offset-y",
                "defaultValue": "0"
            },
            "padding": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Define padding of the overflow"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "padding",
                "defaultValue": "0"
            },
            "position": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "BalProps.BalPopoverPlacement",
                    "resolved": "\"auto\" | \"auto-end\" | \"auto-start\" | \"bottom\" | \"bottom-end\" | \"bottom-start\" | \"left\" | \"left-end\" | \"left-start\" | \"right\" | \"right-end\" | \"right-start\" | \"top\" | \"top-end\" | \"top-start\"",
                    "references": {
                        "BalProps": {
                            "location": "global",
                            "id": "global::BalProps"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Define the position of the popover content."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "position",
                "defaultValue": "'bottom-start'"
            },
            "active": {
                "type": "boolean",
                "mutable": true,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true` the popover content is open."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "active",
                "defaultValue": "false"
            },
            "mobileTop": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true` there will be no backdrop"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "mobile-top",
                "defaultValue": "false"
            }
        };
    }
    static get states() {
        return {
            "isTouch": {},
            "isInMainNav": {},
            "backdropHeight": {}
        };
    }
    static get events() {
        return [{
                "method": "balChange",
                "name": "balChange",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Listen when the popover opens or closes. Returns the current value."
                },
                "complexType": {
                    "original": "BalEvents.BalPopoverChangeDetail",
                    "resolved": "boolean",
                    "references": {
                        "BalEvents": {
                            "location": "global",
                            "id": "global::BalEvents"
                        }
                    }
                }
            }, {
                "method": "balWillAnimate",
                "name": "balWillAnimate",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted before the animation starts"
                },
                "complexType": {
                    "original": "BalEvents.BalPopoverWillAnimateDetail",
                    "resolved": "boolean",
                    "references": {
                        "BalEvents": {
                            "location": "global",
                            "id": "global::BalEvents"
                        }
                    }
                }
            }, {
                "method": "balDidAnimate",
                "name": "balDidAnimate",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted after the animation has finished"
                },
                "complexType": {
                    "original": "BalEvents.BalPopoverDidAnimateDetail",
                    "resolved": "boolean",
                    "references": {
                        "BalEvents": {
                            "location": "global",
                            "id": "global::BalEvents"
                        }
                    }
                }
            }, {
                "method": "balPopoverPrepare",
                "name": "balPopoverPrepare",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [{
                            "name": "internal",
                            "text": "- Use this to close unused popovers."
                        }],
                    "text": ""
                },
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                }
            }];
    }
    static get methods() {
        return {
            "present": {
                "complexType": {
                    "signature": "(options?: PopoverPresentOptions) => Promise<void>",
                    "parameters": [{
                            "name": "options",
                            "type": "PopoverPresentOptions",
                            "docs": ""
                        }],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "PopoverPresentOptions": {
                            "location": "local",
                            "path": "/home/runner/work/design-system/design-system/packages/core/src/components/bal-popover/bal-popover.tsx",
                            "id": "src/components/bal-popover/bal-popover.tsx::PopoverPresentOptions"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Open the popover",
                    "tags": []
                }
            },
            "dismiss": {
                "complexType": {
                    "signature": "(options?: PopoverPresentOptions) => Promise<void>",
                    "parameters": [{
                            "name": "options",
                            "type": "PopoverPresentOptions",
                            "docs": ""
                        }],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "PopoverPresentOptions": {
                            "location": "local",
                            "path": "/home/runner/work/design-system/design-system/packages/core/src/components/bal-popover/bal-popover.tsx",
                            "id": "src/components/bal-popover/bal-popover.tsx::PopoverPresentOptions"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Closes the popover",
                    "tags": []
                }
            },
            "toggle": {
                "complexType": {
                    "signature": "(options?: PopoverPresentOptions) => Promise<void>",
                    "parameters": [{
                            "name": "options",
                            "type": "PopoverPresentOptions",
                            "docs": ""
                        }],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "PopoverPresentOptions": {
                            "location": "local",
                            "path": "/home/runner/work/design-system/design-system/packages/core/src/components/bal-popover/bal-popover.tsx",
                            "id": "src/components/bal-popover/bal-popover.tsx::PopoverPresentOptions"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Open or closes the popover",
                    "tags": []
                }
            }
        };
    }
    static get elementRef() { return "el"; }
    static get watchers() {
        return [{
                "propName": "active",
                "methodName": "activeChanged"
            }];
    }
    static get listeners() {
        return [{
                "name": "balPopoverPrepare",
                "method": "handlePopoverPrepare",
                "target": "document",
                "capture": false,
                "passive": false
            }, {
                "name": "click",
                "method": "clickOnOutside",
                "target": "document",
                "capture": false,
                "passive": false
            }, {
                "name": "keydown",
                "method": "handleKeyUp",
                "target": "window",
                "capture": false,
                "passive": false
            }, {
                "name": "keyup",
                "method": "tabOutside",
                "target": "document",
                "capture": false,
                "passive": false
            }];
    }
}
__decorate([
    Logger('bal-popover'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Function]),
    __metadata("design:returntype", void 0)
], Popover.prototype, "createLogger", null);
__decorate([
    ListenToBreakpoints(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", void 0)
], Popover.prototype, "breakpointListener", null);
let PopoverIds = 0;
