import { Host, h } from "@stencil/core";
import { trackComponent } from "../../global/utils/tracking";
import { isNestedInIfxComponent } from "../../global/utils/dom-utils";
import { detectFramework } from "../../global/utils/framework-detection";
import { queryShadowRoot, isHidden, isFocusable } from "../../global/utils/focus-trap";
import { animationTo, KEYFRAMES } from "../../global/utils/animation";
export class IfxModal {
    constructor() {
        this.opened = false;
        this.showModal = this.opened || false;
        this.caption = 'Modal Title';
        this.closeOnOverlayClick = true;
        this.variant = 'default';
        this.size = 's';
        this.alertIcon = '';
        this.okButtonLabel = 'OK';
        this.cancelButtonLabel = 'Cancel';
        this.slotButtonsPresent = false;
        this.showCloseButton = true;
        this.focusableElements = [];
        this.handleResize = () => {
            clearTimeout(this.resizeTimeout);
            this.resizeTimeout = setTimeout(() => {
                if (this.showModal) {
                    this.handleComponentOverflow();
                }
            }, 100);
        };
        this.handleTopFocus = () => {
            this.attemptFocus(this.getLastFocusableElement());
        };
        this.handleBottomFocus = () => {
            this.attemptFocus(this.getFirstFocusableElement());
        };
        this.handleKeypress = (event) => {
            if (!this.showModal) {
                return;
            }
            if (event.key === 'Escape') {
                this.doBeforeClose('ESCAPE_KEY');
            }
        };
    }
    async componentDidLoad() {
        if (!isNestedInIfxComponent(this.hostElement)) {
            const framework = detectFramework();
            trackComponent('ifx-modal', await framework);
        }
        // Query all focusable elements and store them in `focusableElements`.
        // Needed for the "focus trap" functionality.
        this.focusableElements = queryShadowRoot(this.hostElement.shadowRoot, (el) => isHidden(el) || el.matches('[data-focus-trap-edge]'), isFocusable);
        window.addEventListener('resize', this.handleResize);
    }
    disconnectedCallback() {
        window.removeEventListener('resize', this.handleResize);
    }
    componentWillRender() {
        if (this.showModal) {
            this.handleComponentOverflow();
        }
    }
    async handleComponentOverflow() {
        const modalContentContainer = this.hostElement.shadowRoot.querySelector('.modal-content-container');
        if (this.showModal && await this.isModalContentContainerHeightReachedViewport()) {
            modalContentContainer.classList.add('no-overflow');
        }
        else if (modalContentContainer === null || modalContentContainer === void 0 ? void 0 : modalContentContainer.classList.contains('no-overflow')) {
            modalContentContainer === null || modalContentContainer === void 0 ? void 0 : modalContentContainer.classList.remove('no-overflow');
        }
    }
    getFirstFocusableElement() {
        return this.focusableElements[0];
    }
    getLastFocusableElement() {
        return this.focusableElements[this.focusableElements.length - 1];
    }
    attemptFocus(element) {
        if (element == null) {
            setTimeout(() => {
                this.closeButton.focus();
            });
            return;
        }
        setTimeout(() => {
            element.focus();
        }, 0);
    }
    open() {
        this.showModal = true;
        try {
            const anim = animationTo(this.modalContainer, KEYFRAMES.fadeIn, {
                duration: 200,
            });
            anim.addEventListener('finish', () => {
                // Setting focus on last item and removing immediately
                // so, on tab press first element is focused
                setTimeout(() => {
                    var _a, _b;
                    (_a = this.getLastFocusableElement()) === null || _a === void 0 ? void 0 : _a.focus();
                    (_b = this.getLastFocusableElement()) === null || _b === void 0 ? void 0 : _b.blur();
                }, 0);
                this.ifxOpen.emit();
            });
            this.hostElement.addEventListener('keydown', this.handleKeypress);
        }
        catch (err) {
            this.ifxOpen.emit();
        }
    }
    close() {
        try {
            const anim = animationTo(this.modalContainer, KEYFRAMES.fadeOut, {
                duration: 200,
            });
            anim.addEventListener('finish', () => {
                this.showModal = false;
                this.ifxClose.emit();
            });
            this.hostElement.removeEventListener('keydown', this.handleKeypress);
        }
        catch (err) {
            this.showModal = false;
            this.ifxClose.emit();
        }
    }
    doBeforeClose(trigger) {
        const triggers = [];
        triggers.push(trigger);
        const prevented = triggers.some((event) => event.defaultPrevented);
        if (!prevented) {
            this.opened = false;
        }
    }
    openedChanged(newValue) {
        if (newValue === true) {
            this.open();
        }
        else {
            this.close();
        }
    }
    handleOverlayClick() {
        if (this.closeOnOverlayClick) {
            this.doBeforeClose('BACKDROP');
        }
    }
    handleContentUpdate(e) {
        const slotElement = e.target;
        const nodes = slotElement.assignedNodes();
        if (nodes.length > 0) {
            nodes.forEach(node => {
                if (node.observer) {
                    node.observer.disconnect();
                    delete node.observer;
                }
                const observer = new MutationObserver((mutationsList, _) => {
                    for (let mutation of mutationsList) {
                        if (mutation.type === 'childList') {
                            if (this.showModal) {
                                this.handleComponentOverflow();
                            }
                        }
                    }
                });
                observer.observe(node, { attributes: true, childList: true, subtree: true });
                node.observer = observer;
            });
        }
    }
    handleButtonsSlotChange(e) {
        var _a;
        if (((_a = e.currentTarget.assignedElements()[0]) === null || _a === void 0 ? void 0 : _a.childElementCount) > 0) {
            this.slotButtonsPresent = true;
        }
        else {
            this.slotButtonsPresent = false;
        }
    }
    isModalContentContainerHeightReachedViewport() {
        //Adding timeout for proper height detection on Edge browser
        return new Promise(resolve => {
            setTimeout(() => {
                const modalContent = this.hostElement.shadowRoot.querySelector('.modal-content');
                const modalContentHeight = modalContent.offsetHeight;
                const viewportHeight = window.innerHeight;
                const extraMarginForEdgeBrowser = 3;
                resolve(modalContentHeight + extraMarginForEdgeBrowser >= viewportHeight * 0.9);
            }, 100);
        });
    }
    render() {
        const isAlertVariant = this.variant !== 'default';
        return (h(Host, { key: '8927c0356e8b8987acf9310b559c1568c6de4f37' }, h("div", { key: 'df0f8b0be2953a4974ca739120c7b7495c52fc1f', ref: (el) => (this.modalContainer = el), class: `modal-container ${this.showModal ? 'open' : ''}` }, h("div", { key: '8e6d35ddf390200573b38c6b2057bdf382838428', class: "modal-overlay", onClick: () => this.handleOverlayClick() }), h("div", { key: '324587e244e5519f7e0d755cbf1b43b1ca998ce7', "data-focus-trap-edge": true, onFocus: this.handleTopFocus, tabindex: "0" }), h("div", { key: '11cb80157d6ae5e0c57b786c0a295722b6c94d85', class: `modal-content-container ${this.size}`, role: "dialog", "aria-modal": "true", "aria-label": this.captionAriaLabel }, isAlertVariant ? (h("div", { class: `modal-icon-container ${this.variant === 'alert-brand' ? '' : 'danger'}` }, this.alertIcon ? h("ifx-icon", { icon: this.alertIcon }) : null)) : null, h("div", { key: 'ec6865df02bd71ac1b8513e147bf48bab522479b', class: "modal-content" }, h("div", { key: 'c9591304fc6ee447a60d16eea4c5017903397691', class: "modal-header" }, h("h2", { key: 'de9241b726711243ca5101ce3e49250f743c994b', class: "modal-caption" }, this.caption), this.showCloseButton &&
            h("ifx-icon-button", { key: '561e1f6783efc4f54f422856cc4cb36c89503529', class: 'modal-close-button', ref: (el) => (this.closeButton = el), icon: "cross-16", variant: "tertiary", onClick: () => this.doBeforeClose('CLOSE_BUTTON') })), h("div", { key: '12788241b957ea98433872238c15a8d2ad9c13f6', class: "modal-body" }, h("slot", { key: '1dab9a551e1dbe7e90334869282ef0c6597104a7', name: "content", onSlotchange: (e) => this.handleContentUpdate(e) })), h("div", { key: '215c3be2970c6191a97a878d8fb97d5c8a2a40e6', class: `modal-footer ${this.slotButtonsPresent ? 'buttons-present' : ''}` }, h("slot", { key: '221bf1f5442baa42a6e098505baa32b5aa343ba0', name: "buttons", onSlotchange: (e) => this.handleButtonsSlotChange(e) })))), h("div", { key: '516f850b612376cde60c4cff6f7e04927bda5e7e', "data-focus-trap-edge": true, onFocus: this.handleBottomFocus, tabindex: "0" }))));
    }
    static get is() { return "ifx-modal"; }
    static get encapsulation() { return "shadow"; }
    static get originalStyleUrls() {
        return {
            "$": ["modal.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["modal.css"]
        };
    }
    static get properties() {
        return {
            "opened": {
                "type": "boolean",
                "attribute": "opened",
                "mutable": true,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "defaultValue": "false"
            },
            "caption": {
                "type": "string",
                "attribute": "caption",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "'Modal Title'"
            },
            "captionAriaLabel": {
                "type": "string",
                "attribute": "caption-aria-label",
                "mutable": false,
                "complexType": {
                    "original": "string | null",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "closeOnOverlayClick": {
                "type": "boolean",
                "attribute": "close-on-overlay-click",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "true"
            },
            "variant": {
                "type": "string",
                "attribute": "variant",
                "mutable": false,
                "complexType": {
                    "original": "'default' | 'alert-brand' | 'alert-danger'",
                    "resolved": "\"alert-brand\" | \"alert-danger\" | \"default\"",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "'default'"
            },
            "size": {
                "type": "string",
                "attribute": "size",
                "mutable": false,
                "complexType": {
                    "original": "'s' | 'm' | 'l'",
                    "resolved": "\"l\" | \"m\" | \"s\"",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "'s'"
            },
            "alertIcon": {
                "type": "string",
                "attribute": "alert-icon",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "''"
            },
            "okButtonLabel": {
                "type": "string",
                "attribute": "ok-button-label",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "'OK'"
            },
            "cancelButtonLabel": {
                "type": "string",
                "attribute": "cancel-button-label",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "'Cancel'"
            },
            "closeButtonAriaLabel": {
                "type": "string",
                "attribute": "close-button-aria-label",
                "mutable": false,
                "complexType": {
                    "original": "string | null",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "showCloseButton": {
                "type": "boolean",
                "attribute": "show-close-button",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "true"
            }
        };
    }
    static get states() {
        return {
            "showModal": {},
            "slotButtonsPresent": {}
        };
    }
    static get events() {
        return [{
                "method": "ifxOpen",
                "name": "ifxOpen",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "any",
                    "resolved": "any",
                    "references": {}
                }
            }, {
                "method": "ifxClose",
                "name": "ifxClose",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "any",
                    "resolved": "any",
                    "references": {}
                }
            }];
    }
    static get elementRef() { return "hostElement"; }
    static get watchers() {
        return [{
                "propName": "opened",
                "methodName": "openedChanged"
            }];
    }
}
//# sourceMappingURL=modal.js.map
