import { h, Host } from "@stencil/core";
import { PlatformServiceName, } from "@limetech/lime-web-components";
import { getPercentageClass } from "../../util/percentage-class";
import { normalizeValue } from "../../util/normalize-value";
/**
 * This component generates an infographic that displays the growth trend.
 * It can be used to display the growth of a stock, the increase in sales,
 * or any other value that can be represented as a percentage.
 *
 * There are two ways to use this component:
 * 1. Provide only the `value` prop. This will display the `value` as it is with
 * a growth infographic based on it.
 * 2. Provide both the `value` and `formerValue` props. This will display the:
 *
 * calculated growth: (`value` - `formerValue`) and
 *
 * infographic based on calculate percentage growth:
 *
 * (`value` - `formerValue`) / |`formerValue`| * 100.
 *
 * @exampleComponent limebb-trend-indicator-basic
 * @exampleComponent limebb-trend-indicator-reduce-presence
 * @exampleComponent limebb-trend-indicator-composite
 * @exampleComponent limebb-trend-indicator-former-value
 * @exampleComponent limebb-trend-indicator-locale
 * @beta
 */
export class TrendIndicator {
    constructor() {
        /**
         * A short piece of text to display after the value.
         */
        this.suffix = '%';
        /**
         * When set to `false`, if the `value` equals `0` or there is no value
         * (_undefined_, _null_ or empty string), the component will
         * render the visualization. See the examples for more details.
         */
        this.reducePresence = true;
        this.locale = 'en';
        this.labelId = 'a' + crypto.randomUUID();
        this.tooltipId = 'a' + crypto.randomUUID();
        this.helperTextId = 'a' + crypto.randomUUID();
        this.renderHelperLine = () => {
            if (!this.hasHelperText()) {
                return;
            }
            return (h("limel-helper-line", { helperTextId: this.helperTextId, helperText: this.helperText, invalid: this.invalid }));
        };
        this.hasHelperText = () => {
            return this.helperText !== null && this.helperText !== undefined;
        };
    }
    valueChanged(newValue) {
        this.numValue = this.parseValue(newValue);
    }
    componentWillLoad() {
        try {
            this.locale = this.platform
                .get(PlatformServiceName.UserPreferencesRepository)
                .get('locale');
            this.numberFormat = new Intl.NumberFormat(this.locale);
        }
        catch (_a) {
            console.warn(`Could not get user's locale (${this.locale}), falling back to 'en'.`);
            this.locale = 'en';
            this.numberFormat = new Intl.NumberFormat('en');
        }
        this.numValue = this.parseValue(this.value);
    }
    render() {
        return (h(Host, { key: 'fd3bce29b7cd49a4642904fa630616b10e7d55b8', class: this.getContainerClassList() }, h("limel-notched-outline", { key: '3502f060569abb0e12c5b6bca84fdf9b190e840f', id: this.tooltipId, label: this.label, labelId: this.labelId, invalid: this.invalid, required: this.required, hasValue: true, hasFloatingLabel: true, "aria-labelledby": this.labelId, "aria-describedby": this.helperTextId, "aria-controls": this.helperTextId }, h("div", { key: '4f007fec33a71fe2205c1fbb861b45b8d41f440e', slot: "content", tabIndex: 0 }, this.renderVisualization())), this.renderHelperLine(), this.renderTooltip()));
    }
    renderVisualization() {
        if (this.reducePresence && (this.numValue === 0 || !this.hasValue())) {
            return;
        }
        if (!this.hasValue()) {
            return h("span", { class: "no-value" }, "\u2013");
        }
        return [
            this.getArrowIcon(),
            h("span", null, this.renderGrowthPercentage(), this.renderGrowthAmount()),
        ];
    }
    renderTooltip() {
        if (this.formerValue === undefined) {
            return;
        }
        const tooltipValue = `${this.value}` +
            ' - ' +
            `${this.formerValue > 0 ? this.formerValue : '(' + this.formerValue + ')'}` +
            ' = ' +
            `${this.calculateGrowth()}` +
            ` ${this.suffix} ` +
            ' ';
        const percentage = this.calculatePercentage();
        return (h("limel-tooltip", { openDirection: "top-start", elementId: this.tooltipId, label: percentage + '%', helperLabel: tooltipValue }));
    }
    renderGrowthPercentage() {
        if (this.formerValue === undefined) {
            return this.formatValue(this.numValue, this.suffix);
        }
        const percentage = this.calculatePercentage();
        if (percentage === null) {
            return;
        }
        return this.formatValue(percentage, '%');
    }
    renderGrowthAmount() {
        if (this.formerValue === undefined) {
            return;
        }
        const value = this.calculateGrowth();
        return (h("span", { class: "growth-unit" }, "( ", this.formatValue(value, this.suffix), " )"));
    }
    hasValue() {
        return (this.value !== undefined && this.value !== null && this.value !== '');
    }
    getContainerClassList() {
        if (!this.hasValue()) {
            return;
        }
        const percentage = this.getPercentage();
        const percentageClass = getPercentageClass(percentage);
        return Object.assign({}, (percentageClass && { [percentageClass]: true }));
    }
    getPercentage() {
        if (this.formerValue === undefined) {
            return this.numValue;
        }
        return this.calculatePercentage();
    }
    calculateGrowth() {
        return this.numValue - this.formerValue;
    }
    calculatePercentage() {
        if (this.formerValue === 0) {
            return null;
        }
        const PERCENT = 100;
        const DECIMALS = 2;
        const percentage = (((this.numValue - this.formerValue) /
            Math.abs(this.formerValue)) *
            PERCENT).toFixed(DECIMALS);
        return Number.parseFloat(percentage);
    }
    unifyMinusSign(input) {
        // Replace Unicode minus sign (−) with ASCII hyphen-minus (-)
        return input.replaceAll('−', '-');
    }
    convertToUnicodeMinus(input) {
        // Replace ASCII hyphen-minus (-) with Unicode minus sign (−)
        return input.replaceAll('-', '−');
    }
    parseValue(value) {
        if (typeof value === 'string') {
            return Number.parseFloat(normalizeValue(this.unifyMinusSign(value), this.locale));
        }
        return value;
    }
    formatValue(value, suffix) {
        const constructedValue = `${this.numberFormat.format(value)} ${suffix}`;
        if (value > 0) {
            return '+' + constructedValue;
        }
        return this.convertToUnicodeMinus(constructedValue);
    }
    getArrowIcon() {
        return (h("limel-icon", { class: "icon", name: "right", "aria-hidden": "true", role: "presentation" }));
    }
    static get is() { return "limebb-trend-indicator"; }
    static get encapsulation() { return "shadow"; }
    static get originalStyleUrls() {
        return {
            "$": ["trend-indicator.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["trend-indicator.css"]
        };
    }
    static get properties() {
        return {
            "platform": {
                "type": "unknown",
                "mutable": false,
                "complexType": {
                    "original": "LimeWebComponentPlatform",
                    "resolved": "LimeWebComponentPlatform",
                    "references": {
                        "LimeWebComponentPlatform": {
                            "location": "import",
                            "path": "@limetech/lime-web-components",
                            "id": "node_modules::LimeWebComponentPlatform",
                            "referenceLocation": "LimeWebComponentPlatform"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "inherit",
                            "text": undefined
                        }],
                    "text": "Reference to the platform service container.\n\nUse this to access all platform services like repositories, HTTP client,\ncommand bus, navigator, and more. The platform instance is shared across\nall components in the same application context."
                },
                "getter": false,
                "setter": false
            },
            "context": {
                "type": "unknown",
                "mutable": false,
                "complexType": {
                    "original": "LimeWebComponentContext",
                    "resolved": "LimeWebComponentContext",
                    "references": {
                        "LimeWebComponentContext": {
                            "location": "import",
                            "path": "@limetech/lime-web-components",
                            "id": "node_modules::LimeWebComponentContext",
                            "referenceLocation": "LimeWebComponentContext"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "inherit",
                            "text": undefined
                        }],
                    "text": "The context describing where this component is running.\n\nThe context provides information about the current limetype and record ID\n(if viewing/editing a specific record). Components can use this to load\nrelevant data and understand their operating environment."
                },
                "getter": false,
                "setter": false
            },
            "value": {
                "type": "any",
                "mutable": false,
                "complexType": {
                    "original": "number | string",
                    "resolved": "number | string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Preferably a number (or a string that can be converted to a number\nby the component) that represents the current value."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "value"
            },
            "formerValue": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "A number that represents the previous value.\nWhen both `value` and `formerValue` are provided,\nthe component will calculate the difference between the two\nand display the growth in an infographic way."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "former-value"
            },
            "suffix": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "A short piece of text to display after the value."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "suffix",
                "defaultValue": "'%'"
            },
            "label": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "The label of the field.\nWill be displayed as a floating label on top,\nmimicking other form elements, such as input fields."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "label"
            },
            "invalid": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Set to `true` to indicate that the current value is invalid."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "invalid"
            },
            "required": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Set to `true` to render an asterisk beside the label,\nonly visually indicating that the field is required.\nUseful when the component is used as a from field on cards."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "required"
            },
            "helperText": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Optional helper text to display below the field when it is focused.\nThe helper text also appears when the component is `invalid`."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "helper-text"
            },
            "reducePresence": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "When set to `false`, if the `value` equals `0` or there is no value\n(_undefined_, _null_ or empty string), the component will\nrender the visualization. See the examples for more details."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "reduce-presence",
                "defaultValue": "true"
            }
        };
    }
    static get watchers() {
        return [{
                "propName": "value",
                "methodName": "valueChanged"
            }];
    }
}
