import { Host, h } from "@stencil/core";
import { isRtlDirection } from "../../../utils/scroll";
import { enlarge, trash } from "@pine-ds/icons/icons";
/**
 * Individual filter component with cross-browser popover positioning.
 *
 * Uses a hybrid approach for optimal cross-browser compatibility:
 * - Modern browsers: CSS anchor positioning + JavaScript flip classes
 * - Fallback browsers: JavaScript positioning with viewport boundary detection
 *
 * @part button - Exposes the trigger button element for styling.
 * @part button-content - Exposes the button content container for styling.
 * @part button-text - Exposes the button text for styling.
 * @part icon - Exposes the icon component for styling.
 * @part popover - Exposes the popover container for styling.
 * @slot (default) - Popover content that will be displayed when the filter is open.
 */
export class PdsFilter {
    constructor() {
        this.scrollRAF = null;
        this.lastScrollTime = 0;
        /**
         * The variant style of the filter trigger.
         * @defaultValue 'default'
         */
        this.variant = 'default';
        /**
         * State to track if the popover is open.
         */
        this.isOpen = false;
        /**
         * Handle native popover toggle events directly on the element
         * This is needed for browsers with native Popover API support
         */
        this.handleNativePopoverToggle = (event) => {
            const target = event.target;
            if (target && target.id === `${this.componentId}-popover`) {
                // Check current popover state
                let isCurrentlyOpen = false;
                try {
                    isCurrentlyOpen = target.matches(':popover-open');
                }
                catch (error) {
                    // Fallback if :popover-open selector isn't supported
                    isCurrentlyOpen = target.style.display === 'block';
                }
                // Update state
                this.isOpen = isCurrentlyOpen;
                if (this.isOpen) {
                    setTimeout(() => this.adjustPopoverPosition(), 0);
                    this.pdsFilterOpen.emit({
                        componentId: this.componentId,
                        variant: this.variant,
                        text: this.text,
                    });
                }
                else {
                    this.pdsFilterClose.emit({
                        componentId: this.componentId,
                        variant: this.variant,
                        text: this.text,
                    });
                }
            }
        };
        /**
         * Handle keyboard interactions for clear variant only.
         */
        this.handleKeyDown = (event) => {
            // Only handle clear variant manually, let native API handle everything else
            if (this.variant === 'clear' && (event.key === 'Enter' || event.key === ' ')) {
                event.preventDefault();
                this.handleClick();
            }
        };
        /**
         * Handle trigger button click. Clear variant emits event, others toggle popover.
         */
        this.handleClick = (event) => {
            if (this.variant === 'clear') {
                this.pdsFilterClear.emit({
                    componentId: this.componentId,
                    text: this.text,
                });
                return;
            }
            this.closeOtherPopovers();
            // Check for popover API support
            const supportsPopoverAPI = HTMLElement.prototype.showPopover && !navigator.userAgent.includes('Firefox');
            if (!supportsPopoverAPI) {
                // Manual fallback for browsers without popover API support
                // Prevent default to avoid conflicts with any native behavior
                if (event) {
                    event.preventDefault();
                }
                setTimeout(() => {
                    if (this.popoverEl != null) {
                        this.isOpen = !this.isOpen;
                        if (this.isOpen) {
                            this.popoverEl.style.display = 'block';
                            this.popoverEl.classList.add('is-open');
                            this.adjustPopoverPosition();
                            this.pdsFilterOpen.emit({
                                componentId: this.componentId,
                                variant: this.variant,
                                text: this.text,
                            });
                        }
                        else {
                            this.popoverEl.style.display = 'none';
                            this.popoverEl.classList.remove('is-open');
                            this.pdsFilterClose.emit({
                                componentId: this.componentId,
                                variant: this.variant,
                                text: this.text,
                            });
                        }
                    }
                }, 0);
            }
            // For browsers with native popover API, let the native behavior handle the toggle
            // The toggle event listener will capture the state change and emit events
        };
    }
    /**
     * Component lifecycle: Clean up when disconnected from DOM.
     * Prevents memory leaks by canceling pending operations and closing popovers.
     */
    disconnectedCallback() {
        // Cancel pending animation frames
        if (this.scrollRAF) {
            cancelAnimationFrame(this.scrollRAF);
            this.scrollRAF = null;
        }
        this.lastScrollTime = 0;
        // Clean up native popover event listeners
        if (this.popoverEl) {
            const supportsPopoverAPI = HTMLElement.prototype.showPopover && !navigator.userAgent.includes('Firefox');
            if (supportsPopoverAPI) {
                this.popoverEl.removeEventListener('toggle', this.handleNativePopoverToggle);
            }
        }
        // Ensure popover is closed
        if (this.isOpen && this.popoverEl) {
            try {
                this.popoverEl.hidePopover();
            }
            catch (error) {
                this.popoverEl.style.display = 'none';
                this.popoverEl.classList.remove('is-open');
            }
        }
    }
    componentDidRender() {
        // Note: popoverEl is set via ref callback in render method
        // For browsers with native popover API, we need direct element listeners
        // since the document listener may not capture native popover toggle events
        if (this.popoverEl) {
            const supportsPopoverAPI = HTMLElement.prototype.showPopover && !navigator.userAgent.includes('Firefox');
            if (supportsPopoverAPI) {
                // Remove any existing listeners to avoid duplicates
                this.popoverEl.removeEventListener('toggle', this.handleNativePopoverToggle);
                // Add direct listener for native popover events
                this.popoverEl.addEventListener('toggle', this.handleNativePopoverToggle);
            }
        }
    }
    /**
     * Reposition popovers on window resize.
     */
    handleWindowResize() {
        if (this.isOpen) {
            setTimeout(() => this.adjustPopoverPosition(), 16);
        }
    }
    /**
     * Reposition popovers on scroll with performance throttling.
     */
    handleWindowScroll() {
        if (this.isOpen) {
            const supportsAnchorPositioning = "anchorName" in document.documentElement.style;
            const now = performance.now();
            const throttleMs = supportsAnchorPositioning ? 66 : 33;
            if (now - this.lastScrollTime < throttleMs) {
                return;
            }
            this.lastScrollTime = now;
            if (this.scrollRAF) {
                cancelAnimationFrame(this.scrollRAF);
            }
            this.scrollRAF = requestAnimationFrame(() => {
                if (this.isOpen && this.popoverEl && this.el.isConnected) {
                    this.adjustPopoverPosition();
                }
                this.scrollRAF = null;
            });
        }
    }
    /**
     * Closes other open filter popovers to ensure only one is open at a time.
     */
    closeOtherPopovers() {
        const allFilters = document.querySelectorAll('pds-filter');
        allFilters.forEach((filter) => {
            var _a;
            if (filter === this.el)
                return;
            const popover = (_a = filter.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('.pds-filter__popover');
            if (popover) {
                // Check for popover API support to avoid crashes
                let isPopoverOpen = false;
                try {
                    isPopoverOpen = popover.matches(':popover-open');
                }
                catch (error) {
                    // Fallback if :popover-open selector isn't supported
                    isPopoverOpen = popover.style.display === 'block';
                }
                if (isPopoverOpen) {
                    try {
                        popover.hidePopover();
                    }
                    catch (error) {
                        popover.style.display = 'none';
                        popover.classList.remove('is-open');
                    }
                }
            }
        });
    }
    /**
     * Adjusts popover position to keep it within viewport bounds.
     * Uses CSS anchor positioning for modern browsers, JavaScript for fallback browsers.
     */
    adjustPopoverPosition() {
        var _a;
        if (!this.popoverEl || this.variant === 'clear')
            return;
        const triggerEl = (_a = this.el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('.pds-filter__trigger');
        if (!triggerEl)
            return;
        const triggerRect = triggerEl.getBoundingClientRect();
        const viewportWidth = window.innerWidth;
        const viewportHeight = window.innerHeight;
        const supportsAnchorPositioning = "anchorName" in document.documentElement.style;
        // Get dimensions for boundary detection
        const popoverWidth = 228;
        const popoverHeight = this.popoverEl.getBoundingClientRect().height || 200;
        // Boundary detection for flipping (inline-end overflow respects document direction)
        const bufferSpace = 20;
        const isRtl = isRtlDirection(this.el);
        const wouldOverflowInlineEnd = isRtl
            ? (triggerRect.right - popoverWidth - bufferSpace) < 0
            : (triggerRect.left + popoverWidth + bufferSpace) > viewportWidth;
        const wouldOverflowBottom = (triggerRect.bottom + 8 + popoverHeight + bufferSpace) > viewportHeight;
        if (supportsAnchorPositioning) {
            // Modern browsers: CSS anchor positioning + JavaScript-controlled flipping
            this.popoverEl.classList.remove('popover-flip-horizontal', 'popover-flip-vertical');
            if (wouldOverflowInlineEnd) {
                this.popoverEl.classList.add('popover-flip-horizontal');
            }
            if (wouldOverflowBottom) {
                this.popoverEl.classList.add('popover-flip-vertical');
            }
        }
        else {
            // Fallback browsers: JavaScript positioning with boundary detection
            let left = isRtl ? triggerRect.right - popoverWidth : triggerRect.left;
            let top = triggerRect.bottom + 8;
            let transformOrigin = isRtl ? 'top right' : 'top left';
            // Apply horizontal flipping if needed
            if (wouldOverflowInlineEnd) {
                const actualPopoverWidth = this.popoverEl.getBoundingClientRect().width || popoverWidth;
                left = isRtl ? triggerRect.left : triggerRect.right - actualPopoverWidth;
                transformOrigin = isRtl ? 'top left' : 'top right';
            }
            // Apply vertical flipping if needed
            if (wouldOverflowBottom) {
                top = triggerRect.top - popoverHeight - 8;
                transformOrigin = transformOrigin.replace('top', 'bottom');
            }
            // Apply positioning in single DOM write for performance
            this.popoverEl.style.cssText = `
        position: fixed;
        left: ${left}px;
        top: ${top}px;
        z-index: var(--pine-z-index-overlay);
        transform-origin: ${transformOrigin};
      `;
        }
    }
    /**
     * Opens the filter popover programmatically.
     * Note: Clear variant does not support popover functionality.
     */
    async showFilter() {
        if (this.variant === 'clear') {
            console.warn('Clear variant does not support showFilter method');
            return;
        }
        if (this.popoverEl != null) {
            try {
                this.popoverEl.showPopover();
            }
            catch (error) {
                // Fallback for testing environment where showPopover is not available
                this.popoverEl.style.display = 'block';
                this.popoverEl.classList.add('is-open');
            }
        }
    }
    /**
     * Closes the filter popover programmatically.
     * Note: Clear variant does not support popover functionality.
     */
    async hideFilter() {
        if (this.variant === 'clear') {
            console.warn('Clear variant does not support hideFilter method');
            return;
        }
        if (this.popoverEl != null) {
            try {
                this.popoverEl.hidePopover();
            }
            catch (error) {
                // Fallback for testing environment where hidePopover is not available
                this.popoverEl.style.display = 'none';
                this.popoverEl.classList.remove('is-open');
            }
        }
    }
    /**
     * Listen for popover toggle events for browsers without native Popover API (fallback).
     * Native API browsers use direct element listeners to avoid conflicts.
     */
    handlePopoverToggle(event) {
        const target = event.target;
        const supportsPopoverAPI = HTMLElement.prototype.showPopover && !navigator.userAgent.includes('Firefox');
        // Only handle events for fallback browsers (Firefox) to avoid duplicate handling
        if (!supportsPopoverAPI && target && target.id === `${this.componentId}-popover`) {
            // Check for popover API support to avoid crashes
            let isCurrentlyOpen = false;
            try {
                isCurrentlyOpen = target.matches(':popover-open');
            }
            catch (error) {
                // Fallback if :popover-open selector isn't supported
                isCurrentlyOpen = target.style.display === 'block';
            }
            // Update state
            this.isOpen = isCurrentlyOpen;
            if (this.isOpen) {
                setTimeout(() => this.adjustPopoverPosition(), 0);
                this.pdsFilterOpen.emit({
                    componentId: this.componentId,
                    variant: this.variant,
                    text: this.text,
                });
            }
            else {
                this.pdsFilterClose.emit({
                    componentId: this.componentId,
                    variant: this.variant,
                    text: this.text,
                });
            }
        }
    }
    /**
     * Listen for clicks to detect outside dismissal.
     */
    handleDocumentClick(event) {
        // Check if click is outside and popover gets closed
        if (!this.el.contains(event.target) && this.isOpen && this.variant !== 'clear') {
            setTimeout(() => {
                if (this.popoverEl && this.isOpen) {
                    // Check for popover API support to avoid crashes
                    const supportsPopoverAPI = HTMLElement.prototype.showPopover && !navigator.userAgent.includes('Firefox');
                    let popoverIsClosed = false;
                    if (supportsPopoverAPI) {
                        try {
                            popoverIsClosed = !this.popoverEl.matches(':popover-open');
                        }
                        catch (error) {
                            // Fallback if :popover-open selector isn't supported
                            popoverIsClosed = this.popoverEl.style.display !== 'block';
                        }
                    }
                    else {
                        // Manual fallback - assume popover was closed by outside click
                        popoverIsClosed = true;
                    }
                    if (popoverIsClosed) {
                        this.isOpen = false;
                        if (!supportsPopoverAPI) {
                            this.popoverEl.style.display = 'none';
                            this.popoverEl.classList.remove('is-open');
                        }
                        this.pdsFilterClose.emit({
                            componentId: this.componentId,
                            variant: this.variant,
                            text: this.text,
                        });
                    }
                }
            }, 0);
        }
    }
    /**
     * Listen for Escape key to ensure close event fires.
     */
    handleEscapeKey(event) {
        if (event.key === 'Escape' && this.isOpen && this.variant !== 'clear') {
            // Check if popover was closed by Escape
            setTimeout(() => {
                if (this.popoverEl && this.isOpen) {
                    // Check for popover API support to avoid crashes
                    const supportsPopoverAPI = HTMLElement.prototype.showPopover && !navigator.userAgent.includes('Firefox');
                    let popoverIsClosed = false;
                    if (supportsPopoverAPI) {
                        try {
                            popoverIsClosed = !this.popoverEl.matches(':popover-open');
                        }
                        catch (error) {
                            // Fallback if :popover-open selector isn't supported
                            popoverIsClosed = this.popoverEl.style.display !== 'block';
                        }
                    }
                    else {
                        // Manual fallback - assume popover was closed by Escape
                        popoverIsClosed = true;
                    }
                    if (popoverIsClosed) {
                        this.isOpen = false;
                        if (!supportsPopoverAPI) {
                            this.popoverEl.style.display = 'none';
                            this.popoverEl.classList.remove('is-open');
                        }
                        this.pdsFilterClose.emit({
                            componentId: this.componentId,
                            variant: this.variant,
                            text: this.text,
                        });
                    }
                }
            }, 0);
        }
    }
    /**
     * Get the appropriate icon for the variant.
     */
    getIcon() {
        if (this.variant === 'clear') {
            return trash;
        }
        return this.icon;
    }
    /**
     * Get CSS classes for the trigger button.
     */
    getTriggerClasses() {
        const classes = ['pds-filter__trigger'];
        classes.push(`pds-filter__trigger--${this.variant}`);
        if (this.isOpen && this.variant !== 'clear') {
            classes.push('pds-filter__trigger--open');
        }
        return classes.join(' ');
    }
    /**
     * Render the trigger icon.
     */
    renderIcon() {
        const iconToRender = this.getIcon();
        if (iconToRender == null || iconToRender === '')
            return null;
        return (h("pds-icon", { icon: iconToRender, size: "var(--pine-font-size-100)", "aria-hidden": "true", part: "icon" }));
    }
    /**
     * Render the dropdown icon for selected variant.
     */
    renderDropdownIcon() {
        if (this.variant === 'selected') {
            return (h("pds-icon", { icon: enlarge, size: "var(--pine-dimension-200)", "aria-hidden": "true", class: "pds-filter__dropdown-icon", part: "icon" }));
        }
        return null;
    }
    render() {
        return (h(Host, { key: '620b1e6b9ab4a16af9cf601381e3b3bc625677a9', id: this.componentId }, h("button", { key: '6c27edb5a9584e223f0716ae2c95cf07488a041b', class: this.getTriggerClasses(), type: "button", popoverTarget: this.variant !== 'clear' ? `${this.componentId}-popover` : undefined, popoverTargetAction: this.variant !== 'clear' ? 'toggle' : undefined, onKeyDown: this.variant === 'clear' ? this.handleKeyDown : undefined, onClick: (event) => this.handleClick(event), part: "button", "aria-expanded": this.isOpen ? 'true' : 'false', "aria-haspopup": this.variant !== 'clear' ? 'true' : undefined, "aria-controls": this.variant !== 'clear' ? `${this.componentId}-popover` : undefined }, h("span", { key: 'ef9970dc8d453d170703e90ba8690b652e11fa5c', class: "pds-filter__button-content", part: "button-content" }, this.renderIcon(), this.text && (h("span", { key: '8e71b9d19327117dbce1cf50d169699ab771d362', class: "pds-filter__button-text", part: "button-text" }, this.text)), this.renderDropdownIcon())), this.variant !== 'clear' && (h("div", { key: 'e1eb24326d93b0247db0e11700286af74b6b19c1', ref: el => this.popoverEl = el, id: `${this.componentId}-popover`, class: "pds-filter__popover", popover: "auto", part: "popover" }, h("slot", { key: '374f65b6dab21601c1bbd86cf661971a5c6d1d43' })))));
    }
    static get is() { return "pds-filter"; }
    static get encapsulation() { return "shadow"; }
    static get originalStyleUrls() {
        return {
            "$": ["pds-filter.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["pds-filter.css"]
        };
    }
    static get properties() {
        return {
            "componentId": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": true,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "A unique identifier used for the underlying component `id` attribute."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "component-id"
            },
            "variant": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "PdsFilterVariant",
                    "resolved": "\"clear\" | \"default\" | \"more\" | \"selected\"",
                    "references": {
                        "PdsFilterVariant": {
                            "location": "import",
                            "path": "./filter-interface",
                            "id": "src/components/pds-filters/pds-filter/filter-interface.ts::PdsFilterVariant"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "defaultValue",
                            "text": "'default'"
                        }],
                    "text": "The variant style of the filter trigger."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "variant",
                "defaultValue": "'default'"
            },
            "icon": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "The name of the icon to display in the trigger button.\nFor 'clear' variant, this is ignored as it always shows trash icon."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "icon"
            },
            "text": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "The text content displayed in the trigger button."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "text"
            }
        };
    }
    static get states() {
        return {
            "isOpen": {}
        };
    }
    static get events() {
        return [{
                "method": "pdsFilterOpen",
                "name": "pdsFilterOpen",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Event emitted when the filter popover is opened."
                },
                "complexType": {
                    "original": "PdsFilterOpenEventDetail",
                    "resolved": "PdsFilterOpenEventDetail",
                    "references": {
                        "PdsFilterOpenEventDetail": {
                            "location": "import",
                            "path": "./filter-interface",
                            "id": "src/components/pds-filters/pds-filter/filter-interface.ts::PdsFilterOpenEventDetail"
                        }
                    }
                }
            }, {
                "method": "pdsFilterClose",
                "name": "pdsFilterClose",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Event emitted when the filter popover is closed."
                },
                "complexType": {
                    "original": "PdsFilterCloseEventDetail",
                    "resolved": "PdsFilterCloseEventDetail",
                    "references": {
                        "PdsFilterCloseEventDetail": {
                            "location": "import",
                            "path": "./filter-interface",
                            "id": "src/components/pds-filters/pds-filter/filter-interface.ts::PdsFilterCloseEventDetail"
                        }
                    }
                }
            }, {
                "method": "pdsFilterClear",
                "name": "pdsFilterClear",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Event emitted when the clear variant is clicked."
                },
                "complexType": {
                    "original": "PdsFilterClearEventDetail",
                    "resolved": "PdsFilterClearEventDetail",
                    "references": {
                        "PdsFilterClearEventDetail": {
                            "location": "import",
                            "path": "./filter-interface",
                            "id": "src/components/pds-filters/pds-filter/filter-interface.ts::PdsFilterClearEventDetail"
                        }
                    }
                }
            }];
    }
    static get methods() {
        return {
            "showFilter": {
                "complexType": {
                    "signature": "() => Promise<void>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Opens the filter popover programmatically.\nNote: Clear variant does not support popover functionality.",
                    "tags": []
                }
            },
            "hideFilter": {
                "complexType": {
                    "signature": "() => Promise<void>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Closes the filter popover programmatically.\nNote: Clear variant does not support popover functionality.",
                    "tags": []
                }
            }
        };
    }
    static get elementRef() { return "el"; }
    static get listeners() {
        return [{
                "name": "resize",
                "method": "handleWindowResize",
                "target": "window",
                "capture": false,
                "passive": true
            }, {
                "name": "scroll",
                "method": "handleWindowScroll",
                "target": "window",
                "capture": false,
                "passive": true
            }, {
                "name": "toggle",
                "method": "handlePopoverToggle",
                "target": "document",
                "capture": false,
                "passive": false
            }, {
                "name": "click",
                "method": "handleDocumentClick",
                "target": "document",
                "capture": false,
                "passive": false
            }, {
                "name": "keydown",
                "method": "handleEscapeKey",
                "target": "document",
                "capture": false,
                "passive": false
            }];
    }
}
//# sourceMappingURL=pds-filter.js.map
