import { h, Host } from "@stencil/core";
const LOADING_INDICATOR_WIDTHS = {
    large: 120,
    medium: 80,
    small: 40,
    icon: 20,
};
export class LoadingIndicator {
    constructor() {
        this.labelList = [];
        this.circularDiameter = 0;
        this.circularLineWidth = 0;
        this.circularDimensions = {
            x: 0,
            y: 0,
            r: 0,
        };
        this.clipInnerElement = false;
        this.internalType = "circular";
        /**
         * The description that will be set as the aria-label of the loading indicator when not using a visible label.
         */
        this.description = "Loading";
        /**
         * If `true`, when linear, the full-width variant (i.e. without a border radius) will be displayed.
         */
        this.fullWidth = false;
        /**
         * The time in milliseconds before the label changes.
         */
        this.labelDuration = 8000;
        /**
         * The maximum value that the progress value can take.
         * Used to calculate the proportional width of the progress bar.
         */
        this.max = 100;
        /**
         * The minimum value that the progress value can take.
         * Used to calculate the proportional width of the progress bar.
         */
        this.min = 0;
        /**
         * If `true`, the element will display as black and white.
         */
        this.monochrome = false;
        /**
         * The size of the loading indicator.
         */
        this.size = "medium";
        /**
         * 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 indicator, either linear or circular. When size is set to 'icon' the type will be set to circular.
         */
        this.type = "circular";
        this.getLabel = (labelIndex) => new Promise(() => {
            this.interval = setInterval(() => {
                if (labelIndex < this.labelList.length - 1) {
                    labelIndex++;
                }
                else {
                    labelIndex = 0;
                }
                this.indicatorLabel = this.labelList[labelIndex];
            }, this.labelDuration);
        });
        this.getLabelVariant = () => {
            const width = this.internalType === "circular" ? this.calculateWidth() : 0;
            if (this.size === "small" || (width && width < 60)) {
                return "label";
            }
            else if (this.size === "large" || width >= 120) {
                return "h2";
            }
            return "h4";
        };
        this.calculateWidth = () => {
            var _a, _b, _c;
            if ((_a = this.outerElement) === null || _a === void 0 ? void 0 : _a.offsetWidth)
                return this.outerElement.offsetWidth;
            if (this.outerElement) {
                const { width } = window.getComputedStyle(this.outerElement);
                if (width) {
                    // Regex to check the units of the css string
                    if (((_b = width.match(/\D+$/)) === null || _b === void 0 ? void 0 : _b[0]) !== "%")
                        return parseFloat(width);
                    const parentWidth = (_c = this.outerElement.parentElement) === null || _c === void 0 ? void 0 : _c.offsetWidth;
                    if (parentWidth)
                        return parentWidth * (parseFloat(width) / 100);
                }
            }
            return LOADING_INDICATOR_WIDTHS[this.size];
        };
        this.calculateProportion = (progress) => {
            const minProgress = Math.min(this.max, Math.max(this.min, progress));
            return (minProgress - this.min) / (this.max - this.min);
        };
        this.setLinearDeterminateWidth = () => {
            // Ensure progress cannot be out of bounds
            if (!this.innerElement || !this.progress)
                return;
            const proportion = this.calculateProportion(this.progress);
            this.clipInnerElement = proportion > 0.5;
            if (this.clipInnerElement) {
                this.innerElement.classList.remove("clip");
            }
            else {
                this.innerElement.classList.add("clip");
            }
            this.innerElement.style.setProperty("--linear-width", `${proportion * 100}%`);
        };
        this.setInternalType = () => {
            this.internalType = this.type;
            if (this.type == "linear") {
                this.internalType = this.size == "icon" ? "circular" : "linear";
            }
        };
        this.updateLabel = () => {
            if (!this.label)
                return;
            if (typeof this.label === "string") {
                this.indicatorLabel = this.label;
            }
            else {
                this.labelList = this.label;
                this.indicatorLabel = this.labelList[0];
                if (this.labelList.length > 1) {
                    this.getLabel(0);
                }
            }
        };
        this.setCircleDimensions = () => {
            if (this.circularDiameter <= 0)
                return;
            const r = this.circularDiameter / 2;
            const nextRadius = r - this.circularLineWidth / 2;
            const dashArray = 2 * Math.PI * nextRadius;
            this.circularDimensions = {
                x: r,
                y: r,
                r: nextRadius,
                dashArray: `${dashArray}px`,
                dashOffset: this.progress
                    ? `${(-1 - this.calculateProportion(this.progress)) * dashArray}px`
                    : undefined,
            };
        };
    }
    watchPropHandler() {
        this.updateLabel();
    }
    handleProgressChange() {
        if (this.internalType === "linear") {
            this.setLinearDeterminateWidth();
        }
        else {
            this.setCircleDimensions();
        }
    }
    handleIconSize() {
        this.setIndicatorDimensions();
    }
    setIndicatorDimensions() {
        this.setInternalType();
        if (this.internalType === "circular") {
            // Sets the circular indicator line width - accounting for the circle size being altered using the CSS custom property
            const diameter = this.calculateWidth();
            if (this.outerElement && diameter !== this.circularDiameter) {
                this.circularLineWidth = diameter * 0.1;
                this.circularDiameter = diameter;
                this.outerElement.style.setProperty("--circular-line-width", `${this.circularLineWidth}px`);
            }
            this.setCircleDimensions();
        }
        else {
            this.setLinearDeterminateWidth();
        }
    }
    disconnectedCallback() {
        clearInterval(this.interval);
    }
    componentWillLoad() {
        this.updateLabel();
        this.el.setAttribute("exportparts", "ic-loading-container");
    }
    componentDidLoad() {
        this.setIndicatorDimensions();
    }
    render() {
        const { circularDiameter, circularDimensions: { x, y, r, dashArray, dashOffset }, description, fullWidth, indicatorLabel, innerLabel, internalType, label, max, min, monochrome, progress, size, theme, } = this;
        return (h(Host, { key: '243c07c3e1680457f322a8b6f5885c9d87e76d5d', class: {
                [`ic-theme-${theme}`]: theme !== "inherit",
                "ic-loading-indicator-full-width": fullWidth,
                "ic-loading-indicator-label": !!label,
                "ic-loading-indicator-monochrome": monochrome,
                [`ic-loading-indicator-size-${size}`]: true,
            } }, h("div", { key: '9babb0d72e18da86831c77b3cafe898a07f862bd', class: "ic-loading-container", part: "ic-loading-container" }, h("div", { key: 'fc2acfe835840bcb374bf8d5a018b3e9e16d8998', ref: (el) => (this.outerElement = el), class: {
                [`ic-loading-${internalType}-outer`]: true,
                [progress === undefined ? "indeterminate" : "determinate"]: true,
            }, role: "progressbar", "aria-labelledby": label && size !== "icon" && "ic-loading-label", "aria-label": description, "aria-valuenow": progress, "aria-valuemin": min, "aria-valuemax": max }, h("div", { key: '953e6e286631e85d75dd2a0fe48fb8b24543d38e', ref: (el) => (this.innerElement = el), class: {
                [`ic-loading-${internalType}-inner`]: true,
                "inner-label": !!innerLabel,
            } }, innerLabel && size === "small" && (h("ic-typography", { key: 'bd2371f08cba6309c42137ca1a69b76126708414', variant: "subtitle-small", class: "inner-text" }, innerLabel)), internalType === "circular" && (h("svg", { key: 'd8d29654375b72d57906e0875065e04191866685', class: "ic-loading-circular-svg", viewBox: `0 0 ${circularDiameter} ${circularDiameter}` }, h("circle", { key: '0f244e5c1d2c0154f927c332ed3e215e89c21aee', cx: x, cy: y, r: r }), h("circle", { key: 'f1a18ea21887f9325ebcaee5a727ecb9824a0aab', style: {
                "--circular-steps-max": progress ? `${max}` : undefined,
                "--progress-value": progress !== undefined ? `${progress}` : undefined,
                "--stroke-dasharray": dashArray,
                "--stroke-dashoffset": dashOffset,
            }, cx: x, cy: y, r: r }))))), label && size !== "icon" && (h("ic-typography", { key: '2a69d9c65183971baedab9f9dbe85f51be96db5e', id: "ic-loading-label", class: "ic-loading-label", role: "alert", variant: this.getLabelVariant() }, h("p", { key: '9b21465fcb1befe73cc481499cb037733ab6c1f2' }, indicatorLabel))))));
    }
    static get is() { return "ic-loading-indicator"; }
    static get encapsulation() { return "shadow"; }
    static get originalStyleUrls() {
        return {
            "$": ["ic-loading-indicator.css"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["ic-loading-indicator.css"]
        };
    }
    static get properties() {
        return {
            "description": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The description that will be set as the aria-label of the loading indicator when not using a visible label."
                },
                "getter": false,
                "setter": false,
                "attribute": "description",
                "reflect": false,
                "defaultValue": "\"Loading\""
            },
            "fullWidth": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true`, when linear, the full-width variant (i.e. without a border radius) will be displayed."
                },
                "getter": false,
                "setter": false,
                "attribute": "full-width",
                "reflect": true,
                "defaultValue": "false"
            },
            "innerLabel": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "internal",
                            "text": "The step number of a compact step, managed by ic-step."
                        }],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "attribute": "inner-label",
                "reflect": false
            },
            "label": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string | string[]",
                    "resolved": "string | string[] | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "The label to be displayed beneath the loading indicator.\nDisplay a changing label by supplying an array of messages."
                },
                "getter": false,
                "setter": false,
                "attribute": "label",
                "reflect": false
            },
            "labelDuration": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The time in milliseconds before the label changes."
                },
                "getter": false,
                "setter": false,
                "attribute": "label-duration",
                "reflect": false,
                "defaultValue": "8000"
            },
            "max": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The maximum value that the progress value can take.\nUsed to calculate the proportional width of the progress bar."
                },
                "getter": false,
                "setter": false,
                "attribute": "max",
                "reflect": false,
                "defaultValue": "100"
            },
            "min": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The minimum value that the progress value can take.\nUsed to calculate the proportional width of the progress bar."
                },
                "getter": false,
                "setter": false,
                "attribute": "min",
                "reflect": false,
                "defaultValue": "0"
            },
            "monochrome": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true`, the element will display as black and white."
                },
                "getter": false,
                "setter": false,
                "attribute": "monochrome",
                "reflect": false,
                "defaultValue": "false"
            },
            "progress": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "The current amount of progress made.\nIf not provided, component acts as an indeterminate loading indicator."
                },
                "getter": false,
                "setter": false,
                "attribute": "progress",
                "reflect": false
            },
            "size": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "IcLoadingSizes",
                    "resolved": "\"icon\" | \"large\" | \"medium\" | \"small\"",
                    "references": {
                        "IcLoadingSizes": {
                            "location": "import",
                            "path": "./ic-loading-indicator.types",
                            "id": "src/components/ic-loading-indicator/ic-loading-indicator.types.tsx::IcLoadingSizes"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The size of the loading indicator."
                },
                "getter": false,
                "setter": false,
                "attribute": "size",
                "reflect": true,
                "defaultValue": "\"medium\""
            },
            "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\""
            },
            "type": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "IcLoadingTypes",
                    "resolved": "\"circular\" | \"linear\"",
                    "references": {
                        "IcLoadingTypes": {
                            "location": "import",
                            "path": "./ic-loading-indicator.types",
                            "id": "src/components/ic-loading-indicator/ic-loading-indicator.types.tsx::IcLoadingTypes"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The type of indicator, either linear or circular. When size is set to 'icon' the type will be set to circular."
                },
                "getter": false,
                "setter": false,
                "attribute": "type",
                "reflect": true,
                "defaultValue": "\"circular\""
            }
        };
    }
    static get states() {
        return {
            "circularDiameter": {},
            "circularLineWidth": {},
            "circularDimensions": {},
            "indicatorLabel": {},
            "clipInnerElement": {},
            "internalType": {}
        };
    }
    static get elementRef() { return "el"; }
    static get watchers() {
        return [{
                "propName": "label",
                "methodName": "watchPropHandler"
            }, {
                "propName": "max",
                "methodName": "handleProgressChange"
            }, {
                "propName": "min",
                "methodName": "handleProgressChange"
            }, {
                "propName": "progress",
                "methodName": "handleProgressChange"
            }, {
                "propName": "size",
                "methodName": "handleIconSize"
            }, {
                "propName": "type",
                "methodName": "setIndicatorDimensions"
            }];
    }
}
//# sourceMappingURL=ic-loading-indicator.js.map
