import * as i0 from '@angular/core';
import { signal, inject, DestroyRef, Input, ChangeDetectionStrategy, Component, ViewChild } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import * as i1 from '@angular/forms';
import { Validators, NgForm, ControlContainer, ReactiveFormsModule } from '@angular/forms';
import { DashboardChildComponent, MeasurementRealtimeService, C8yTranslateDirective, IconDirective, LoadingComponent, EmptyStateComponent, DatePipe, C8yTranslatePipe, C8yValidators, FormGroupComponent, MessagesComponent, GuideDocsComponent, GuideHrefDirective } from '@c8y/ngx-components';
import * as i2 from '@c8y/ngx-components/context-dashboard';
import { ContextDashboardComponent } from '@c8y/ngx-components/context-dashboard';
import { DatapointSelectorModule } from '@c8y/ngx-components/datapoint-selector';
import * as i3 from '@c8y/ngx-components/icon-selector';
import { IconSelectorModule } from '@c8y/ngx-components/icon-selector';
import * as i4 from 'ngx-bootstrap/popover';
import { PopoverModule } from 'ngx-bootstrap/popover';
import { share, pairwise, map, startWith, distinctUntilChanged, filter, switchMap, tap, debounceTime } from 'rxjs/operators';
import { GLOBAL_CONTEXT_DISPLAY_MODE, PRESET_NAME, WidgetConfigMigrationService, REFRESH_OPTION, GlobalContextConnectorComponent, LocalControlsComponent } from '@c8y/ngx-components/global-context';
import { merge, isEqual } from 'lodash-es';
import { NEVER, BehaviorSubject, Subject, combineLatest, merge as merge$1 } from 'rxjs';
import { NgClass, NgStyle, AsyncPipe, DecimalPipe } from '@angular/common';

var ColorClass;
(function (ColorClass) {
    ColorClass["danger"] = "text-danger";
    ColorClass["warning"] = "text-warning";
    ColorClass["unknown"] = "";
})(ColorClass || (ColorClass = {}));

class KpiWidgetViewComponent {
    constructor() {
        this.config = { datapoints: [] };
        this.displayMode = signal(GLOBAL_CONTEXT_DISPLAY_MODE.DASHBOARD, ...(ngDevMode ? [{ debugName: "displayMode" }] : []));
        this.contextConfig = signal({}, ...(ngDevMode ? [{ debugName: "contextConfig" }] : []));
        this.isLinkedToGlobal = signal(undefined, ...(ngDevMode ? [{ debugName: "isLinkedToGlobal" }] : []));
        this.widgetControls = signal(PRESET_NAME.KPI, ...(ngDevMode ? [{ debugName: "widgetControls" }] : []));
        this.isHistoryMode = signal(false, ...(ngDevMode ? [{ debugName: "isHistoryMode" }] : []));
        this.state$ = NEVER;
        this.noDataInitiallyInDB = signal(false, ...(ngDevMode ? [{ debugName: "noDataInitiallyInDB" }] : []));
        this.GLOBAL_CONTEXT_DISPLAY_MODE = GLOBAL_CONTEXT_DISPLAY_MODE;
        this.dashboardChild = inject(DashboardChildComponent, { optional: true });
        this.dashboard = inject(ContextDashboardComponent, { optional: true });
        this.measurementRealtime = inject(MeasurementRealtimeService);
        this.widgetConfigMigrationService = inject(WidgetConfigMigrationService);
        this.destroyRef = inject(DestroyRef);
        this.context$ = new BehaviorSubject(null);
        this.refresh$ = new Subject();
        this.lastDatapoint = null;
    }
    ngOnInit() {
        this.config = merge(this.config, this.widgetConfigMigrationService.migrateWidgetConfig(this.config));
        this.syncDisplayState();
        this.buildStatePipeline();
        if (!this.isDashboardMode()) {
            this.emitContext(this.config);
        }
    }
    ngOnChanges(changes) {
        const cfg = changes.config?.currentValue;
        if (!cfg) {
            return;
        }
        this.config = cfg;
        this.syncDisplayState();
        if (this.isOnRealDashboard()) {
            return;
        }
        if (this.isDashboardPreviewWaitingForContext()) {
            return;
        }
        this.emitContext(this.config, this.hasDatapointChanged());
    }
    onContextChange(event) {
        this.contextConfig.set(event.context);
        this.emitContext(event.context);
    }
    onRefresh() {
        this.refresh$.next();
    }
    getDashboardChild() {
        return this.dashboardChild;
    }
    setupObservable(datapoint, context) {
        const isHistory = context.refreshOption === REFRESH_OPTION.HISTORY;
        const isPaused = !isHistory && context.isAutoRefreshEnabled === false;
        this.isHistoryMode.set(isHistory);
        this.noDataInitiallyInDB.set(false);
        let source$;
        if (isPaused) {
            source$ = this.getHistoryMeasurement$(datapoint, {});
        }
        else if (isHistory) {
            source$ = this.getHistoryMeasurement$(datapoint, context);
        }
        else {
            source$ = this.getLiveMeasurement$(datapoint);
        }
        const shared$ = source$.pipe(share());
        const lastTwo$ = shared$.pipe(pairwise());
        return combineLatest([
            shared$,
            lastTwo$.pipe(map(([prev]) => prev), startWith(undefined)),
            this.getTrend$(lastTwo$),
            shared$.pipe(map(m => datapoint.unit || m.unit || ''), startWith(''), distinctUntilChanged()),
            this.getColorClass$(shared$, datapoint)
        ]).pipe(map(([latestMeasurement, previousValue, trend, unit, colorClass]) => ({
            latestMeasurement,
            previousValue,
            trend,
            unit,
            colorClass
        })));
    }
    buildStatePipeline() {
        const readState = () => ({ ctx: this.context$.value, dp: this.findActiveDatapoint() });
        this.state$ = merge$1(this.context$.pipe(map(readState), distinctUntilChanged(isEqual)), this.refresh$.pipe(map(readState))).pipe(filter((s) => !!s.ctx && !!s.dp), switchMap(({ ctx, dp }) => {
            this.assignContextFromContextDashboard(dp);
            return this.setupObservable(dp, ctx).pipe(startWith(null));
        }), takeUntilDestroyed(this.destroyRef));
    }
    syncDisplayState() {
        const newMode = this.resolveDisplayMode();
        if (this.displayMode() !== newMode) {
            this.displayMode.set(newMode);
        }
        const newCtx = this.extractContext(this.config);
        if (!isEqual(this.contextConfig(), newCtx)) {
            this.contextConfig.set(newCtx);
        }
    }
    emitContext(source, force = false) {
        const ctx = this.extractContext(source);
        if (force || !isEqual(this.context$.value, ctx)) {
            this.context$.next(ctx);
        }
    }
    isDashboardMode() {
        return this.resolveDisplayMode() === GLOBAL_CONTEXT_DISPLAY_MODE.DASHBOARD;
    }
    isOnRealDashboard() {
        return this.isDashboardMode() && !!this.dashboardChild;
    }
    isDashboardPreviewWaitingForContext() {
        return this.isDashboardMode() && !this.config.isGlobalContextReady;
    }
    resolveDisplayMode() {
        return (this.config?.displayMode || GLOBAL_CONTEXT_DISPLAY_MODE.VIEW_AND_CONFIG);
    }
    extractContext(source) {
        return {
            dateTimeContext: source.dateTimeContext,
            isAutoRefreshEnabled: source.isAutoRefreshEnabled,
            refreshInterval: source.refreshInterval,
            refreshOption: source.refreshOption
        };
    }
    findActiveDatapoint() {
        return this.config?.datapoints?.find(dp => dp?.__active);
    }
    hasDatapointChanged() {
        const dp = this.findActiveDatapoint();
        if (!dp) {
            return false;
        }
        const prev = this.lastDatapoint;
        this.lastDatapoint = dp;
        return (!prev ||
            dp.fragment !== prev.fragment ||
            dp.series !== prev.series ||
            dp.__target?.id !== prev.__target?.id ||
            dp.unit !== prev.unit ||
            dp.redRangeMin !== prev.redRangeMin ||
            dp.redRangeMax !== prev.redRangeMax ||
            dp.yellowRangeMin !== prev.yellowRangeMin ||
            dp.yellowRangeMax !== prev.yellowRangeMax);
    }
    getLiveMeasurement$(datapoint) {
        return this.measurementRealtime
            .latestValueOfSpecificMeasurement$(datapoint.fragment, datapoint.series, datapoint.__target, this.config.showTrend ? 2 : 1, true)
            .pipe(tap(m => {
            if (!m)
                this.noDataInitiallyInDB.set(true);
        }), filter(m => !!m), map(m => this.toMeasurementValue(m, datapoint)));
    }
    getHistoryMeasurement$(datapoint, context) {
        return this.measurementRealtime
            .lastMeasurement$(datapoint.fragment, datapoint.series, datapoint.__target, 1, true, context.dateTimeContext?.dateFrom, context.dateTimeContext?.dateTo)
            .pipe(tap(m => {
            if (!m)
                this.noDataInitiallyInDB.set(true);
        }), filter(m => !!m), map(m => this.toMeasurementValue(m, datapoint)));
    }
    toMeasurementValue(m, dp) {
        return {
            unit: m[dp.fragment][dp.series].unit,
            value: m[dp.fragment][dp.series].value,
            date: m.time
        };
    }
    getColorClass$(measurement$, datapoint) {
        return measurement$.pipe(map(m => {
            if (this.inRange(datapoint, m.value, 'redRangeMin', 'redRangeMax')) {
                return ColorClass.danger;
            }
            if (this.inRange(datapoint, m.value, 'yellowRangeMin', 'yellowRangeMax')) {
                return ColorClass.warning;
            }
            return ColorClass.unknown;
        }), startWith(ColorClass.unknown), distinctUntilChanged());
    }
    getTrend$(lastTwo$) {
        return lastTwo$.pipe(map(([prev, curr]) => {
            if (prev.value < curr.value)
                return '45deg';
            if (prev.value > curr.value)
                return '135deg';
            return '90deg';
        }), startWith('90deg'), distinctUntilChanged());
    }
    inRange(dp, value, minKey, maxKey) {
        return (typeof dp[minKey] === 'number' &&
            typeof dp[maxKey] === 'number' &&
            value >= dp[minKey] &&
            value < dp[maxKey]);
    }
    assignContextFromContextDashboard(datapoint) {
        if (!this.dashboard?.isDeviceTypeDashboard) {
            return;
        }
        const context = this.dashboard?.context;
        if (context?.id) {
            datapoint.__target = { name: context.name, id: context.id };
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KpiWidgetViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: KpiWidgetViewComponent, isStandalone: true, selector: "c8y-kpi-widget-view", inputs: { config: "config" }, host: { classAttribute: "d-col fit-h" }, providers: [MeasurementRealtimeService], usesOnChanges: true, ngImport: i0, template: "@if (displayMode() === GLOBAL_CONTEXT_DISPLAY_MODE.DASHBOARD && getDashboardChild()) {\n  <c8y-global-context-connector\n    [controls]=\"widgetControls()\"\n    [config]=\"contextConfig()\"\n    [dashboardChild]=\"getDashboardChild()\"\n    [linked]=\"isLinkedToGlobal()\"\n    [propagateAutoRefresh]=\"false\"\n    (configChange)=\"onContextChange($event)\"\n    (refresh)=\"onRefresh()\"\n  ></c8y-global-context-connector>\n} @else if (displayMode() !== GLOBAL_CONTEXT_DISPLAY_MODE.DASHBOARD) {\n  <c8y-local-controls\n    [controls]=\"widgetControls()\"\n    [displayMode]=\"displayMode()\"\n    [config]=\"contextConfig()\"\n    [propagateAutoRefresh]=\"false\"\n    (configChange)=\"onContextChange($event)\"\n    (refresh)=\"onRefresh()\"\n  ></c8y-local-controls>\n}\n\n@if (state$ | async; as lastState) {\n  <div class=\"kpi-widget__container d-flex d-col flex-grow fit-w a-i-center j-c-center\">\n    <div class=\"d-flex a-i-center j-c-center fit-w\">\n      @if (config.icon && config.showIcon) {\n        <div\n          class=\"m-r-16 flex-no-shrink text-muted\"\n          [ngClass]=\"lastState.colorClass\"\n        >\n          <i\n            class=\"icon-32\"\n            [c8yIcon]=\"config.icon\"\n          ></i>\n        </div>\n      }\n      <div class=\"text-truncate\">\n        <span\n          class=\"text-truncate text-medium\"\n          [ngStyle]=\"{ 'font-size': (config.fontSize || '36') + 'px' }\"\n          title=\"{{\n            lastState.colorClass === 'text-danger'\n              ? ('Within red range:' | translate)\n              : lastState.colorClass === 'text-warning'\n                ? ('Within yellow range:' | translate)\n                : ''\n          }} {{\n            lastState.latestMeasurement.value\n              | number\n                : '1.' +\n                    (config.numberOfDecimalPlaces || '0') +\n                    '-' +\n                    (config.numberOfDecimalPlaces || '0')\n          }} {{ lastState.unit || '' }}\"\n          [ngClass]=\"lastState.colorClass\"\n        >\n          {{\n            lastState.latestMeasurement.value\n              | number\n                : '1.' +\n                    (config.numberOfDecimalPlaces || '0') +\n                    '-' +\n                    (config.numberOfDecimalPlaces || '0')\n          }}\n          <small class=\"text-regular\">{{ lastState.unit || '' }}</small>\n        </span>\n      </div>\n      @if (config?.showTrend && lastState.previousValue; as previousValue) {\n        <div class=\"dot dot-info dot-30 m-l-16 flex-no-shrink\">\n          <i\n            class=\"icon-20\"\n            c8yIcon=\"arrow-dotted-up\"\n            [ngStyle]=\"{ transform: 'rotate(' + lastState.trend + ')' }\"\n            [title]=\"\n              ('Previous value' | translate) +\n              ': ' +\n              (previousValue.value\n                | number\n                  : '1.' +\n                      (config.numberOfDecimalPlaces || '0') +\n                      '-' +\n                      (config.numberOfDecimalPlaces || '0')) +\n              ' (' +\n              (previousValue.date | c8yDate: 'medium') +\n              ')'\n            \"\n          ></i>\n        </div>\n      }\n    </div>\n    <div class=\"d-flex d-col a-i-center\">\n      @if (config?.showTimestamp) {\n        <p class=\"icon-flex text-center text-muted small m-b-0\">\n          <i c8yIcon=\"calendar\"></i>\n          {{ lastState.latestMeasurement.date | c8yDate: 'medium' }}\n        </p>\n      }\n      @if (isHistoryMode()) {\n        <p class=\"text-center text-muted small m-b-0\">\n          <span translate>Last measurement in selected time range</span>\n        </p>\n      }\n    </div>\n  </div>\n} @else {\n  <div class=\"d-flex flex-grow fit-w j-c-center a-i-center\">\n    @let noDataSubtitleLive = 'Waiting for measurements to be created.' | translate;\n    @let noDataSubtitleHistory = 'No data available for the selected time period.' | translate;\n    @if (noDataInitiallyInDB()) {\n      <c8y-ui-empty-state\n        [icon]=\"'line-chart'\"\n        [title]=\"'No measurement to display.' | translate\"\n        [subtitle]=\"isHistoryMode() ? noDataSubtitleHistory : noDataSubtitleLive\"\n        [horizontal]=\"true\"\n      ></c8y-ui-empty-state>\n    } @else {\n      <c8y-loading></c8y-loading>\n    }\n  </div>\n}\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "component", type: LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "component", type: GlobalContextConnectorComponent, selector: "c8y-global-context-connector", inputs: ["controls", "config", "isLoading", "dashboardChild", "linked", "propagateAutoRefresh", "emitRefresh"], outputs: ["configChange", "refresh", "linkedChange"] }, { kind: "component", type: LocalControlsComponent, selector: "c8y-local-controls", inputs: ["controls", "displayMode", "config", "isLoading", "disabled", "propagateAutoRefresh", "emitRefresh", "dashboardChild"], outputs: ["configChange", "refresh"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: DatePipe, name: "c8yDate" }, { kind: "pipe", type: DecimalPipe, name: "number" }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KpiWidgetViewComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-kpi-widget-view', standalone: true, imports: [
                        AsyncPipe,
                        DatePipe,
                        DecimalPipe,
                        NgClass,
                        NgStyle,
                        C8yTranslatePipe,
                        C8yTranslateDirective,
                        IconDirective,
                        LoadingComponent,
                        EmptyStateComponent,
                        GlobalContextConnectorComponent,
                        LocalControlsComponent
                    ], providers: [MeasurementRealtimeService], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'd-col fit-h' }, template: "@if (displayMode() === GLOBAL_CONTEXT_DISPLAY_MODE.DASHBOARD && getDashboardChild()) {\n  <c8y-global-context-connector\n    [controls]=\"widgetControls()\"\n    [config]=\"contextConfig()\"\n    [dashboardChild]=\"getDashboardChild()\"\n    [linked]=\"isLinkedToGlobal()\"\n    [propagateAutoRefresh]=\"false\"\n    (configChange)=\"onContextChange($event)\"\n    (refresh)=\"onRefresh()\"\n  ></c8y-global-context-connector>\n} @else if (displayMode() !== GLOBAL_CONTEXT_DISPLAY_MODE.DASHBOARD) {\n  <c8y-local-controls\n    [controls]=\"widgetControls()\"\n    [displayMode]=\"displayMode()\"\n    [config]=\"contextConfig()\"\n    [propagateAutoRefresh]=\"false\"\n    (configChange)=\"onContextChange($event)\"\n    (refresh)=\"onRefresh()\"\n  ></c8y-local-controls>\n}\n\n@if (state$ | async; as lastState) {\n  <div class=\"kpi-widget__container d-flex d-col flex-grow fit-w a-i-center j-c-center\">\n    <div class=\"d-flex a-i-center j-c-center fit-w\">\n      @if (config.icon && config.showIcon) {\n        <div\n          class=\"m-r-16 flex-no-shrink text-muted\"\n          [ngClass]=\"lastState.colorClass\"\n        >\n          <i\n            class=\"icon-32\"\n            [c8yIcon]=\"config.icon\"\n          ></i>\n        </div>\n      }\n      <div class=\"text-truncate\">\n        <span\n          class=\"text-truncate text-medium\"\n          [ngStyle]=\"{ 'font-size': (config.fontSize || '36') + 'px' }\"\n          title=\"{{\n            lastState.colorClass === 'text-danger'\n              ? ('Within red range:' | translate)\n              : lastState.colorClass === 'text-warning'\n                ? ('Within yellow range:' | translate)\n                : ''\n          }} {{\n            lastState.latestMeasurement.value\n              | number\n                : '1.' +\n                    (config.numberOfDecimalPlaces || '0') +\n                    '-' +\n                    (config.numberOfDecimalPlaces || '0')\n          }} {{ lastState.unit || '' }}\"\n          [ngClass]=\"lastState.colorClass\"\n        >\n          {{\n            lastState.latestMeasurement.value\n              | number\n                : '1.' +\n                    (config.numberOfDecimalPlaces || '0') +\n                    '-' +\n                    (config.numberOfDecimalPlaces || '0')\n          }}\n          <small class=\"text-regular\">{{ lastState.unit || '' }}</small>\n        </span>\n      </div>\n      @if (config?.showTrend && lastState.previousValue; as previousValue) {\n        <div class=\"dot dot-info dot-30 m-l-16 flex-no-shrink\">\n          <i\n            class=\"icon-20\"\n            c8yIcon=\"arrow-dotted-up\"\n            [ngStyle]=\"{ transform: 'rotate(' + lastState.trend + ')' }\"\n            [title]=\"\n              ('Previous value' | translate) +\n              ': ' +\n              (previousValue.value\n                | number\n                  : '1.' +\n                      (config.numberOfDecimalPlaces || '0') +\n                      '-' +\n                      (config.numberOfDecimalPlaces || '0')) +\n              ' (' +\n              (previousValue.date | c8yDate: 'medium') +\n              ')'\n            \"\n          ></i>\n        </div>\n      }\n    </div>\n    <div class=\"d-flex d-col a-i-center\">\n      @if (config?.showTimestamp) {\n        <p class=\"icon-flex text-center text-muted small m-b-0\">\n          <i c8yIcon=\"calendar\"></i>\n          {{ lastState.latestMeasurement.date | c8yDate: 'medium' }}\n        </p>\n      }\n      @if (isHistoryMode()) {\n        <p class=\"text-center text-muted small m-b-0\">\n          <span translate>Last measurement in selected time range</span>\n        </p>\n      }\n    </div>\n  </div>\n} @else {\n  <div class=\"d-flex flex-grow fit-w j-c-center a-i-center\">\n    @let noDataSubtitleLive = 'Waiting for measurements to be created.' | translate;\n    @let noDataSubtitleHistory = 'No data available for the selected time period.' | translate;\n    @if (noDataInitiallyInDB()) {\n      <c8y-ui-empty-state\n        [icon]=\"'line-chart'\"\n        [title]=\"'No measurement to display.' | translate\"\n        [subtitle]=\"isHistoryMode() ? noDataSubtitleHistory : noDataSubtitleLive\"\n        [horizontal]=\"true\"\n      ></c8y-ui-empty-state>\n    } @else {\n      <c8y-loading></c8y-loading>\n    }\n  </div>\n}\n" }]
        }], propDecorators: { config: [{
                type: Input
            }] } });

function exactlyASingleDatapointActive() {
    return (control) => {
        const datapoints = control.value;
        if (!datapoints?.length) {
            return null;
        }
        return datapoints.filter(dp => dp.__active).length === 1
            ? null
            : { exactlyOneDatapointNeedsToBeActive: true };
    };
}
class KpiWidgetConfigComponent {
    set previewMapSet(template) {
        this.widgetConfigService.setPreview(template || null);
    }
    constructor(formBuilder, form, widgetConfig, widgetConfigService) {
        this.formBuilder = formBuilder;
        this.form = form;
        this.widgetConfig = widgetConfig;
        this.widgetConfigService = widgetConfigService;
        this.datapointSelectionConfig = {};
        this.defaultFormOptions = {
            showRedRange: true,
            showYellowRange: true
        };
        this.destroyRef = inject(DestroyRef);
        this.limits = {
            fontSizeMax: 72,
            fontSizeMin: 18,
            numberOfDecimalPlacesMax: 10,
            numberOfDecimalPlacesMin: 0
        };
    }
    onBeforeSave(config) {
        if (this.formGroup.valid) {
            Object.assign(config, this.formGroup.value);
            return true;
        }
        return false;
    }
    ngOnChanges(changes) {
        if (this.formGroup && changes.config) {
            this.formGroup.controls.datapoints.patchValue(this.config.datapoints || []);
        }
    }
    ngOnInit() {
        if (this.widgetConfig.context?.id) {
            this.datapointSelectionConfig.contextAsset = this.widgetConfig.context;
        }
        this.previewConfig = { ...this.config };
        this.initForm();
        if (this.config?.datapoints) {
            this.formGroup.patchValue({ datapoints: this.config.datapoints });
            this.previewActiveDatapoint = this.config.datapoints.find(dp => dp.__active);
        }
        this.widgetConfigService.currentConfig$
            .pipe(filter(c => !!c), takeUntilDestroyed(this.destroyRef))
            .subscribe(c => {
            this.previewConfig = { ...this.previewConfig, ...c, ...this.formGroup.value };
        });
    }
    initForm() {
        this.formGroup = this.createForm();
        this.form.form.addControl('config', this.formGroup);
        this.formGroup.patchValue(this.config);
        this.formGroup.valueChanges
            .pipe(debounceTime(100), takeUntilDestroyed(this.destroyRef))
            .subscribe(formValue => {
            if (formValue.datapoints) {
                this.previewActiveDatapoint = formValue.datapoints.find(dp => dp.__active);
            }
            if (this.formGroup.valid) {
                this.previewConfig = { ...this.config, ...this.applyLimitsToPreview(formValue) };
            }
            Object.assign(this.config, formValue);
        });
    }
    applyLimitsToPreview(formValue) {
        const result = { ...formValue };
        if (result.numberOfDecimalPlaces !== undefined) {
            result.numberOfDecimalPlaces = this.clamp(result.numberOfDecimalPlaces, this.limits.numberOfDecimalPlacesMin, this.limits.numberOfDecimalPlacesMax);
        }
        if (result.fontSize !== undefined) {
            result.fontSize = this.clamp(result.fontSize, this.limits.fontSizeMin, this.limits.fontSizeMax);
        }
        return result;
    }
    clamp(value, min, max) {
        return Math.max(min, Math.min(max, value));
    }
    createForm() {
        return this.formBuilder.group({
            numberOfDecimalPlaces: [
                2,
                [
                    Validators.required,
                    Validators.min(this.limits.numberOfDecimalPlacesMin),
                    Validators.max(this.limits.numberOfDecimalPlacesMax),
                    C8yValidators.integerValidator()
                ]
            ],
            showTimestamp: [true, []],
            showTrend: [true, []],
            showIcon: [true, []],
            icon: ['water', [Validators.required, Validators.minLength(1)]],
            fontSize: [
                36,
                [
                    Validators.required,
                    Validators.min(this.limits.fontSizeMin),
                    Validators.max(this.limits.fontSizeMax)
                ]
            ],
            datapoints: this.formBuilder.control(new Array(), [
                Validators.required,
                Validators.minLength(1),
                exactlyASingleDatapointActive()
            ])
        });
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KpiWidgetConfigComponent, deps: [{ token: i1.FormBuilder }, { token: i1.NgForm }, { token: i2.WidgetConfigComponent }, { token: i2.WidgetConfigService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: KpiWidgetConfigComponent, isStandalone: true, selector: "c8y-kpi-widget-config", inputs: { config: "config" }, viewQueries: [{ propertyName: "previewMapSet", first: true, predicate: ["kpiPreview"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<form [formGroup]=\"formGroup\">\n  <fieldset class=\"c8y-fieldset\">\n    <legend>{{ 'Layout' | translate }}</legend>\n    <div class=\"d-flex a-i-center gap-8\">\n      <div class=\"form-group form-group-sm m-b-24\">\n        <label translate>Icon</label>\n        <c8y-icon-selector-wrapper\n          [iconSize]=\"16\"\n          name=\"icon\"\n          formControlName=\"icon\"\n        ></c8y-icon-selector-wrapper>\n      </div>\n      <c8y-form-group class=\"form-group-sm m-b-24 flex-grow\">\n        <label\n          [title]=\"'Font size of measurement value (px)' | translate\"\n          translate\n        >\n          Font size of measurement value (px)\n        </label>\n        <input\n          class=\"form-control\"\n          name=\"fontSize\"\n          type=\"number\"\n          formControlName=\"fontSize\"\n          [placeholder]=\"'e.g. {{ example }}' | translate: { example: 36 }\"\n        />\n        <c8y-messages [show]=\"formGroup.controls?.fontSize?.errors\"></c8y-messages>\n      </c8y-form-group>\n    </div>\n  </fieldset>\n\n  <fieldset class=\"c8y-fieldset\">\n    <legend>{{ 'Display' | translate }}</legend>\n    <div class=\"d-flex gap-16 flex-wrap p-t-4 p-b-8 m-b-4\">\n      <c8y-form-group class=\"m-b-0\">\n        <label\n          class=\"c8y-checkbox\"\n          [title]=\"'Show timestamp' | translate\"\n        >\n          <input\n            name=\"showTimestamp\"\n            type=\"checkbox\"\n            formControlName=\"showTimestamp\"\n          />\n          <span></span>\n          <span translate>Show timestamp</span>\n        </label>\n      </c8y-form-group>\n\n      <c8y-form-group class=\"m-b-0\">\n        <label\n          class=\"c8y-checkbox\"\n          [title]=\"'Show icon' | translate\"\n        >\n          <input\n            name=\"showIcon\"\n            type=\"checkbox\"\n            formControlName=\"showIcon\"\n          />\n          <span></span>\n          <span translate>Show icon</span>\n        </label>\n      </c8y-form-group>\n\n      <c8y-form-group class=\"m-b-0\">\n        <label\n          class=\"c8y-checkbox\"\n          [title]=\"'Show trend icon' | translate\"\n        >\n          <input\n            name=\"showTrend\"\n            type=\"checkbox\"\n            formControlName=\"showTrend\"\n          />\n          <span></span>\n          <span translate>Show trend icon</span>\n          <button\n            class=\"btn-help btn-help--sm\"\n            [attr.aria-label]=\"'Help' | translate\"\n            popover=\"{{\n              'Indicates the trend between the last two measurement values.' | translate\n            }}\"\n            placement=\"top\"\n            triggers=\"focus\"\n            container=\"body\"\n            type=\"button\"\n          ></button>\n        </label>\n      </c8y-form-group>\n    </div>\n  </fieldset>\n\n  <fieldset class=\"c8y-fieldset\">\n    <legend translate>Number of decimal places</legend>\n    <c8y-form-group class=\"form-group-sm p-t-4\">\n      <input\n        class=\"form-control\"\n        name=\"numberOfDecimalPlaces\"\n        type=\"number\"\n        formControlName=\"numberOfDecimalPlaces\"\n        [placeholder]=\"'e.g. {{ example }}' | translate: { example: 1 }\"\n      />\n      <c8y-messages [show]=\"formGroup.controls?.numberOfDecimalPlaces?.errors\"></c8y-messages>\n    </c8y-form-group>\n  </fieldset>\n</form>\n\n<ng-template #kpiPreview>\n  @if (formGroup && formGroup.value) {\n    @if (formGroup.value.datapoints?.length > 0 && previewActiveDatapoint) {\n      <div style=\"height: 300px\">\n        <c8y-kpi-widget-view [config]=\"previewConfig\"></c8y-kpi-widget-view>\n      </div>\n    } @else {\n      <div class=\"col-md-6 d-col a-i-start j-c-center\">\n        <c8y-ui-empty-state\n          [icon]=\"'c8y-data-points'\"\n          [title]=\"'No data points selected' | translate\"\n          [subtitle]=\"'Select data point to render content' | translate\"\n          [horizontal]=\"false\"\n          data-cy=\"kpi-widget--empty-state-no-data-point-selected\"\n        >\n          <p c8y-guide-docs>\n            <small\n              translate\n              ngNonBindable\n            >\n              Find out more in the\n              <a c8y-guide-href=\"/docs/cockpit/widgets-collection/#kpi\">user documentation</a>.\n            </small>\n          </p>\n        </c8y-ui-empty-state>\n      </div>\n    }\n  }\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "component", type: MessagesComponent, selector: "c8y-messages", inputs: ["show", "defaults", "helpMessage", "additionalMessages"] }, { kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "component", type: GuideDocsComponent, selector: "[c8y-guide-docs]" }, { kind: "directive", type: GuideHrefDirective, selector: "[c8y-guide-href]", inputs: ["c8y-guide-href"] }, { kind: "ngmodule", type: DatapointSelectorModule }, { kind: "ngmodule", type: IconSelectorModule }, { kind: "component", type: i3.IconSelectorWrapperComponent, selector: "c8y-icon-selector-wrapper", inputs: ["canRemoveIcon", "selectedIcon", "iconSize"], outputs: ["onSelect"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "directive", type: i4.PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "component", type: KpiWidgetViewComponent, selector: "c8y-kpi-widget-view", inputs: ["config"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }], viewProviders: [{ provide: ControlContainer, useExisting: NgForm }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KpiWidgetConfigComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-kpi-widget-config', standalone: true, imports: [
                        ReactiveFormsModule,
                        C8yTranslatePipe,
                        C8yTranslateDirective,
                        FormGroupComponent,
                        MessagesComponent,
                        EmptyStateComponent,
                        GuideDocsComponent,
                        GuideHrefDirective,
                        DatapointSelectorModule,
                        IconSelectorModule,
                        PopoverModule,
                        KpiWidgetViewComponent
                    ], viewProviders: [{ provide: ControlContainer, useExisting: NgForm }], changeDetection: ChangeDetectionStrategy.OnPush, template: "<form [formGroup]=\"formGroup\">\n  <fieldset class=\"c8y-fieldset\">\n    <legend>{{ 'Layout' | translate }}</legend>\n    <div class=\"d-flex a-i-center gap-8\">\n      <div class=\"form-group form-group-sm m-b-24\">\n        <label translate>Icon</label>\n        <c8y-icon-selector-wrapper\n          [iconSize]=\"16\"\n          name=\"icon\"\n          formControlName=\"icon\"\n        ></c8y-icon-selector-wrapper>\n      </div>\n      <c8y-form-group class=\"form-group-sm m-b-24 flex-grow\">\n        <label\n          [title]=\"'Font size of measurement value (px)' | translate\"\n          translate\n        >\n          Font size of measurement value (px)\n        </label>\n        <input\n          class=\"form-control\"\n          name=\"fontSize\"\n          type=\"number\"\n          formControlName=\"fontSize\"\n          [placeholder]=\"'e.g. {{ example }}' | translate: { example: 36 }\"\n        />\n        <c8y-messages [show]=\"formGroup.controls?.fontSize?.errors\"></c8y-messages>\n      </c8y-form-group>\n    </div>\n  </fieldset>\n\n  <fieldset class=\"c8y-fieldset\">\n    <legend>{{ 'Display' | translate }}</legend>\n    <div class=\"d-flex gap-16 flex-wrap p-t-4 p-b-8 m-b-4\">\n      <c8y-form-group class=\"m-b-0\">\n        <label\n          class=\"c8y-checkbox\"\n          [title]=\"'Show timestamp' | translate\"\n        >\n          <input\n            name=\"showTimestamp\"\n            type=\"checkbox\"\n            formControlName=\"showTimestamp\"\n          />\n          <span></span>\n          <span translate>Show timestamp</span>\n        </label>\n      </c8y-form-group>\n\n      <c8y-form-group class=\"m-b-0\">\n        <label\n          class=\"c8y-checkbox\"\n          [title]=\"'Show icon' | translate\"\n        >\n          <input\n            name=\"showIcon\"\n            type=\"checkbox\"\n            formControlName=\"showIcon\"\n          />\n          <span></span>\n          <span translate>Show icon</span>\n        </label>\n      </c8y-form-group>\n\n      <c8y-form-group class=\"m-b-0\">\n        <label\n          class=\"c8y-checkbox\"\n          [title]=\"'Show trend icon' | translate\"\n        >\n          <input\n            name=\"showTrend\"\n            type=\"checkbox\"\n            formControlName=\"showTrend\"\n          />\n          <span></span>\n          <span translate>Show trend icon</span>\n          <button\n            class=\"btn-help btn-help--sm\"\n            [attr.aria-label]=\"'Help' | translate\"\n            popover=\"{{\n              'Indicates the trend between the last two measurement values.' | translate\n            }}\"\n            placement=\"top\"\n            triggers=\"focus\"\n            container=\"body\"\n            type=\"button\"\n          ></button>\n        </label>\n      </c8y-form-group>\n    </div>\n  </fieldset>\n\n  <fieldset class=\"c8y-fieldset\">\n    <legend translate>Number of decimal places</legend>\n    <c8y-form-group class=\"form-group-sm p-t-4\">\n      <input\n        class=\"form-control\"\n        name=\"numberOfDecimalPlaces\"\n        type=\"number\"\n        formControlName=\"numberOfDecimalPlaces\"\n        [placeholder]=\"'e.g. {{ example }}' | translate: { example: 1 }\"\n      />\n      <c8y-messages [show]=\"formGroup.controls?.numberOfDecimalPlaces?.errors\"></c8y-messages>\n    </c8y-form-group>\n  </fieldset>\n</form>\n\n<ng-template #kpiPreview>\n  @if (formGroup && formGroup.value) {\n    @if (formGroup.value.datapoints?.length > 0 && previewActiveDatapoint) {\n      <div style=\"height: 300px\">\n        <c8y-kpi-widget-view [config]=\"previewConfig\"></c8y-kpi-widget-view>\n      </div>\n    } @else {\n      <div class=\"col-md-6 d-col a-i-start j-c-center\">\n        <c8y-ui-empty-state\n          [icon]=\"'c8y-data-points'\"\n          [title]=\"'No data points selected' | translate\"\n          [subtitle]=\"'Select data point to render content' | translate\"\n          [horizontal]=\"false\"\n          data-cy=\"kpi-widget--empty-state-no-data-point-selected\"\n        >\n          <p c8y-guide-docs>\n            <small\n              translate\n              ngNonBindable\n            >\n              Find out more in the\n              <a c8y-guide-href=\"/docs/cockpit/widgets-collection/#kpi\">user documentation</a>.\n            </small>\n          </p>\n        </c8y-ui-empty-state>\n      </div>\n    }\n  }\n</ng-template>\n" }]
        }], ctorParameters: () => [{ type: i1.FormBuilder }, { type: i1.NgForm }, { type: i2.WidgetConfigComponent }, { type: i2.WidgetConfigService }], propDecorators: { previewMapSet: [{
                type: ViewChild,
                args: ['kpiPreview']
            }], config: [{
                type: Input
            }] } });

/**
 * Generated bundle index. Do not edit.
 */

export { ColorClass, KpiWidgetConfigComponent, KpiWidgetViewComponent, exactlyASingleDatapointActive };
//# sourceMappingURL=c8y-ngx-components-widgets-implementations-kpi.mjs.map
