import * as i0 from '@angular/core';
import { Input, Optional, Component, ViewChild } from '@angular/core';
import { BehaviorSubject, Subject, takeUntil } from 'rxjs';
import { filter, map, distinctUntilChanged, switchMap, shareReplay, debounceTime } from 'rxjs/operators';
import * as i1 from '@angular/forms';
import { Validators, ReactiveFormsModule } from '@angular/forms';
import * as i2 from '@c8y/ngx-components/context-dashboard';
import * as i4 from '@c8y/ngx-components';
import { DynamicComponentAlert, RangeDisplayModule, MeasurementRealtimeService, CoreModule } from '@c8y/ngx-components';
import * as i3 from '@c8y/ngx-components/datapoint-selector';
import { DatapointSelectorModule } from '@c8y/ngx-components/datapoint-selector';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { gettext } from '@c8y/ngx-components/gettext';
import { defaultWidgetIds } from '@c8y/ngx-components/widgets/definitions';
import * as i5 from '@angular/common';
import { NgIf, NgClass, AsyncPipe } from '@angular/common';

class LinearGaugeWidgetViewComponent {
    constructor(measurementRealtime, dashboard, dynamicComponent) {
        this.measurementRealtime = measurementRealtime;
        this.dashboard = dashboard;
        this.dynamicComponent = dynamicComponent;
        this.activeDatapoint$ = new BehaviorSubject(null);
        const activeDatapoint = this.activeDatapoint$.pipe(filter(dp => !!dp), map(dp => this.assignContextFromContextDashboard(dp)), distinctUntilChanged());
        this.rangeDisplayConfig$ = activeDatapoint.pipe(switchMap(dp => this.getRangeDisplayConfig$(dp)), shareReplay({ refCount: true, bufferSize: 1 }));
        this.rangeDisplayConfig$
            .pipe(map(data => this.getErrorType(data)), distinctUntilChanged(), takeUntilDestroyed())
            .subscribe(inRange => this.updateAlertStatus(inRange));
    }
    ngOnChanges() {
        const activeDp = this.config.datapoints.find(dp => dp.__active);
        this.activeDatapoint$.next(activeDp);
    }
    getRangeDisplayConfig$(dp) {
        return this.measurementRealtime
            .latestValueOfSpecificMeasurement$(dp.fragment, dp.series, dp.__target, 1, true)
            .pipe(map(m => {
            if (!m) {
                return null;
            }
            const date = m.time;
            const measurement = m[dp.fragment][dp.series];
            return {
                current: measurement.value,
                fractionSize: this.config.fractionSize || 1,
                max: this.ensureIsNumber(dp.max),
                min: this.ensureIsNumber(dp.min),
                redRangeMax: this.ensureIsNumber(dp.redRangeMax),
                redRangeMin: this.ensureIsNumber(dp.redRangeMin),
                target: this.ensureIsNumber(dp.target),
                time: date,
                yellowRangeMax: this.ensureIsNumber(dp.yellowRangeMax),
                yellowRangeMin: this.ensureIsNumber(dp.yellowRangeMin),
                unit: measurement.unit || dp.unit,
                orientation: this.getOrientation()
            };
        }));
    }
    ensureIsNumber(value) {
        if (typeof value === 'number') {
            return value;
        }
        if (typeof value === 'string' && value.trim().length > 0) {
            const parsedValue = parseFloat(value);
            if (!isNaN(parsedValue)) {
                return parsedValue;
            }
        }
        return undefined;
    }
    assignContextFromContextDashboard(datapoint) {
        if (!this.dashboard?.isDeviceTypeDashboard) {
            return datapoint;
        }
        const context = this.dashboard?.context;
        if (context?.id) {
            const { name, id } = context;
            datapoint.__target = { name, id };
        }
        return datapoint;
    }
    getOrientation() {
        return this.dynamicComponent?.componentId === defaultWidgetIds.LINEAR_GAUGE
            ? 'horizontal'
            : 'vertical';
    }
    getErrorType(data) {
        if (!data) {
            return 'NOT_FOUND';
        }
        if (!this.isInRange(data)) {
            return 'OUT_OF_RANGE';
        }
        return 'NONE';
    }
    isInRange(data) {
        if (!Number.isFinite(data.max) || !Number.isFinite(data.min)) {
            // default range is 0-100
            return data.current <= 100 && data.current >= 0;
        }
        return data.current <= data.max && data.current >= data.min;
    }
    updateAlertStatus(errorType) {
        if (!this.alerts) {
            return;
        }
        this.alerts.clear();
        let msg;
        if (errorType === 'OUT_OF_RANGE') {
            msg = gettext('Current value out of defined range.');
        }
        else if (errorType === 'NOT_FOUND') {
            msg = gettext('Configured data point not available on the selected device.');
        }
        if (!msg) {
            return;
        }
        this.alerts.addAlerts(new DynamicComponentAlert({
            type: 'warning',
            text: msg
        }));
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: LinearGaugeWidgetViewComponent, deps: [{ token: i4.MeasurementRealtimeService }, { token: i2.ContextDashboardComponent, optional: true }, { token: i4.DynamicComponentComponent, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: LinearGaugeWidgetViewComponent, isStandalone: true, selector: "c8y-linear-gauge-widget-view", inputs: { config: "config" }, providers: [MeasurementRealtimeService], usesOnChanges: true, ngImport: i0, template: "<div\n  class=\"p-l-16 p-r-16 p-b-16 fit-h d-flex d-col flex-center\"\n  *ngIf=\"rangeDisplayConfig$ | async as rangeDisplayConfig\"\n  [ngClass]=\"{\n    'p-t-40 j-c-center': rangeDisplayConfig.orientation === 'horizontal',\n  }\"\n>\n  <c8y-range-display [config]=\"rangeDisplayConfig\" [ngClass]=\"{'flex-grow': rangeDisplayConfig.orientation == 'vertical'}\"></c8y-range-display>\n</div>\n", dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: RangeDisplayModule }, { kind: "component", type: i4.RangeDisplayComponent, selector: "c8y-range-display", inputs: ["config", "display"] }, { kind: "pipe", type: AsyncPipe, name: "async" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: LinearGaugeWidgetViewComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-linear-gauge-widget-view', providers: [MeasurementRealtimeService], standalone: true, imports: [NgIf, NgClass, AsyncPipe, RangeDisplayModule], template: "<div\n  class=\"p-l-16 p-r-16 p-b-16 fit-h d-flex d-col flex-center\"\n  *ngIf=\"rangeDisplayConfig$ | async as rangeDisplayConfig\"\n  [ngClass]=\"{\n    'p-t-40 j-c-center': rangeDisplayConfig.orientation === 'horizontal',\n  }\"\n>\n  <c8y-range-display [config]=\"rangeDisplayConfig\" [ngClass]=\"{'flex-grow': rangeDisplayConfig.orientation == 'vertical'}\"></c8y-range-display>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i4.MeasurementRealtimeService }, { type: i2.ContextDashboardComponent, decorators: [{
                    type: Optional
                }] }, { type: i4.DynamicComponentComponent, decorators: [{
                    type: Optional
                }] }], propDecorators: { config: [{
                type: Input
            }] } });

class LinearGaugeWidgetConfigComponent {
    set previewMapSet(template) {
        if (template) {
            this.widgetConfigService.setPreview(template);
            return;
        }
        this.widgetConfigService.setPreview(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,
            showRange: true,
            showTarget: true
        };
        this.limits = {
            numberOfDecimalPlacesMax: 10,
            numberOfDecimalPlacesMin: 0
        };
        this.destroy$ = new Subject();
    }
    onBeforeSave(config) {
        if (this.formGroup.valid) {
            Object.assign(config, this.formGroup.value);
            return true;
        }
        return false;
    }
    ngOnInit() {
        if (this.widgetConfig.context?.id) {
            this.datapointSelectionConfig.contextAsset = this.widgetConfig?.context;
        }
        // Initialize preview config
        this.previewConfig = { ...this.config };
        this.initForm();
        if (this.config?.datapoints) {
            this.formGroup.patchValue({ datapoints: this.config.datapoints });
        }
        if (typeof this.config?.fractionSize === 'number' && !Number.isNaN(this.config?.fractionSize)) {
            this.formGroup.patchValue({ fractionSize: this.config.fractionSize });
        }
    }
    ngOnDestroy() {
        this.destroy$.next();
        this.destroy$.complete();
    }
    initForm() {
        this.formGroup = this.createForm();
        this.form.form.addControl('config', this.formGroup);
        this.formGroup.patchValue(this.config);
        // Update preview on form changes
        this.formGroup.valueChanges
            .pipe(debounceTime(100), takeUntil(this.destroy$))
            .subscribe(formValue => {
            if (formValue.datapoints) {
                this.previewActiveDatapoint = formValue.datapoints.find(dp => dp.__active);
            }
            this.previewConfig = { ...this.config, ...formValue };
            Object.assign(this.config, formValue);
        });
    }
    createForm() {
        return this.formBuilder.group({
            fractionSize: [
                2,
                [
                    Validators.required,
                    Validators.min(this.limits.numberOfDecimalPlacesMin),
                    Validators.max(this.limits.numberOfDecimalPlacesMax)
                ]
            ],
            datapoints: this.formBuilder.control(new Array(), [Validators.required])
        });
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: LinearGaugeWidgetConfigComponent, deps: [{ token: i1.FormBuilder }, { token: i1.NgForm }, { token: i2.WidgetConfigComponent }, { token: i2.WidgetConfigService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: LinearGaugeWidgetConfigComponent, isStandalone: true, selector: "c8y-linear-gauge-widget-config", inputs: { config: "config" }, viewQueries: [{ propertyName: "previewMapSet", first: true, predicate: ["linearGaugePreview"], descendants: true }], ngImport: i0, template: "<form\n  class=\"no-card-context\"\n  [formGroup]=\"formGroup\"\n>\n  <c8y-datapoint-selection-list\n    class=\"bg-inherit d-block\"\n    name=\"datapoints\"\n    [defaultFormOptions]=\"defaultFormOptions\"\n    [config]=\"datapointSelectionConfig\"\n    [minActiveCount]=\"1\"\n    [maxActiveCount]=\"1\"\n    formControlName=\"datapoints\"\n  ></c8y-datapoint-selection-list>\n  <fieldset class=\"c8y-fieldset\">\n    <legend translate>Decimal places</legend>\n    <c8y-form-group class=\"form-group-sm m-b-16\">\n      <input\n        class=\"form-control\"\n        name=\"fractionSize\"\n        type=\"number\"\n        formControlName=\"fractionSize\"\n        step=\"1\"\n      />\n      <c8y-messages [show]=\"formGroup.controls.fractionSize.errors\"></c8y-messages>\n    </c8y-form-group>\n  </fieldset>\n</form>\n\n<ng-template #linearGaugePreview>\n  <ng-container *ngIf=\"formGroup && formGroup.value\">\n    <div\n      style=\"height: 300px\"\n      *ngIf=\"formGroup.value.datapoints?.length > 0 && previewActiveDatapoint; else emptyState\"\n    >\n      <c8y-linear-gauge-widget-view\n        *ngIf=\"previewConfig\"\n        [config]=\"previewConfig\"\n      ></c8y-linear-gauge-widget-view>\n    </div>\n    <ng-template #emptyState>\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=\"linear-gauge--empty-state-no-data-point-selected\"\n        >\n          <p c8y-guide-docs>\n            <small translate>\n              Find out more in the\n              <a c8y-guide-href=\"/docs/cockpit/widgets-collection/#linear-gauge\">\n                user documentation\n              </a>\n              .\n            </small>\n          </p>\n        </c8y-ui-empty-state>\n      </div>\n    </ng-template>\n  </ng-container>\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: DatapointSelectorModule }, { kind: "component", type: i3.DatapointSelectionListComponent, selector: "c8y-datapoint-selection-list", inputs: ["actions", "allowDragAndDrop", "config", "defaultFormOptions", "maxActiveCount", "minActiveCount", "resolveContext", "listTitle"], outputs: ["isValid", "change"] }, { 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.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: "ngmodule", type: CoreModule }, { kind: "component", type: i4.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: i4.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i4.FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "component", type: i4.MessagesComponent, selector: "c8y-messages", inputs: ["show", "defaults", "helpMessage"] }, { kind: "directive", type: i4.RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "directive", type: i4.GuideHrefDirective, selector: "[c8y-guide-href]", inputs: ["c8y-guide-href"] }, { kind: "component", type: i4.GuideDocsComponent, selector: "[c8y-guide-docs]" }, { kind: "component", type: LinearGaugeWidgetViewComponent, selector: "c8y-linear-gauge-widget-view", inputs: ["config"] }, { kind: "pipe", type: i4.C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: LinearGaugeWidgetConfigComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-linear-gauge-widget-config', standalone: true, imports: [
                        DatapointSelectorModule,
                        ReactiveFormsModule,
                        CoreModule,
                        LinearGaugeWidgetViewComponent
                    ], template: "<form\n  class=\"no-card-context\"\n  [formGroup]=\"formGroup\"\n>\n  <c8y-datapoint-selection-list\n    class=\"bg-inherit d-block\"\n    name=\"datapoints\"\n    [defaultFormOptions]=\"defaultFormOptions\"\n    [config]=\"datapointSelectionConfig\"\n    [minActiveCount]=\"1\"\n    [maxActiveCount]=\"1\"\n    formControlName=\"datapoints\"\n  ></c8y-datapoint-selection-list>\n  <fieldset class=\"c8y-fieldset\">\n    <legend translate>Decimal places</legend>\n    <c8y-form-group class=\"form-group-sm m-b-16\">\n      <input\n        class=\"form-control\"\n        name=\"fractionSize\"\n        type=\"number\"\n        formControlName=\"fractionSize\"\n        step=\"1\"\n      />\n      <c8y-messages [show]=\"formGroup.controls.fractionSize.errors\"></c8y-messages>\n    </c8y-form-group>\n  </fieldset>\n</form>\n\n<ng-template #linearGaugePreview>\n  <ng-container *ngIf=\"formGroup && formGroup.value\">\n    <div\n      style=\"height: 300px\"\n      *ngIf=\"formGroup.value.datapoints?.length > 0 && previewActiveDatapoint; else emptyState\"\n    >\n      <c8y-linear-gauge-widget-view\n        *ngIf=\"previewConfig\"\n        [config]=\"previewConfig\"\n      ></c8y-linear-gauge-widget-view>\n    </div>\n    <ng-template #emptyState>\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=\"linear-gauge--empty-state-no-data-point-selected\"\n        >\n          <p c8y-guide-docs>\n            <small translate>\n              Find out more in the\n              <a c8y-guide-href=\"/docs/cockpit/widgets-collection/#linear-gauge\">\n                user documentation\n              </a>\n              .\n            </small>\n          </p>\n        </c8y-ui-empty-state>\n      </div>\n    </ng-template>\n  </ng-container>\n</ng-template>\n" }]
        }], ctorParameters: () => [{ type: i1.FormBuilder }, { type: i1.NgForm }, { type: i2.WidgetConfigComponent }, { type: i2.WidgetConfigService }], propDecorators: { previewMapSet: [{
                type: ViewChild,
                args: ['linearGaugePreview']
            }], config: [{
                type: Input
            }] } });

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

export { LinearGaugeWidgetConfigComponent, LinearGaugeWidgetViewComponent };
//# sourceMappingURL=c8y-ngx-components-widgets-implementations-linear-gauge.mjs.map
