import { Host, h, } from "@stencil/core";
import { createPopper } from "@popperjs/core";
import { onComponentRequiredPropUndefined } from "../../utils/helpers";
export class Tooltip {
    constructor() {
        this.delayedHideEvents = ["mouseleave"];
        this.dialogOverflow = false;
        this.instantHideEvents = ["focusout"];
        this.mouseOverTool = false;
        this.persistTooltip = false;
        this.onDialog = false;
        this.showEvents = [
            !this.disableHover && "mouseenter",
            !this.disableHover && "focusin",
            !this.disableClick && "click",
        ];
        /**
         * If `true`, the tooltip will not be displayed on click, it will require hover or using the display method.
         */
        this.disableClick = false;
        /**
         * If `true`, the tooltip will not be displayed on hover, it will require a click.
         */
        this.disableHover = false;
        /**
         * The position of the tooltip in relation to the parent element.
         */
        this.placement = "bottom";
        /**
         * @internal Sets the tooltip to aria-hidden, when used as part of components that are already announced.
         */
        this.silent = false;
        /**
         * Sets the tooltip to the dark or light theme colors. "inherit" will set the color based on the system settings or ic-theme component.
         */
        this.theme = "inherit";
        this.popperProps = {};
        this.getTooltipTranslate = (dialogEl) => {
            const child = this.el.children[0].getBoundingClientRect();
            let tooltipX;
            let tooltipY;
            switch (this.placement) {
                case "bottom":
                    tooltipX = child.left - dialogEl.left - 0.5 * child.width;
                    tooltipY = child.bottom - dialogEl.top;
                    break;
                case "bottom-start":
                    tooltipX = child.left - dialogEl.left;
                    tooltipY = child.bottom - dialogEl.top;
                    break;
                case "bottom-end":
                    tooltipX = child.right - dialogEl.right;
                    tooltipY = child.bottom - dialogEl.top;
                    break;
                case "top":
                    tooltipX = child.left - dialogEl.left - 0.5 * child.width;
                    tooltipY = child.top - dialogEl.bottom;
                    break;
                case "top-start":
                    tooltipX = child.left - dialogEl.left;
                    tooltipY = child.top - dialogEl.bottom;
                    break;
                case "top-end":
                    tooltipX = child.right - dialogEl.right;
                    tooltipY = child.top - dialogEl.bottom;
                    break;
                case "left":
                case "left-start":
                    tooltipX = child.right - dialogEl.right - child.width;
                    tooltipY = child.bottom - dialogEl.top - child.height;
                    break;
                case "left-end":
                    tooltipX = child.right - dialogEl.right - child.width;
                    tooltipY = child.top - dialogEl.bottom + child.height;
                    break;
                case "right":
                case "right-start":
                    tooltipX = child.left - dialogEl.left + child.width;
                    tooltipY = child.bottom - dialogEl.top - child.height;
                    break;
                case "right-end":
                    tooltipX = child.left - dialogEl.left + child.width;
                    tooltipY = child.top - dialogEl.bottom + child.height;
                    break;
            }
            if (this.dialogOverflow && tooltipX && tooltipX < 0) {
                if (this.placement.includes("top") ||
                    this.placement.includes("bottom")) {
                    this.toolTip.style.setProperty("--tooltip-arrow-translate", `${tooltipX}px`);
                    tooltipX = child.left - dialogEl.left;
                }
                if (this.placement.includes("left")) {
                    this.placement = "right";
                    tooltipX = child.left - dialogEl.left + child.width;
                }
            }
            this.toolTip.style.setProperty("--tooltip-translate-x", `${tooltipX}px`);
            this.toolTip.style.setProperty("--tooltip-translate-y", `${tooltipY}px`);
        };
        this.show = () => {
            var _a, _b, _c;
            if (this.label) {
                this.toolTip.setAttribute("data-show", "");
                if (this.onDialog) {
                    this.el.classList.add("on-dialog");
                    const dialogEl = (_c = (_b = (_a = this.icDialogEl) === null || _a === void 0 ? void 0 : _a.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector("dialog")) === null || _c === void 0 ? void 0 : _c.getBoundingClientRect();
                    dialogEl && this.getTooltipTranslate(dialogEl);
                }
                this.popperInstance = createPopper(this.el, this.toolTip, Object.assign({ placement: this.placement, modifiers: [
                        {
                            name: "offset",
                            options: {
                                offset: [0, 10],
                            },
                        },
                        {
                            name: "arrow",
                            options: {
                                element: this.arrow,
                            },
                        },
                        {
                            name: "eventListeners",
                            options: { scroll: false, resize: false },
                        },
                    ] }, this.popperProps));
            }
            else {
                console.warn(`Tooltip can't display without prop 'label' set`);
            }
        };
        this.hide = () => {
            this.toolTip.removeAttribute("data-show");
            this.persistTooltip = false;
            if (this.popperInstance !== undefined) {
                this.popperInstance.destroy();
            }
        };
        this.checkCloseTooltip = () => {
            setTimeout(() => {
                if (!this.mouseOverTool && !this.persistTooltip) {
                    this.hide();
                }
            }, 100);
        };
        this.mouseEnterTooltip = () => {
            this.mouseOverTool = true;
        };
        this.mouseLeaveTooltip = () => {
            this.mouseOverTool = false;
            this.checkCloseTooltip();
        };
        this.handleKeyDown = (event) => {
            if (event.key === "Escape" && !this.persistTooltip) {
                this.hide();
            }
        };
        this.manageEventListeners = (action) => {
            const method = action === "add" ? "addEventListener" : "removeEventListener";
            this.showEvents.forEach((event) => {
                if (event) {
                    this.el[method](event, this.show);
                    if (this.toolTip !== undefined) {
                        this.toolTip[method](event, this.mouseEnterTooltip);
                    }
                }
            });
            if (!this.persistTooltip) {
                this.instantHideEvents.forEach((event) => {
                    this.el[method](event, this.hide);
                });
            }
            this.delayedHideEvents.forEach((event) => {
                this.el[method](event, this.checkCloseTooltip);
                if (this.toolTip !== undefined) {
                    this.toolTip[method](event, this.mouseLeaveTooltip);
                }
            });
            document[method]("keydown", this.handleKeyDown);
        };
        this.updateTooltipEvents = () => {
            this.manageEventListeners("remove");
            this.showEvents = [
                !this.disableHover && "mouseenter",
                !this.disableHover && "focusin",
                !this.disableClick && "click",
            ];
            this.manageEventListeners("add");
        };
    }
    watchDisableClickHandler() {
        if (this.disableClick) {
            this.hide();
        }
        this.updateTooltipEvents();
    }
    watchDisableHoverHandler() {
        if (this.disableHover) {
            this.hide();
        }
        this.updateTooltipEvents();
    }
    /**
     * @internal This method allows props to be added to the PopperJS createPopper instance outside of tooltip
     * @param props object - createPopper props set externally
     */
    async setExternalPopperProps(props) {
        this.popperProps = props;
    }
    disconnectedCallback() {
        this.manageEventListeners("remove");
        if (this.popperInstance !== undefined) {
            this.popperInstance.destroy();
        }
    }
    componentDidLoad() {
        var _a;
        this.manageEventListeners("add");
        this.icDialogEl = this.el.closest("ic-dialog");
        this.dialogOverflow =
            ((_a = this.icDialogEl) === null || _a === void 0 ? void 0 : _a.getAttribute("data-overflow")) === "true";
        this.onDialog = this.icDialogEl !== null;
        onComponentRequiredPropUndefined([{ prop: this.label, propName: "label" }], "Tooltip");
    }
    componentDidRender() {
        var _a;
        const typographyEl = (_a = this.el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector(".ic-tooltip-container > ic-typography");
        this.maxLines &&
            this.maxLines > 0 &&
            (typographyEl === null || typographyEl === void 0 ? void 0 : typographyEl.setAttribute("style", `--truncation-max-lines: ${this.maxLines}`));
    }
    /**
     * Method to programmatically show/hide the tooltip without needing to interact with an anchor element
     * @param show Whether to show or hide the tooltip
     * @param persistTooltip Whether the tooltip should stay on the screen when actions are performed that would previously dismiss the tooltip, such as on hover
     */
    async displayTooltip(show, persistTooltip) {
        this.persistTooltip = !!persistTooltip;
        show ? this.show() : this.hide();
    }
    /**
     * @internal Method to return if tooltip is currently visible.
     */
    async isTooltipVisible() {
        return Promise.resolve(this.toolTip.hasAttribute("data-show"));
    }
    render() {
        const { label, maxLines, silent, theme } = this;
        return (h(Host, { key: '6e9449deb13ab672b4b9c5a637b406e4bbbf01cf', class: {
                "ic-tooltip": true,
                [`ic-theme-${theme}`]: theme !== "inherit",
            } }, h("div", { key: '85eced68333b24b831affc67ddd6e19a1142a1da', ref: (el) => (this.toolTip = el), role: "tooltip", class: "ic-tooltip-container", "aria-hidden": `${silent}` }, h("ic-typography", { key: 'c8b2727b200dc1f409332fa1eb362600fdf50334', maxLines: maxLines, variant: "caption" }, label), h("div", { key: '452bc4142b7ef38d95883f93ccc2550228cd1ae8', ref: (el) => (this.arrow = el), class: "ic-tooltip-arrow" })), h("slot", { key: '14ca9939bf600654b87b750ff43c02fd20bafd56' })));
    }
    static get is() { return "ic-tooltip"; }
    static get encapsulation() { return "shadow"; }
    static get originalStyleUrls() {
        return {
            "$": ["ic-tooltip.css"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["ic-tooltip.css"]
        };
    }
    static get properties() {
        return {
            "disableClick": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "If `true`, the tooltip will not be displayed on click, it will require hover or using the display method."
                },
                "getter": false,
                "setter": false,
                "attribute": "disable-click",
                "reflect": false,
                "defaultValue": "false"
            },
            "disableHover": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "If `true`, the tooltip will not be displayed on hover, it will require a click."
                },
                "getter": false,
                "setter": false,
                "attribute": "disable-hover",
                "reflect": false,
                "defaultValue": "false"
            },
            "maxLines": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "The number of lines to display before truncating the text."
                },
                "getter": false,
                "setter": false,
                "attribute": "max-lines",
                "reflect": false
            },
            "placement": {
                "type": "string",
                "mutable": true,
                "complexType": {
                    "original": "IcTooltipPlacements",
                    "resolved": "\"bottom\" | \"bottom-end\" | \"bottom-start\" | \"left\" | \"left-end\" | \"left-start\" | \"right\" | \"right-end\" | \"right-start\" | \"top\" | \"top-end\" | \"top-start\" | undefined",
                    "references": {
                        "IcTooltipPlacements": {
                            "location": "import",
                            "path": "./ic-tooltip.types",
                            "id": "src/components/ic-tooltip/ic-tooltip.types.ts::IcTooltipPlacements"
                        }
                    }
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "The position of the tooltip in relation to the parent element."
                },
                "getter": false,
                "setter": false,
                "attribute": "placement",
                "reflect": false,
                "defaultValue": "\"bottom\""
            },
            "silent": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "internal",
                            "text": "Sets the tooltip to aria-hidden, when used as part of components that are already announced."
                        }],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "attribute": "silent",
                "reflect": false,
                "defaultValue": "false"
            },
            "target": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "The ID of the element the tooltip is describing - for when aria-labelledby or aria-describedby is used."
                },
                "getter": false,
                "setter": false,
                "attribute": "target",
                "reflect": true
            },
            "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 tooltip to the dark or light theme colors. \"inherit\" will set the color based on the system settings or ic-theme component."
                },
                "getter": false,
                "setter": false,
                "attribute": "theme",
                "reflect": false,
                "defaultValue": "\"inherit\""
            },
            "label": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": true,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The text to display on the tooltip."
                },
                "getter": false,
                "setter": false,
                "attribute": "label",
                "reflect": false
            }
        };
    }
    static get states() {
        return {
            "popperProps": {}
        };
    }
    static get methods() {
        return {
            "setExternalPopperProps": {
                "complexType": {
                    "signature": "<T extends Partial<Options>>(props: T) => Promise<void>",
                    "parameters": [{
                            "name": "props",
                            "type": "T",
                            "docs": "object - createPopper props set externally"
                        }],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "Partial": {
                            "location": "global",
                            "id": "global::Partial"
                        },
                        "Options": {
                            "location": "import",
                            "path": "@popperjs/core",
                            "id": "node_modules::Options"
                        },
                        "T": {
                            "location": "global",
                            "id": "global::T"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "",
                    "tags": [{
                            "name": "internal",
                            "text": "This method allows props to be added to the PopperJS createPopper instance outside of tooltip"
                        }, {
                            "name": "param",
                            "text": "props object - createPopper props set externally"
                        }]
                }
            },
            "displayTooltip": {
                "complexType": {
                    "signature": "(show: boolean, persistTooltip?: boolean) => Promise<void>",
                    "parameters": [{
                            "name": "show",
                            "type": "boolean",
                            "docs": "Whether to show or hide the tooltip"
                        }, {
                            "name": "persistTooltip",
                            "type": "boolean | undefined",
                            "docs": "Whether the tooltip should stay on the screen when actions are performed that would previously dismiss the tooltip, such as on hover"
                        }],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Method to programmatically show/hide the tooltip without needing to interact with an anchor element",
                    "tags": [{
                            "name": "param",
                            "text": "show Whether to show or hide the tooltip"
                        }, {
                            "name": "param",
                            "text": "persistTooltip Whether the tooltip should stay on the screen when actions are performed that would previously dismiss the tooltip, such as on hover"
                        }]
                }
            },
            "isTooltipVisible": {
                "complexType": {
                    "signature": "() => Promise<boolean>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<boolean>"
                },
                "docs": {
                    "text": "",
                    "tags": [{
                            "name": "internal",
                            "text": "Method to return if tooltip is currently visible."
                        }]
                }
            }
        };
    }
    static get elementRef() { return "el"; }
    static get watchers() {
        return [{
                "propName": "disableClick",
                "methodName": "watchDisableClickHandler"
            }, {
                "propName": "disableHover",
                "methodName": "watchDisableHoverHandler"
            }];
    }
}
//# sourceMappingURL=ic-tooltip.js.map
