import { h } from "@stencil/core";
export class PdsModal {
    constructor() {
        this.focusableElements = [];
        /**
         * Whether the modal can be dismissed by clicking the backdrop
         * @default true
         */
        this.backdropDismiss = true;
        /**
         * Whether the modal is open
         * @default false
         */
        this.open = false;
        /**
         * The size of the modal
         * @default 'md'
         */
        this.size = 'md';
        /**
         * Whether the modal content should be scrollable
         * @default true
         */
        this.scrollable = true;
        /**
         * Stores the list of focusable elements in the modal
         */
        this.focusableElementsArray = [];
        this.handleBackdropClick = (e) => {
            if (!this.backdropDismiss || !this.open)
                return;
            if (e.target.classList.contains('pds-modal__backdrop')) {
                e.stopPropagation();
                // Only close if this is the innermost modal
                if (this.isInnermostModal()) {
                    this.hideModal();
                }
            }
        };
        this.handleKeyDown = (e) => {
            // If the modal is not open, don't handle any keyboard events
            if (!this.open)
                return;
            // Handle Escape key to close the modal
            if (e.key === 'Escape') {
                // Always prevent native dialog close behavior
                e.preventDefault();
                // Only close if backdropDismiss is enabled and this is the innermost modal
                if (this.backdropDismiss && this.isInnermostModal()) {
                    this.hideModal();
                }
                return;
            }
            // Handle Tab key for focus trapping
            if (e.key === 'Tab') {
                // If there are no focusable elements, do nothing
                if (this.focusableElements.length === 0)
                    return;
                // Get the first and last focusable elements
                const firstFocusableElement = this.focusableElements[0];
                const lastFocusableElement = this.focusableElements[this.focusableElements.length - 1];
                // Get the current active element
                const activeElement = document.activeElement;
                // Check if we need to wrap focus
                const isFirstElement = activeElement === firstFocusableElement ||
                    firstFocusableElement.contains(activeElement);
                const isLastElement = activeElement === lastFocusableElement ||
                    lastFocusableElement.contains(activeElement);
                // If shift + tab is pressed and focus is on the first element, move to the last element
                if (e.shiftKey && isFirstElement) {
                    e.preventDefault();
                    this.focusElement(lastFocusableElement);
                }
                // If tab is pressed and focus is on the last element, move to the first element
                else if (!e.shiftKey && isLastElement) {
                    e.preventDefault();
                    this.focusElement(firstFocusableElement);
                }
            }
        };
    }
    componentDidLoad() {
        this.modalRef = this.el.querySelector('.pds-modal__backdrop');
        // Add keyboard event listener
        document.addEventListener('keydown', this.handleKeyDown);
    }
    disconnectedCallback() {
        // Clean up event listener
        document.removeEventListener('keydown', this.handleKeyDown);
    }
    handleOpenChange(newValue) {
        if (newValue) {
            this.showModal();
        }
        else {
            this.hideModal();
        }
    }
    /**
     * Updates the list of focusable elements in the modal
     */
    updateFocusableElements() {
        if (!this.modalRef)
            return;
        // Get all focusable elements within the modal
        const selector = [
            'a[href]',
            'button:not([disabled])',
            'input:not([disabled])',
            'select:not([disabled])',
            'textarea:not([disabled])',
            '[tabindex]:not([tabindex="-1"])',
            'pds-button:not([disabled])',
            'pds-link:not([disabled])',
            'pds-input:not([disabled])',
            'pds-checkbox:not([disabled])',
            'pds-radio:not([disabled])',
            'pds-switch:not([disabled])',
            'pds-select:not([disabled])',
        ].join(',');
        this.focusableElements = Array.from(this.modalRef.querySelectorAll(selector));
        // Filter out elements with display: none or visibility: hidden
        this.focusableElements = this.focusableElements.filter(el => {
            const style = window.getComputedStyle(el);
            return style.display !== 'none' && style.visibility !== 'hidden';
        });
    }
    /**
     * Sets focus to the first focusable element in the modal
     */
    setInitialFocus() {
        if (this.focusableElements.length === 0)
            return;
        // Focus the first focusable element
        const firstElement = this.focusableElements[0];
        // For web components, we need to ensure they're properly focused
        this.focusElement(firstElement);
    }
    /**
     * Helper method to focus an element, with special handling for web components
     */
    focusElement(element) {
        if (!element)
            return;
        try {
            // Try standard focus first
            element.focus();
            // Check if focus worked
            setTimeout(() => {
                if (document.activeElement !== element) {
                    // For web components, try to find a focusable element inside
                    if (element.shadowRoot) {
                        const focusableInShadow = element.shadowRoot.querySelector('button, [tabindex], input, a[href]');
                        if (focusableInShadow) {
                            focusableInShadow.focus();
                        }
                    }
                }
            }, 0);
        }
        catch (error) {
            console.error('Error focusing element:', error);
        }
    }
    /**
     * Opens the modal
     */
    async showModal() {
        if (this.modalRef) {
            try {
                // Store the currently focused element to restore focus when modal closes
                this.previousActiveElement = document.activeElement;
                // Use native dialog showModal method which makes the rest of the page inert
                this.modalRef.showModal();
                this.open = true;
                // Update focusable elements and set initial focus
                // Using a longer timeout to ensure all components are fully rendered
                setTimeout(() => {
                    this.updateFocusableElements();
                    this.setInitialFocus();
                    this.pdsModalOpen.emit();
                }, 100);
            }
            catch (error) {
                console.error('Failed to show modal:', error);
            }
        }
    }
    /**
     * Closes the modal
     */
    async hideModal() {
        if (this.modalRef) {
            try {
                this.modalRef.close();
                this.open = false;
                // Restore focus to the element that was focused before the modal was opened
                if (this.previousActiveElement && typeof this.previousActiveElement.focus === 'function') {
                    this.previousActiveElement.focus();
                }
                this.pdsModalClose.emit();
            }
            catch (error) {
                console.error('Failed to hide modal:', error);
            }
        }
    }
    /**
     * Gets the z-index of a modal's backdrop element
     */
    getBackdropZIndex(modal) {
        const backdrop = modal.querySelector('.pds-modal__backdrop');
        return backdrop ? parseInt(getComputedStyle(backdrop).zIndex, 10) : -1;
    }
    /**
     * Checks if this modal is the innermost (highest z-index) modal
     */
    isInnermostModal() {
        // Find all open modals
        const openModals = Array.from(document.querySelectorAll('pds-modal')).filter(modal => modal.open);
        if (openModals.length === 0)
            return false;
        // Get this modal's backdrop element
        const thisBackdrop = this.el.querySelector('.pds-modal__backdrop');
        if (!thisBackdrop)
            return false;
        // Get computed z-index of all open modal backdrops
        const modalZIndexes = openModals.map(modal => this.getBackdropZIndex(modal));
        // Get the highest z-index
        const maxZIndex = Math.max(...modalZIndexes);
        // Check if this modal's backdrop has the highest z-index
        const thisZIndex = this.getBackdropZIndex(this.el);
        return thisZIndex === maxZIndex;
    }
    render() {
        return (h("dialog", { key: 'cf2710a889d8f0e80a3551088ab38a88dc44ad1e', class: {
                'pds-modal__backdrop': true,
                'open': this.open
            }, "aria-modal": "true", "aria-labelledby": `${this.componentId}-heading`, onClick: this.handleBackdropClick }, h("div", { key: 'a06d017153e67ad38bc1ced56ba22aeade977aaf', class: {
                'pds-modal': true,
                [`pds-modal--${this.size}`]: true,
                'pds-modal--scrollable': this.scrollable
            }, part: "modal" }, h("slot", { key: 'd995c586809a4940c091912244a86cb4605a961c' }))));
    }
    static get is() { return "pds-modal"; }
    static get originalStyleUrls() {
        return {
            "$": ["pds-modal.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["pds-modal.css"]
        };
    }
    static get properties() {
        return {
            "backdropDismiss": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "default",
                            "text": "true"
                        }],
                    "text": "Whether the modal can be dismissed by clicking the backdrop"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "backdrop-dismiss",
                "defaultValue": "true"
            },
            "componentId": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "A unique identifier used for the underlying component `id` attribute."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "component-id"
            },
            "open": {
                "type": "boolean",
                "mutable": true,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "default",
                            "text": "false"
                        }],
                    "text": "Whether the modal is open"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "open",
                "defaultValue": "false"
            },
            "size": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "'sm' | 'md' | 'lg' | 'fullscreen'",
                    "resolved": "\"fullscreen\" | \"lg\" | \"md\" | \"sm\"",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "default",
                            "text": "'md'"
                        }],
                    "text": "The size of the modal"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "size",
                "defaultValue": "'md'"
            },
            "scrollable": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "default",
                            "text": "true"
                        }],
                    "text": "Whether the modal content should be scrollable"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "scrollable",
                "defaultValue": "true"
            }
        };
    }
    static get states() {
        return {
            "focusableElementsArray": {}
        };
    }
    static get events() {
        return [{
                "method": "pdsModalOpen",
                "name": "pdsModalOpen",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the modal is opened"
                },
                "complexType": {
                    "original": "void",
                    "resolved": "void",
                    "references": {}
                }
            }, {
                "method": "pdsModalClose",
                "name": "pdsModalClose",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the modal is closed"
                },
                "complexType": {
                    "original": "void",
                    "resolved": "void",
                    "references": {}
                }
            }];
    }
    static get methods() {
        return {
            "showModal": {
                "complexType": {
                    "signature": "() => Promise<void>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "HTMLElement": {
                            "location": "global",
                            "id": "global::HTMLElement"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Opens the modal",
                    "tags": []
                }
            },
            "hideModal": {
                "complexType": {
                    "signature": "() => Promise<void>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Closes the modal",
                    "tags": []
                }
            }
        };
    }
    static get elementRef() { return "el"; }
    static get watchers() {
        return [{
                "propName": "open",
                "methodName": "handleOpenChange"
            }];
    }
}
//# sourceMappingURL=pds-modal.js.map
