import { Host, h } from "@stencil/core";
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import "dayjs/locale/nl";
import { sensorInfo } from "../../utils/sensorInfo";
import { getStore } from "../../store";
import statusCodesState from "../../stores/status-codes.store";
import { isEmptyObject } from "../../utils/is-empty-object";
import { getSafeRelativeTime } from "../../utils/safe-relative-time";
import { isNil } from "lodash-es";
import { watchStoreLocale } from "../../utils/locale-state";
import { getStoreUnavailableError } from "../../utils/store-error";
export class LsStatusMessages {
    constructor() {
        /**
         * Whether or not to show the title of the component.
         */
        this.hideTitle = false;
        /**
         * Allows user to filter messages based on severity
         */
        // Leading comma is to allow for <empty_string>
        this.severityOptions = ",impact,informational,non-impact";
        /**
         * The data received from the subscription is placed in this state.
         * The component is automatically rerendered after the state changes.
         */
        this.statusMessages = [];
        /**
         * The timestamp of when the sensor last changed.
         */
        this.lastChange = "";
        /**
         * The timer is used to update the relative timestamps.
         */
        this.time = Date.now();
        /**
         * Centralized error state for tracking component errors
         */
        this.errorState = {
            hasError: false,
            messageKey: undefined,
            type: "",
        };
        this.store = null;
        /**
         * The sensor ID associated with the status messages.
         */
        this.sensorId = 513;
        this.isComponentMounted = false;
        this.storeUnsubscribe = null;
        // This function processes the raw data from the socket server
        this.updateData = (sensorData) => {
            var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
            this.updateErrorState();
            // Only listen to our own sensor identifier
            if (isEmptyObject((_a = sensorData === null || sensorData === void 0 ? void 0 : sensorData.values) === null || _a === void 0 ? void 0 : _a[this.sensorId]))
                return;
            const items = (_b = sensorData.values[this.sensorId]) === null || _b === void 0 ? void 0 : _b.split(",").filter((id) => id.trim() !== "");
            if (isNil(items) || items.length === 0) {
                this.lastChange = getSafeRelativeTime(sensorData.updated[this.sensorId], (_c = this.store) === null || _c === void 0 ? void 0 : _c.state.locale);
                this.statusMessages = [];
                return;
            }
            const result = [];
            for (const item of items) {
                const parts = item.split(":");
                const identifier = parts[0];
                const timestampValue = parseInt(parts[1], 10) / 1000;
                const timestamp = dayjs.unix(timestampValue).locale((_d = this.store) === null || _d === void 0 ? void 0 : _d.state.locale);
                const humanReadableTimestamp = timestamp.format("D MMM YYYY H:mm:ss");
                const relativeTimestamp = getSafeRelativeTime(timestampValue * 1000, (_e = this.store) === null || _e === void 0 ? void 0 : _e.state.locale); // Convert back to milliseconds
                const active = parseInt(parts[2], 10);
                // The description and severity level are retrieved from the central store
                const description = (_g = (_f = statusCodesState[identifier]) === null || _f === void 0 ? void 0 : _f.description) !== null && _g !== void 0 ? _g : identifier;
                const severity = (_j = (_h = statusCodesState[identifier]) === null || _h === void 0 ? void 0 : _h.level) !== null && _j !== void 0 ? _j : null;
                // Add the item to the results array
                if (active === 1 && ((_k = this.severityFilter) === null || _k === void 0 ? void 0 : _k.includes(severity))) {
                    result.push({
                        id: identifier,
                        humanReadableTimestamp,
                        relativeTimestamp,
                        description,
                        severity,
                    });
                }
            }
            this.lastChange = getSafeRelativeTime(sensorData.updated[this.sensorId], (_l = this.store) === null || _l === void 0 ? void 0 : _l.state.locale);
            this.statusMessages = result;
        };
        this.isSeverity = (value) => {
            return ["", "impact", "informational", "non-impact"].includes(value);
        };
    }
    get componentTitle() {
        var _a;
        return sensorInfo.getLabel(this.sensorId, (_a = this.store) === null || _a === void 0 ? void 0 : _a.state.locale);
    }
    /**
     * Updates the error state based on current component conditions
     */
    updateErrorState() {
        var _a;
        if (this.store === null) {
            this.errorState = getStoreUnavailableError((_a = this.store) === null || _a === void 0 ? void 0 : _a.state.locale);
            return;
        }
        if (this.store.state.error.hasError) {
            this.errorState = {
                hasError: true,
                messageKey: this.store.state.error.messageKey,
                type: this.store.state.error.type,
            };
            this.stopTimer();
            return;
        }
        // No error detected
        this.errorState = {
            hasError: false,
            messageKey: undefined,
            type: "",
        };
        this.startTimer();
    }
    connectedCallback() {
        this.startTimer();
        const severityFilterSplit = this.severityOptions
            .replace(/\s+/g, "")
            .split(",")
            .filter((id) => id.trim() !== "");
        const severityFilter = [];
        severityFilterSplit.forEach((item) => {
            if (this.isSeverity(item) && !severityFilter.includes(item)) {
                severityFilter.push(item);
            }
        });
        if (severityFilter.length > 0) {
            this.severityFilter = severityFilter;
        }
        else {
            console.group("%cError%c [LsStatusMessages] Incorrect severity filter options supplied", "color: #DC2626; background-color: #FEF2F2; display: inline-block; padding: 0 4px; border-radius: 2px;", "");
            console.log("Allowed options: '<empty_string>, impact, informational and non-impact");
            console.log("Check https://springtree.github.io/ednl-liftstatus-web-components/#/components/ls-status-messages for more information");
            console.groupEnd();
        }
    }
    startTimer() {
        // Clear any existing timer first
        this.stopTimer();
        // The timer is used to update the relative timestamps
        this.timer = window.setInterval(() => {
            var _a, _b;
            // Check if component is still mounted
            if (!this.isComponentMounted) {
                this.stopTimer();
                return;
            }
            // Access data only if needed to minimize closure scope
            const sensorData = (_b = (_a = this.store) === null || _a === void 0 ? void 0 : _a.state) === null || _b === void 0 ? void 0 : _b.currentSensorData;
            if (sensorData !== undefined) {
                // Update the data, so that the relative timestamp gets updated
                this.updateData(sensorData);
                // The timestamp is actually not displayed, but is only used to update the state and rerender the DOM
                this.time = Date.now();
            }
        }, 20000);
    }
    stopTimer() {
        clearInterval(this.timer);
        this.timer = null;
    }
    getSeverityLabel(severity) {
        const key = severity !== undefined && severity !== null && severity !== ""
            ? `ui:impact_level.${severity.replace(/-/g, "_")}`
            : "ui:impact_level.unknown";
        return this.store.t(key);
    }
    async componentWillLoad() {
        dayjs.extend(relativeTime);
        this.store = await getStore(this.idKey);
        watchStoreLocale(this, this.store, () => {
            this.updateData(this.store.state.currentSensorData);
        }, { skipForceUpdate: true });
        this.isComponentMounted = true;
        this.updateData(this.store.state.currentSensorData);
        const sensorDataUnsubscribe = this.store.onChange("currentSensorData", (sensorData) => {
            this.updateData(sensorData);
        });
        const errorUnsubscribe = this.store.onChange("error", () => {
            this.updateErrorState();
        });
        this.storeUnsubscribe = () => {
            sensorDataUnsubscribe();
            errorUnsubscribe();
        };
    }
    render() {
        return (h(Host, { key: 'd71dcf935ee5b486ab73f392be61a41edfdca4d3' }, h("slot", { key: 'ff05145909d6a85cee24e76aa479e1050fb7a611' }), h("div", { key: '1f50fd89fc6efa7b913ee93a7cdc54d77d36b223', class: "ls-status-messages" }, !this.hideTitle && (h("div", { key: '5be15933febf9e3225c3078a3786d534788cfc06', class: "title" }, this.componentTitle || this.store.t("ui:status_messages.title"))), this.lastChange === "" && !this.errorState.hasError ? (h("div", { class: "messages" }, h("div", { class: "label" }, this.store.t("ui:status_messages.loading")))) : (h("div", { class: "messages" }, this.errorState.hasError && (h("div", { class: "subtitle" }, this.store.t("ui:status_messages.last_known"))), this.statusMessages.length > 0 ? (this.statusMessages.map((message) => {
            var _a, _b, _c;
            return (h("div", { class: `message ${((_a = statusCodesState[message.id]) === null || _a === void 0 ? void 0 : _a.description.length) > 0 ? "has-status-code" : ""}` }, h("div", { class: "label", title: ((_b = statusCodesState[message.id]) === null || _b === void 0 ? void 0 : _b.description.length) > 0 ? undefined : message.id }, message.description || message.id), ((_c = statusCodesState[message.id]) === null || _c === void 0 ? void 0 : _c.description.length) > 0 && (h("div", { class: "status-code" }, message.id)), h("div", { class: `severity ${message.severity}` }, this.getSeverityLabel(message.severity)), h("div", { class: "human-readable-timestamp" }, message.humanReadableTimestamp), h("div", { class: "timestamp relative-timestamp" }, message.relativeTimestamp)));
        })) : (h("dt", { class: "label" }, this.store.t("ui:status_messages.none"))), this.statusMessages.length === 0 && (h("div", { class: "timestamp" }, this.lastChange)))))));
    }
    disconnectedCallback() {
        this.isComponentMounted = false;
        this.stopTimer();
        // Unsubscribe from store changes
        if (this.storeUnsubscribe !== null) {
            this.storeUnsubscribe();
            this.storeUnsubscribe = null;
        }
    }
    static get is() { return "ls-status-messages"; }
    static get encapsulation() { return "shadow"; }
    static get originalStyleUrls() {
        return {
            "$": ["ls-status-messages.css"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["ls-status-messages.css"]
        };
    }
    static get properties() {
        return {
            "hideTitle": {
                "type": "boolean",
                "attribute": "hide-title",
                "mutable": false,
                "complexType": {
                    "original": "false",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Whether or not to show the title of the component."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "false"
            },
            "severityOptions": {
                "type": "string",
                "attribute": "severity-options",
                "mutable": false,
                "complexType": {
                    "original": "\",impact,informational,non-impact\"",
                    "resolved": "\",impact,informational,non-impact\"",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Allows user to filter messages based on severity"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "\",impact,informational,non-impact\""
            },
            "idKey": {
                "type": "string",
                "attribute": "id-key",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The unique key that is used to identify store data."
                },
                "getter": false,
                "setter": false,
                "reflect": false
            }
        };
    }
    static get states() {
        return {
            "statusMessages": {},
            "lastChange": {},
            "time": {},
            "errorState": {}
        };
    }
}
//# sourceMappingURL=ls-status-messages.js.map
