import { Host, h, } from "@stencil/core";
import paginationNextPrevious from "../../assets/pagination-next-previous.svg";
import paginationFirstLast from "../../assets/pagination-first-last.svg";
import { onComponentRequiredPropUndefined, removeDisabledFalse, } from "../../utils/helpers";
export class Pagination {
    constructor() {
        this.endEllipsis = false;
        this.endItems = [];
        this.midItems = [];
        this.startEllipsis = false;
        this.startItems = [];
        /**
         * The accessible label of the pagination component to provide context for screen reader users.
         */
        this.accessibleLabel = "Pagination Navigation";
        /**
         * The number of pages displayed adjacent to the current page when using 'complex' type pagination. Accepted values are 0, 1 & 2.
         */
        this.adjacentPageCount = 1;
        /**
         * The number of pages displayed as boundary items to the current page when using 'complex' type pagination. Accepted values are 0, 1 & 2.
         */
        this.boundaryPageCount = 1;
        /**
         * The default page to display.
         */
        this.defaultPage = 1;
        /**
         * If `true`, the pagination will not allow interaction.
         */
        this.disabled = false;
        /**
         * If `true`, the current page of the simple pagination will not be displayed.
         */
        this.hideCurrentPage = false;
        /**
         * If `true`, the first and last page buttons will not be displayed.
         */
        this.hideFirstAndLastPageButton = false;
        /**
         * The label for the pagination item (applicable when simple pagination is being used).
         */
        this.label = "Page";
        /**
         * If `true`, the pagination will display as black in the light theme, and white in dark theme.
         */
        this.monochrome = false;
        /**
         * Sets the theme color to the dark or light theme color. "inherit" will set the color based on the system settings or ic-theme component.
         */
        this.theme = "inherit";
        /**
         * The type of pagination to be used.
         */
        this.type = "simple";
        /**
         * The current page displayed by the pagination.
         */
        this.currentPage = this.defaultPage;
        this.handleClickFirst = () => {
            this.currentPage = 1;
            this.icPageChange.emit({ value: this.currentPage });
        };
        this.handleClickPrevious = () => {
            this.currentPage--;
            this.icPageChange.emit({ value: this.currentPage });
        };
        this.handleClickNext = () => {
            this.currentPage++;
            this.icPageChange.emit({ value: this.currentPage });
        };
        this.handleClickLast = () => {
            this.currentPage = this.pages;
            this.icPageChange.emit({ value: this.currentPage });
        };
        // button rendering abstracted from component render methods for clarity
        this.firstButton = () => {
            return (h("ic-button", { id: "first-page-button", "aria-label": "Go to first page", theme: this.theme, onClick: this.handleClickFirst, class: "page-button first-last", disabled: this.currentPage === 1 || this.disabled, variant: "icon-tertiary", monochrome: this.theme == "light" || this.theme == "dark", innerHTML: paginationFirstLast }));
        };
        this.previousButton = () => {
            return (h("ic-button", { id: "previous-page-button", "aria-label": "Go to previous page", theme: this.theme, onClick: this.handleClickPrevious, class: "page-button next-previous flip", disabled: this.currentPage === 1 || this.disabled, variant: "icon-tertiary", monochrome: this.theme == "light" || this.theme == "dark", innerHTML: paginationNextPrevious }));
        };
        this.nextButton = () => {
            return (h("ic-button", { id: "next-page-button", "aria-label": "Go to next page", theme: this.theme, onClick: this.handleClickNext, class: "page-button next-previous", disabled: this.currentPage === this.pages || this.disabled, variant: "icon-tertiary", monochrome: this.theme == "light" || this.theme == "dark", innerHTML: paginationNextPrevious }));
        };
        this.lastButton = () => {
            return (h("ic-button", { id: "last-page-button", "aria-label": "Go to last page", theme: this.theme, onClick: this.handleClickLast, class: "page-button first-last flip", disabled: this.currentPage === this.pages || this.disabled, variant: "icon-tertiary", monochrome: this.theme == "light" || this.theme == "dark", innerHTML: paginationFirstLast }));
        };
        this.renderStartEllipsis = () => {
            return (h("ic-pagination-item", { theme: this.theme, monochrome: this.monochrome, type: "ellipsis", id: "start-ellipsis", disabled: this.disabled }));
        };
        this.renderEndEllipsis = () => {
            return (h("ic-pagination-item", { theme: this.theme, monochrome: this.monochrome, type: "ellipsis", id: "end-ellipsis", disabled: this.disabled }));
        };
        this.renderStartItems = () => {
            return this.startItems.map((page) => {
                return (h("ic-pagination-item", { theme: this.theme, monochrome: this.monochrome, selected: page === this.currentPage, id: `pagination-item-${page}`, type: "page", page: page, disabled: this.disabled }));
            });
        };
        this.renderEndItems = () => {
            return this.endItems.map((page) => {
                return (h("ic-pagination-item", { theme: this.theme, monochrome: this.monochrome, selected: page === this.currentPage, id: `pagination-item-${page}`, type: "page", page: page, disabled: this.disabled }));
            });
        };
        this.renderMiddleItems = () => {
            return this.midItems.map((page) => {
                return (h("ic-pagination-item", { theme: this.theme, monochrome: this.monochrome, selected: page === this.currentPage, id: `pagination-item-${page}`, type: "page", page: page, disabled: this.disabled }));
            });
        };
    }
    watchAdjacentPageCountHandler() {
        if (this.adjacentPageCount > 2) {
            this.adjacentPageCount = 2;
        }
    }
    watchBoundaryPageCountHandler() {
        if (this.boundaryPageCount > 2) {
            this.boundaryPageCount = 2;
        }
    }
    watchDisabledHandler() {
        removeDisabledFalse(this.disabled, this.el);
    }
    watchNumberPagesHandler() {
        this.watchPageChangeHandler();
    }
    watchTypeHandler() {
        this.watchPageChangeHandler();
    }
    watchPageChangeHandler() {
        if (this.type === "simple") {
            return;
        }
        this.startEllipsis = false;
        this.endEllipsis = false;
        this.startItems = [];
        this.endItems = [];
        this.midItems = [];
        const startItems = [];
        let startItemCount = 0;
        const endItems = [];
        let endStart = this.pages;
        const midItems = [];
        let midStart;
        let midEnd;
        let startEllipsis = false;
        let endEllipsis = false;
        if (this.pages <=
            this.boundaryPageCount * 2 + this.adjacentPageCount * 2 + 3) {
            this.startEllipsis = false;
            this.endEllipsis = false;
            for (let i = 1; i <= this.pages; i++) {
                startItems.push(i);
            }
            this.startItems = startItems;
            return;
        }
        startItemCount = this.boundaryPageCount === 0 ? 1 : this.boundaryPageCount;
        endStart =
            this.boundaryPageCount === 0
                ? this.pages
                : this.pages - this.boundaryPageCount + 1;
        if (this.currentPage <=
            this.adjacentPageCount + this.boundaryPageCount + 2) {
            startEllipsis = false;
            endEllipsis = true;
            let numItems = 2 * this.adjacentPageCount + 1;
            if (this.boundaryPageCount === 0) {
                numItems--;
            }
            midStart = startItemCount + 1;
            midEnd = midStart + numItems;
        }
        else {
            startEllipsis = true;
            if (this.currentPage >
                this.pages - (this.adjacentPageCount + this.boundaryPageCount + 2)) {
                let numItems = 2 * this.adjacentPageCount + 1;
                if (this.boundaryPageCount === 0) {
                    numItems--;
                }
                midEnd =
                    this.boundaryPageCount === 0
                        ? this.pages - 1
                        : this.pages - this.boundaryPageCount;
                midStart = midEnd - numItems;
            }
            else {
                endEllipsis = true;
                midStart = this.currentPage - this.adjacentPageCount;
                midEnd = this.currentPage + this.adjacentPageCount;
            }
        }
        //create array of start items
        if (this.boundaryPageCount > 0 ||
            (this.boundaryPageCount === 0 && startEllipsis === false)) {
            for (let i = 1; i <= startItemCount; i++) {
                startItems.push(i);
            }
        }
        //create array of end items
        if (this.boundaryPageCount > 0 ||
            (this.boundaryPageCount === 0 && endEllipsis === false)) {
            for (let i = endStart; i <= this.pages; i++) {
                endItems.push(i);
            }
        }
        //create array of mid items
        for (let i = midStart; i <= midEnd; i++) {
            midItems.push(i);
        }
        this.startEllipsis = startEllipsis;
        this.endEllipsis = endEllipsis;
        this.startItems = startItems;
        this.endItems = endItems;
        this.midItems = midItems;
    }
    componentWillLoad() {
        this.watchPageChangeHandler();
        this.watchBoundaryPageCountHandler();
        this.watchAdjacentPageCountHandler();
        removeDisabledFalse(this.disabled, this.el);
    }
    componentDidLoad() {
        onComponentRequiredPropUndefined([{ prop: this.pages, propName: "pages" }], "Pagination");
    }
    /**
     * Prevents focus lingering on a disabled element. If the currently
     * focused element is one of the back buttons (and we reach the first page),
     * move focus to "next" button, and vice versa.
     * @param ev
     */
    icPageChangeHandler(ev) {
        var _a, _b, _c;
        const shadow = (_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.shadowRoot;
        const activeEl = shadow ? shadow.activeElement : document.activeElement;
        if (!shadow || !activeEl) {
            return;
        }
        if (ev.detail.value === 1 &&
            ["first-page-button", "previous-page-button"].some((id) => id === (activeEl === null || activeEl === void 0 ? void 0 : activeEl.id))) {
            const btn = (_b = shadow.querySelector("#next-page-button").shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector("button");
            // When navigating from firstPage->lastPage or vice versa, the to-be-selected element will be disabled. wait a tick so that it can receive focus.
            setTimeout(() => btn === null || btn === void 0 ? void 0 : btn.focus(), 10);
        }
        else if (ev.detail.value === this.pages &&
            ["last-page-button", "next-page-button"].some((id) => id === (activeEl === null || activeEl === void 0 ? void 0 : activeEl.id))) {
            const btn = (_c = shadow.querySelector("#previous-page-button").shadowRoot) === null || _c === void 0 ? void 0 : _c.querySelector("button");
            setTimeout(() => btn === null || btn === void 0 ? void 0 : btn.focus(), 10);
        }
    }
    paginationItemClickHandler(ev) {
        const page = ev.detail.page;
        this.currentPage = page;
        this.icPageChange.emit({ value: this.currentPage });
    }
    /**
     * Sets the currently displayed page.
     * @param {number} page The page number to set as the current page
     */
    async setCurrentPage(page) {
        if (typeof page === "number" && page > 0 && page <= this.pages) {
            this.currentPage = page;
        }
        else {
            console.error("Current page must be a number greater than zero but less than or equal to the total number of pages");
        }
    }
    render() {
        const { type, currentPage, hideCurrentPage, disabled, hideFirstAndLastPageButton, label, theme, monochrome, } = this;
        return (h(Host, { key: 'cefb3137892be2304c041ca32ca118268f8ccb07', class: {
                [`ic-theme-${theme}`]: theme !== "inherit",
                ["ic-pagination-monochrome"]: !!monochrome,
            } }, type === "simple" && (h("nav", { key: '9a1d8230be41cb26b31bb8af066a32e9b64e0d89', class: {
                ["disabled"]: !!disabled,
            }, role: "navigation", "aria-label": this.accessibleLabel }, hideFirstAndLastPageButton ? null : this.firstButton(), this.previousButton(), h("ic-pagination-item", { key: '577b9b9894ce6ddc2cf02381729600e4284e8912', theme: this.theme, monochrome: this.monochrome, type: "simple-current", page: currentPage, label: label, class: { ["hide-current-page"]: !!hideCurrentPage }, disabled: disabled }), this.nextButton(), hideFirstAndLastPageButton ? null : this.lastButton())), type === "complex" && (h("nav", { key: '317d507ca76549e3c980ced7d01332504738a102', class: {
                ["disabled"]: !!disabled,
            }, role: "navigation", "aria-label": this.accessibleLabel }, hideFirstAndLastPageButton ? null : this.firstButton(), this.previousButton(), this.renderStartItems(), this.startEllipsis && this.renderStartEllipsis(), this.renderMiddleItems(), this.endEllipsis && this.renderEndEllipsis(), this.renderEndItems(), this.nextButton(), hideFirstAndLastPageButton ? null : this.lastButton())), type === "complex" && (h("span", { key: '6d3a5778f4704dd5ec1e74bf2cf236143c5f7e7c', class: "sr-only", "aria-live": "polite" }, "Page ", this.currentPage))));
    }
    static get is() { return "ic-pagination"; }
    static get encapsulation() { return "shadow"; }
    static get originalStyleUrls() {
        return {
            "$": ["ic-pagination.css"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["ic-pagination.css"]
        };
    }
    static get properties() {
        return {
            "accessibleLabel": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "The accessible label of the pagination component to provide context for screen reader users."
                },
                "getter": false,
                "setter": false,
                "attribute": "accessible-label",
                "reflect": false,
                "defaultValue": "\"Pagination Navigation\""
            },
            "adjacentPageCount": {
                "type": "number",
                "mutable": true,
                "complexType": {
                    "original": "number",
                    "resolved": "number | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "The number of pages displayed adjacent to the current page when using 'complex' type pagination. Accepted values are 0, 1 & 2."
                },
                "getter": false,
                "setter": false,
                "attribute": "adjacent-page-count",
                "reflect": false,
                "defaultValue": "1"
            },
            "boundaryPageCount": {
                "type": "number",
                "mutable": true,
                "complexType": {
                    "original": "number",
                    "resolved": "number | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "The number of pages displayed as boundary items to the current page when using 'complex' type pagination. Accepted values are 0, 1 & 2."
                },
                "getter": false,
                "setter": false,
                "attribute": "boundary-page-count",
                "reflect": false,
                "defaultValue": "1"
            },
            "defaultPage": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "The default page to display."
                },
                "getter": false,
                "setter": false,
                "attribute": "default-page",
                "reflect": false,
                "defaultValue": "1"
            },
            "disabled": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "If `true`, the pagination will not allow interaction."
                },
                "getter": false,
                "setter": false,
                "attribute": "disabled",
                "reflect": false,
                "defaultValue": "false"
            },
            "hideCurrentPage": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "If `true`, the current page of the simple pagination will not be displayed."
                },
                "getter": false,
                "setter": false,
                "attribute": "hide-current-page",
                "reflect": false,
                "defaultValue": "false"
            },
            "hideFirstAndLastPageButton": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "If `true`, the first and last page buttons will not be displayed."
                },
                "getter": false,
                "setter": false,
                "attribute": "hide-first-and-last-page-button",
                "reflect": false,
                "defaultValue": "false"
            },
            "label": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "The label for the pagination item (applicable when simple pagination is being used)."
                },
                "getter": false,
                "setter": false,
                "attribute": "label",
                "reflect": false,
                "defaultValue": "\"Page\""
            },
            "monochrome": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "If `true`, the pagination will display as black in the light theme, and white in dark theme."
                },
                "getter": false,
                "setter": false,
                "attribute": "monochrome",
                "reflect": false,
                "defaultValue": "false"
            },
            "pages": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": true,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The total number of pages."
                },
                "getter": false,
                "setter": false,
                "attribute": "pages",
                "reflect": false
            },
            "theme": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "IcThemeMode",
                    "resolved": "\"dark\" | \"inherit\" | \"light\" | undefined",
                    "references": {
                        "IcThemeMode": {
                            "location": "import",
                            "path": "../../utils/types",
                            "id": "src/utils/types.ts::IcThemeMode"
                        }
                    }
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Sets the theme color to the dark or light theme color. \"inherit\" will set the color based on the system settings or ic-theme component."
                },
                "getter": false,
                "setter": false,
                "attribute": "theme",
                "reflect": false,
                "defaultValue": "\"inherit\""
            },
            "type": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "IcPaginationTypes",
                    "resolved": "\"complex\" | \"simple\" | undefined",
                    "references": {
                        "IcPaginationTypes": {
                            "location": "import",
                            "path": "./ic-pagination.types",
                            "id": "src/components/ic-pagination/ic-pagination.types.ts::IcPaginationTypes"
                        }
                    }
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "The type of pagination to be used."
                },
                "getter": false,
                "setter": false,
                "attribute": "type",
                "reflect": false,
                "defaultValue": "\"simple\""
            },
            "currentPage": {
                "type": "number",
                "mutable": true,
                "complexType": {
                    "original": "number",
                    "resolved": "number | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "The current page displayed by the pagination."
                },
                "getter": false,
                "setter": false,
                "attribute": "current-page",
                "reflect": false,
                "defaultValue": "this.defaultPage"
            }
        };
    }
    static get states() {
        return {
            "endEllipsis": {},
            "endItems": {},
            "midItems": {},
            "startEllipsis": {},
            "startItems": {}
        };
    }
    static get events() {
        return [{
                "method": "icPageChange",
                "name": "icPageChange",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when a page is selected."
                },
                "complexType": {
                    "original": "IcChangeEventDetail",
                    "resolved": "IcChangeEventDetail",
                    "references": {
                        "IcChangeEventDetail": {
                            "location": "import",
                            "path": "./ic-pagination.types",
                            "id": "src/components/ic-pagination/ic-pagination.types.ts::IcChangeEventDetail"
                        }
                    }
                }
            }];
    }
    static get methods() {
        return {
            "setCurrentPage": {
                "complexType": {
                    "signature": "(page: number) => Promise<void>",
                    "parameters": [{
                            "name": "page",
                            "type": "number",
                            "docs": "The page number to set as the current page"
                        }],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Sets the currently displayed page.",
                    "tags": [{
                            "name": "param",
                            "text": "page The page number to set as the current page"
                        }]
                }
            }
        };
    }
    static get elementRef() { return "el"; }
    static get watchers() {
        return [{
                "propName": "adjacentPageCount",
                "methodName": "watchAdjacentPageCountHandler"
            }, {
                "propName": "boundaryPageCount",
                "methodName": "watchBoundaryPageCountHandler"
            }, {
                "propName": "disabled",
                "methodName": "watchDisabledHandler"
            }, {
                "propName": "pages",
                "methodName": "watchNumberPagesHandler"
            }, {
                "propName": "type",
                "methodName": "watchTypeHandler"
            }, {
                "propName": "currentPage",
                "methodName": "watchPageChangeHandler"
            }];
    }
    static get listeners() {
        return [{
                "name": "icPageChange",
                "method": "icPageChangeHandler",
                "target": undefined,
                "capture": false,
                "passive": false
            }, {
                "name": "paginationItemClick",
                "method": "paginationItemClickHandler",
                "target": undefined,
                "capture": false,
                "passive": false
            }];
    }
}
//# sourceMappingURL=ic-pagination.js.map
