import { h, Host, } from "@stencil/core";
import closeIcon from "../../assets/close-icon.svg";
import { VARIANT_ICONS } from "../../utils/constants";
import { getSlot, isPropDefined, isSlotUsed, onComponentRequiredPropUndefined, } from "../../utils/helpers";
const AUTO_DISMISS_TIMER_REFRESH_RATE_MS = 1000;
const TOAST_HEADING_CHAR_LIMIT = 70;
const TOAST_MESSAGE_CHAR_LIMIT = 140;
/**
 * @slot action - IcButton or IcLink is placed below header and message. If used will default toast to manual `dismiss` type.
 * @slot neutral-icon - A custom neutral icon is placed on the left side of the component. If used will default toast to `neutral` variant.
 */
export class Toast {
    constructor() {
        this.interactiveElements = [];
        this.timerProgress = 100;
        this.visible = 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";
        /**
         * If toast dismissMode is set to `automatic`, use this prop to define the time before the toast dismisses (in MILLISECONDS)
         * (NOTE: Has a minimum value of `5000ms`)
         */
        this.autoDismissTimeout = 5000;
        /**
         * If toast can be manually dismissed, this prop sets a custom aria-label for the ic-button component
         */
        this.dismissButtonAriaLabel = "dismiss";
        /**
         * How the toast will be dismissed. If manual will display a dismiss button.
         */
        this.dismissMode = "manual";
        this.dismissAction = () => {
            this.icDismiss.emit();
        };
        this.handleProgressChange = () => {
            this.timerProgress -=
                (AUTO_DISMISS_TIMER_REFRESH_RATE_MS / this.autoDismissTimeout) * 100;
        };
        this.onFocus = () => {
            if (this.focusInteractiveElement) {
                this.isManual = true;
            }
        };
        this.onBlur = () => {
            this.handleTimer({ type: "mouseleave" });
        };
    }
    dismissModeChangeHandler(newValue) {
        this.isManual = newValue === "manual";
    }
    disconnectedCallback() {
        window.clearTimeout(this.dismissTimeout);
        window.clearInterval(this.timerRefreshInterval);
    }
    componentWillLoad() {
        var _a, _b;
        this.handleLongText(this.heading.length > TOAST_HEADING_CHAR_LIMIT, !!this.message && ((_a = this.message) === null || _a === void 0 ? void 0 : _a.length) > TOAST_MESSAGE_CHAR_LIMIT);
        if (this.autoDismissTimeout < 5000)
            this.autoDismissTimeout = 5000;
        if (isSlotUsed(this.el, "action"))
            this.dismissMode = "manual";
        this.isManual = this.dismissMode === "manual";
        if (isSlotUsed(this.el, "neutral-icon"))
            this.variant = "neutral";
        if (this.variant === "neutral") {
            this.neutralVariantLabel =
                (_b = this.neutralIconAriaLabel) !== null && _b !== void 0 ? _b : VARIANT_ICONS[this.variant].ariaLabel;
        }
        if (this.isManual) {
            const toastMessage = isPropDefined(this.message)
                ? `. ${this.message}`
                : "";
            this.el.setAttribute("aria-label", this.variant
                ? this.neutralVariantLabel || VARIANT_ICONS[this.variant].ariaLabel
                : this.heading);
            (this.variant || this.message) &&
                this.el.setAttribute("aria-description", this.variant ? `${this.heading}${toastMessage}` : this.message || "");
        }
    }
    componentDidLoad() {
        onComponentRequiredPropUndefined([{ prop: this.heading, propName: "heading" }], "Toast");
    }
    componentDidUpdate() {
        var _a;
        if (this.focusInteractiveElement && this.isManual) {
            this.resetAutoDismissTimer();
            const actionContent = getSlot(this.el, "action");
            const dismissButton = (_a = this.el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector("ic-button");
            if (actionContent)
                this.interactiveElements.push(actionContent);
            if (dismissButton)
                this.interactiveElements.push(dismissButton);
            this.focusInteractiveElement = false;
            this.findNextInteractiveElement(this.shiftKeyPressed).setFocus();
            this.shiftKeyPressed = false;
        }
    }
    watchVisibleHandler() {
        var _a;
        if (this.visible) {
            const actionContent = getSlot(this.el, "action");
            const dismissButton = (_a = this.el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector("ic-button");
            if (actionContent)
                this.interactiveElements.push(actionContent);
            if (dismissButton)
                this.interactiveElements.push(dismissButton);
        }
        else {
            this.interactiveElements = [];
        }
    }
    handleDismiss() {
        this.visible = false;
        this.resetAutoDismissTimer();
    }
    handleKeyboard(ev) {
        if (this.visible) {
            if (this.isManual) {
                switch (ev.key) {
                    case "Tab":
                        ev.preventDefault();
                        this.findNextInteractiveElement(ev.shiftKey).setFocus();
                        break;
                    case "Escape":
                        !ev.repeat && this.dismissAction();
                        ev.stopImmediatePropagation();
                        break;
                }
            }
            else {
                if (ev.key === "Tab") {
                    this.shiftKeyPressed = ev.shiftKey;
                    this.focusInteractiveElement = true;
                }
            }
        }
    }
    handleTimer(ev) {
        switch (ev.type) {
            case "mouseenter":
                if (!this.isManual) {
                    this.resetAutoDismissTimer();
                }
                this.isManual = true;
                break;
            case "mouseleave":
                if (this.dismissMode === "automatic") {
                    this.isManual = false;
                    this.interactiveElements = [];
                    if (this.visible) {
                        this.dismissTimeout = window.setTimeout(this.dismissAction, this.autoDismissTimeout);
                        this.timerRefreshInterval = window.setInterval(this.handleProgressChange, AUTO_DISMISS_TIMER_REFRESH_RATE_MS);
                    }
                }
                break;
        }
    }
    /**
     * @internal Used to display the individual toast.
     * @returns The element that previously had focus before the toast appeared
     */
    async setVisible() {
        if (!this.visible)
            this.visible = true;
        if (!this.isManual) {
            this.dismissTimeout = window.setTimeout(this.dismissAction, this.autoDismissTimeout);
            this.timerRefreshInterval = window.setInterval(this.handleProgressChange, AUTO_DISMISS_TIMER_REFRESH_RATE_MS);
            return null;
        }
        else {
            this.interactiveElements[0] &&
                window.setTimeout(() => this.interactiveElements[0].setFocus(), 200);
            return document.activeElement;
        }
    }
    handleLongText(headingTooLong, messageTooLong) {
        if (messageTooLong || headingTooLong) {
            console.error(`Too many characters in toast ${headingTooLong ? "heading" : ""}${headingTooLong && messageTooLong ? " and " : ""}${messageTooLong ? "message" : ""}. Refer to character limits specified in the prop description`);
        }
    }
    findNextInteractiveElement(isBackwards) {
        const firstEl = this.interactiveElements[0];
        const lastEl = this.interactiveElements[this.interactiveElements.length - 1];
        if (this.isActive(isBackwards ? firstEl : lastEl))
            return isBackwards ? lastEl : firstEl;
        let currentIndex = 0;
        return this.interactiveElements.some((el, index) => {
            if (!this.isActive(el))
                return false;
            currentIndex = index;
            return true;
        })
            ? this.interactiveElements[currentIndex + (isBackwards ? -1 : 1)]
            : firstEl;
    }
    resetAutoDismissTimer() {
        window.clearTimeout(this.dismissTimeout);
        window.clearInterval(this.timerRefreshInterval);
        this.timerProgress = 100;
    }
    isActive(targetEl) {
        return targetEl === this.el
            ? !!this.el.shadowRoot.activeElement
            : document.activeElement === targetEl;
    }
    render() {
        const { variant, heading, message, visible, isManual, dismissButtonAriaLabel, theme, } = this;
        return (h(Host, { key: 'ff2cb4fa83ec20e9226dac7e6d65692877f6ba18', class: {
                [`ic-theme-${theme}`]: theme !== "inherit",
                ["ic-toast-hidden"]: !visible,
                [`ic-toast-variant-${variant}`]: variant !== undefined,
            }, tabindex: "0", onFocus: this.onFocus, onBlur: this.onBlur, role: isManual ? "dialog" : "alert", "aria-live": isManual ? null : "polite" }, h("div", { key: '96a06262e46b6fd4eefe8e3eb84c3b67c5a85335', class: {
                ["container"]: true,
                [`container-${variant}`]: variant !== undefined,
            } }, variant && visible && (h("div", { key: '30eec9ac65d800405983859cada0514bce740b6a', class: "toast-icon-container" }, h("div", { key: '741228b2fa872bc5f6c4a2e57d76b2ce1ae313da', class: {
                ["divider"]: true,
                [`divider-${variant}`]: true,
            } }), variant === "neutral" ? (h("slot", { name: "neutral-icon" })) : (h("span", { class: "toast-icon", innerHTML: VARIANT_ICONS[variant].icon })))), h("div", { key: '5068418007424fb1e8074a51c3d48b44d3d4960d', class: {
                ["toast-content"]: true,
                ["no-icon"]: variant === "neutral" && !isSlotUsed(this.el, "neutral-icon"),
            } }, h("div", { key: '99bb37a24570386689e6712e1b5e55cfce64fba9', class: "toast-text" }, h("ic-typography", { key: '017c9e715e6f60aeb95ee28d67130541b6df4888', variant: "subtitle-large", class: "toast-heading" }, visible && (isManual ? h("h5", null, heading) : h("p", null, heading))), message && (h("ic-typography", { key: '30d276906aec46c8ac41ef3275dc3b7b5c96177b', variant: "body", class: "toast-message" }, visible && h("p", { key: 'f1648dc19f63770974cc92ef9da333e000677bb9' }, message)))), isSlotUsed(this.el, "action") && (h("div", { key: 'a8e396c4263d937de7c76c15aa68cf499ad5df78', class: "toast-action-container" }, h("slot", { key: '22d5e4ef0f50a3b65067c27d305ade75eab441a0', name: "action" })))), !isManual ? (h("ic-loading-indicator", { class: "toast-dismiss-timer", theme: "dark", monochrome: true, size: "icon", progress: this.timerProgress, description: "Dismiss timer" })) : (h("ic-button", { id: "dismiss-button", innerHTML: closeIcon, onClick: this.dismissAction, variant: "icon-tertiary", "aria-label": dismissButtonAriaLabel })))));
    }
    static get is() { return "ic-toast"; }
    static get encapsulation() { return "shadow"; }
    static get originalStyleUrls() {
        return {
            "$": ["ic-toast.css"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["ic-toast.css"]
        };
    }
    static get properties() {
        return {
            "theme": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "IcThemeMode",
                    "resolved": "\"dark\" | \"inherit\" | \"light\"",
                    "references": {
                        "IcThemeMode": {
                            "location": "import",
                            "path": "../../utils/types",
                            "id": "src/utils/types.ts::IcThemeMode"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "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\""
            },
            "autoDismissTimeout": {
                "type": "number",
                "mutable": true,
                "complexType": {
                    "original": "number | undefined",
                    "resolved": "number | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "If toast dismissMode is set to `automatic`, use this prop to define the time before the toast dismisses (in MILLISECONDS)\n(NOTE: Has a minimum value of `5000ms`)"
                },
                "getter": false,
                "setter": false,
                "attribute": "auto-dismiss-timeout",
                "reflect": false,
                "defaultValue": "5000"
            },
            "dismissButtonAriaLabel": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string | undefined",
                    "resolved": "string | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "If toast can be manually dismissed, this prop sets a custom aria-label for the ic-button component"
                },
                "getter": false,
                "setter": false,
                "attribute": "dismiss-button-aria-label",
                "reflect": false,
                "defaultValue": "\"dismiss\""
            },
            "dismissMode": {
                "type": "string",
                "mutable": true,
                "complexType": {
                    "original": "IcActivationTypes",
                    "resolved": "\"automatic\" | \"manual\" | undefined",
                    "references": {
                        "IcActivationTypes": {
                            "location": "import",
                            "path": "../../utils/types",
                            "id": "src/utils/types.ts::IcActivationTypes"
                        }
                    }
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "How the toast will be dismissed. If manual will display a dismiss button."
                },
                "getter": false,
                "setter": false,
                "attribute": "dismiss-mode",
                "reflect": false,
                "defaultValue": "\"manual\""
            },
            "heading": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": true,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The title to display at the start of the toast. (NOTE: Should be no more than `70` characters)"
                },
                "getter": false,
                "setter": false,
                "attribute": "heading",
                "reflect": false
            },
            "message": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "The main body message of the toast. (NOTE: Should be no more than `140` characters)"
                },
                "getter": false,
                "setter": false,
                "attribute": "message",
                "reflect": false
            },
            "neutralIconAriaLabel": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Provides a custom alt-text to be announced to screen readers, if slotting a custom neutral icon"
                },
                "getter": false,
                "setter": false,
                "attribute": "neutral-icon-aria-label",
                "reflect": false
            },
            "variant": {
                "type": "string",
                "mutable": true,
                "complexType": {
                    "original": "IcStatusVariants",
                    "resolved": "\"ai\" | \"error\" | \"info\" | \"neutral\" | \"success\" | \"warning\" | undefined",
                    "references": {
                        "IcStatusVariants": {
                            "location": "import",
                            "path": "../../utils/types",
                            "id": "src/utils/types.ts::IcStatusVariants"
                        }
                    }
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "The variant of the toast being rendered"
                },
                "getter": false,
                "setter": false,
                "attribute": "variant",
                "reflect": false
            }
        };
    }
    static get states() {
        return {
            "isManual": {},
            "timerProgress": {},
            "visible": {}
        };
    }
    static get events() {
        return [{
                "method": "icDismiss",
                "name": "icDismiss",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Is emitted when the user dismisses the toast"
                },
                "complexType": {
                    "original": "void",
                    "resolved": "void",
                    "references": {}
                }
            }];
    }
    static get methods() {
        return {
            "setVisible": {
                "complexType": {
                    "signature": "() => Promise<HTMLElement | null>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "HTMLElement": {
                            "location": "global",
                            "id": "global::HTMLElement"
                        }
                    },
                    "return": "Promise<HTMLElement | null>"
                },
                "docs": {
                    "text": "",
                    "tags": [{
                            "name": "internal",
                            "text": "Used to display the individual toast."
                        }, {
                            "name": "returns",
                            "text": "The element that previously had focus before the toast appeared"
                        }]
                }
            }
        };
    }
    static get elementRef() { return "el"; }
    static get watchers() {
        return [{
                "propName": "dismissMode",
                "methodName": "dismissModeChangeHandler"
            }, {
                "propName": "visible",
                "methodName": "watchVisibleHandler"
            }];
    }
    static get listeners() {
        return [{
                "name": "icDismiss",
                "method": "handleDismiss",
                "target": undefined,
                "capture": true,
                "passive": false
            }, {
                "name": "keydown",
                "method": "handleKeyboard",
                "target": "document",
                "capture": false,
                "passive": false
            }, {
                "name": "mouseenter",
                "method": "handleTimer",
                "target": undefined,
                "capture": false,
                "passive": true
            }, {
                "name": "mouseleave",
                "method": "handleTimer",
                "target": undefined,
                "capture": false,
                "passive": true
            }];
    }
}
//# sourceMappingURL=ic-toast.js.map
