import { h, } from "@stencil/core";
import { isNestedInIfxComponent } from "../..//shared/utils/dom-utils";
import { detectFramework } from "../..//shared/utils/framework-detection";
import { trackComponent } from "../../shared/utils/tracking";
export class Pagination {
    el;
    /** Emitted when the current page changes */
    ifxPageChange;
    /** Emitted when the items-per-page value changes */
    ifxItemsPerPageChange;
    /** The current page number passed from the outside */
    currentPage = 1;
    /** Wether to display the items-per-page selector */
    showItemsPerPage = true;
    showAllItems = false;
    internalPage = 1;
    internalItemsPerPage = 10;
    numberOfPages = [];
    /** Total number of items to paginate */
    total = 1;
    /** Items-per-page options */
    itemsPerPage;
    filteredItemsPerPage = [];
    visiblePages = [];
    itemsPerPageLabel = "Results per Page";
    CLASS_DISABLED = "disabled";
    CLASS_ACTIVE = "active";
    prevInternalPage;
    watchTotalHandler() {
        if (this.showAllItems) {
            this.internalItemsPerPage = this.total;
        }
        this.calculateNumberOfPages();
        this.updateVisiblePages();
    }
    currentPageWatcher(newVal) {
        this.internalPage = Math.max(1, Math.min(newVal, this.numberOfPages.length));
        this.calculateNumberOfPages();
        this.updateVisiblePages();
    }
    setItemsPerPage(e) {
        const value = e.detail?.value || e.detail?.label;
        if (value === "all") {
            if (this.showAllItems)
                return;
            this.showAllItems = true;
            this.internalItemsPerPage = this.total;
            this.internalPage = 1;
            this.calculateNumberOfPages();
            this.updateVisiblePages();
            this.handleEventEmission();
            return;
        }
        this.showAllItems = false;
        const newItemsPerPage = parseInt(value) || 10;
        if (newItemsPerPage === this.internalItemsPerPage) {
            return;
        }
        this.internalItemsPerPage = newItemsPerPage;
        this.internalPage = 1;
        this.calculateNumberOfPages();
        this.updateVisiblePages();
        this.handleEventEmission();
    }
    emitItemsPerPage(e) {
        this.ifxItemsPerPageChange.emit(e.detail.label);
    }
    async componentDidLoad() {
        if (this.showItemsPerPage) {
            const select = this.el.shadowRoot.querySelector("#itemsPerPageSelect");
            if (select) {
                select.addEventListener("ifxSelect", (e) => this.emitItemsPerPage(e));
            }
        }
        // Add resize listener to update pagination on screen size changes
        window.addEventListener("resize", this.handleResize);
        if (!isNestedInIfxComponent(this.el)) {
            const framework = detectFramework();
            trackComponent("ifx-pagination", await framework);
        }
        this.initPagination();
    }
    disconnectedCallback() {
        if (this.showItemsPerPage) {
            const select = this.el.shadowRoot.querySelector("#itemsPerPageSelect");
            if (select) {
                select.removeEventListener("ifxSelect", (e) => this.emitItemsPerPage(e));
            }
        }
        // Remove resize listener
        window.removeEventListener("resize", this.handleResize);
        // Clear any pending resize timeout
        if (this.resizeTimeout) {
            clearTimeout(this.resizeTimeout);
        }
    }
    updateVisiblePages() {
        // Check if screen is mobile (< 400px)
        const isMobile = window.innerWidth < 400;
        const totalPages = this.numberOfPages.length;
        const current = this.internalPage;
        let pages = [];
        if (isMobile) {
            // Mobile logic: maximum 5 elements
            if (totalPages <= 5) {
                pages = [...this.numberOfPages];
            }
            else {
                // Always show first page
                pages.push(1);
                if (current <= 2) {
                    // Show: 1 2 3 … 10 (for pages 1 and 2)
                    pages.push(2, 3, "...", totalPages);
                }
                else if (current >= totalPages - 1) {
                    // Show: 1 … 23 24 25 (for last 2 pages only)
                    pages.push("...", totalPages - 2, totalPages - 1, totalPages);
                }
                else {
                    // Show: 1 … 5 … 10 (for middle pages, including page 3 and third-to-last page)
                    pages.push("...", current, "...", totalPages);
                }
            }
        }
        else {
            // Desktop logic: maximum 7 elements
            const buffer = 2;
            if (totalPages <= 7) {
                pages = [...this.numberOfPages];
            }
            else {
                // Always show first page
                pages.push(1);
                // Determine the range around current page
                let start = Math.max(2, current - buffer);
                let end = Math.min(totalPages - 1, current + buffer);
                // Adjust range to ensure we show enough pages
                // If we're close to the beginning, extend the end
                if (current <= 4) {
                    start = 2;
                    end = Math.min(totalPages - 1, 5);
                }
                // If we're close to the end, extend the start
                else if (current >= totalPages - 3) {
                    start = Math.max(2, totalPages - 4);
                    end = totalPages - 1;
                }
                // For middle pages, show current +/- 1
                else {
                    start = current - 1;
                    end = current + 1;
                }
                // Add ellipsis before the range if there's a gap
                if (start > 2) {
                    pages.push("...");
                }
                // Add the range of pages
                for (let i = start; i <= end; i++) {
                    pages.push(i);
                }
                // Add ellipsis after the range if there's a gap
                if (end < totalPages - 1) {
                    pages.push("...");
                }
                // Always show last page
                pages.push(totalPages);
            }
        }
        this.visiblePages = pages;
    }
    calculateNumberOfPages() {
        if (this.showAllItems) {
            this.numberOfPages = [1];
            this.internalPage = 1;
            return;
        }
        const totalPages = Math.ceil(this.total / this.internalItemsPerPage);
        this.numberOfPages = Array.from({ length: totalPages }, (_, i) => i + 1);
        this.internalPage = Math.max(1, Math.min(this.currentPage, totalPages));
    }
    filterOptionsArray() {
        const items = typeof this.itemsPerPage === "string"
            ? JSON.parse(this.itemsPerPage)
            : this.itemsPerPage;
        this.filteredItemsPerPage = items.map((item) => ({
            ...item,
            label: item.label || item.value,
        }));
    }
    componentWillLoad() {
        this.filterOptionsArray();
        const selectedOption = this.filteredItemsPerPage.find((option) => option.selected);
        if (selectedOption) {
            const value = selectedOption.value || selectedOption.label;
            if (value === "all") {
                this.showAllItems = true;
                this.internalItemsPerPage = this.total;
            }
            else {
                this.internalItemsPerPage = Number(selectedOption.value);
            }
        }
        else if (this.filteredItemsPerPage.length > 0) {
            const firstItem = this.filteredItemsPerPage[0];
            const value = firstItem.value || firstItem.label;
            if (value === "all") {
                this.showAllItems = true;
                this.internalItemsPerPage = this.total;
            }
            else {
                this.internalItemsPerPage = Number(firstItem.value);
            }
        }
        this.calculateNumberOfPages();
        this.internalPage = Math.max(1, Math.min(this.currentPage, this.numberOfPages.length));
        this.updateVisiblePages();
    }
    componentWillUpdate() {
        if (this.prevInternalPage !== this.internalPage) {
            this.updateVisiblePages();
            this.prevInternalPage = this.internalPage;
        }
    }
    componentDidUpdate() {
        this.initPagination();
    }
    handleEventEmission() {
        this.ifxPageChange.emit({
            currentPage: this.internalPage,
            totalPages: this.numberOfPages.length,
            itemsPerPage: this.internalItemsPerPage,
        });
    }
    initPagination() {
        const pagination = this.el.shadowRoot.querySelector(".pagination");
        if (!pagination)
            return;
        const updateButtons = () => {
            const prev = pagination.querySelector(".prev");
            const next = pagination.querySelector(".next");
            if (prev) {
                prev.disabled = this.internalPage === 1;
                prev.classList.toggle(this.CLASS_DISABLED, this.internalPage === 1);
            }
            if (next) {
                next.disabled = this.internalPage === this.numberOfPages.length;
                next.classList.toggle(this.CLASS_DISABLED, this.internalPage === this.numberOfPages.length);
            }
        };
        pagination.querySelectorAll("li").forEach((li) => {
            li.removeEventListener("click", this.handlePageClick);
            li.addEventListener("click", this.handlePageClick);
        });
        updateButtons();
    }
    handlePageClick = (e) => {
        const li = e.currentTarget;
        const page = parseInt(li.dataset.page);
        if (!isNaN(page))
            this.changePage(page);
    };
    handleResize = () => {
        // Debounce resize events to prevent excessive calls
        clearTimeout(this.resizeTimeout);
        this.resizeTimeout = setTimeout(() => {
            this.updateVisiblePages();
        }, 100);
    };
    resizeTimeout;
    changePage(newPage) {
        newPage = Math.max(1, Math.min(newPage, this.numberOfPages.length));
        if (newPage === this.internalPage)
            return;
        this.internalPage = newPage;
        this.handleEventEmission();
        this.initPagination();
    }
    render() {
        return (h("div", { key: 'a61d4169b15fc02f4f4fdc26b3248fc75a0d4ce1', class: "container" }, this.showItemsPerPage && (h("div", { key: '980abee57e9d8bb70b849a55f08727ea2cc9eec2', class: "items__per-page-wrapper" }, h("div", { key: '4f45bba5e76ae694c6769a400cabb098205ad2ff', class: "items__per-page-label" }, this.itemsPerPageLabel), h("div", { key: '4deba5b390790ed678da6b21ec5495296a6ae54f', class: "items__per-page-field" }, h("ifx-select", { key: 'a1c5883263b69c7826f1bd0c41e9cd418d793d4e', id: "itemsPerPageSelect", placeholder: "false", "show-search": "false", value: undefined, disabled: false, error: false, size: "s", options: this.filteredItemsPerPage, "placeholder-value": "Select" })))), h("div", { key: '8531ae8613e046bc1f89fd5a557a78c2824c0dfb', class: "items__total-wrapper" }, h("div", { key: '752adc6c57bf3dedc96a28bc4c20bf805d05e68d', class: "pagination" }, h("ifx-icon-button", { key: '18f63188e9f43a9cfece7b4cf456277ee52840e1', class: "prev", icon: "arrow-left-16", "aria-label": "Previous Page", onClick: () => this.changePage(this.internalPage - 1), variant: "secondary" }), h("ol", { key: 'aabb324178481bc572cc13feb86241c5c0baf4da' }, this.visiblePages.map((page, i) => typeof page === "number" ? (h("li", { key: `page-${page}`, class: { [this.CLASS_ACTIVE]: page === this.internalPage }, "data-page": page }, h("span", { class: "page__button", role: "button", tabindex: "0", "aria-current": page === this.internalPage ? "page" : undefined, "aria-label": `Page ${page}`, onClick: () => this.changePage(page), onKeyDown: (e) => (e.key === "Enter" || e.key === " ") &&
                this.changePage(page) }, page))) : (h("li", { class: "ellipsis", key: `ellipsis-${i}` }, h("span", { "aria-hidden": "true" }, "..."))))), h("ifx-icon-button", { key: '12003fc5ccee8131b9b0ae745178d7f2634a9051', class: "next", icon: "arrow-right-16", "aria-label": "Next Page", onClick: () => this.changePage(this.internalPage + 1), variant: "secondary" })))));
    }
    static get is() { return "ifx-pagination"; }
    static get encapsulation() { return "shadow"; }
    static get originalStyleUrls() {
        return {
            "$": ["pagination.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["pagination.css"]
        };
    }
    static get properties() {
        return {
            "currentPage": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The current page number passed from the outside"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "current-page",
                "defaultValue": "1"
            },
            "showItemsPerPage": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Wether to display the items-per-page selector"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "show-items-per-page",
                "defaultValue": "true"
            },
            "total": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Total number of items to paginate"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "total",
                "defaultValue": "1"
            },
            "itemsPerPage": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "any[] | string",
                    "resolved": "any[] | string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Items-per-page options"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "items-per-page"
            },
            "itemsPerPageLabel": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "items-per-page-label",
                "defaultValue": "\"Results per Page\""
            }
        };
    }
    static get states() {
        return {
            "showAllItems": {},
            "internalPage": {},
            "internalItemsPerPage": {},
            "numberOfPages": {},
            "filteredItemsPerPage": {},
            "visiblePages": {}
        };
    }
    static get events() {
        return [{
                "method": "ifxPageChange",
                "name": "ifxPageChange",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the current page changes"
                },
                "complexType": {
                    "original": "any",
                    "resolved": "any",
                    "references": {}
                }
            }, {
                "method": "ifxItemsPerPageChange",
                "name": "ifxItemsPerPageChange",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the items-per-page value changes"
                },
                "complexType": {
                    "original": "any",
                    "resolved": "any",
                    "references": {}
                }
            }];
    }
    static get elementRef() { return "el"; }
    static get watchers() {
        return [{
                "propName": "total",
                "methodName": "watchTotalHandler"
            }, {
                "propName": "currentPage",
                "methodName": "currentPageWatcher"
            }];
    }
    static get listeners() {
        return [{
                "name": "ifxSelect",
                "method": "setItemsPerPage",
                "target": undefined,
                "capture": false,
                "passive": false
            }];
    }
}
