import * as i0 from '@angular/core';
import { forwardRef, Input, Component, NgModule } from '@angular/core';
import * as i1 from '@angular/forms';
import { Validators, FormsModule, ReactiveFormsModule, NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
import * as i2 from '@c8y/ngx-components';
import { C8yTranslateDirective, FormGroupComponent, RequiredInputPlaceholderDirective, MessagesComponent, MessageDirective, C8yTranslatePipe, CoreModule } from '@c8y/ngx-components';
import * as i1$1 from 'ngx-bootstrap/datepicker';
import { BsDatepickerInputDirective, BsDatepickerDirective, BsDatepickerModule } from 'ngx-bootstrap/datepicker';
import * as i2$1 from 'ngx-bootstrap/timepicker';
import { TimepickerComponent, TimepickerModule } from 'ngx-bootstrap/timepicker';
import { gettext } from '@c8y/ngx-components/gettext';
import { isEmpty } from 'lodash-es';
import { throttleTime } from 'rxjs/operators';

class OperationSchedulerComponent {
    set _minutesAhead(minutes) {
        if (minutes && minutes > this.MINUTES_AHEAD_DEFAULT) {
            this.minutesAhead = minutes;
        }
    }
    constructor(formBuilder, options, dateFormatService) {
        this.formBuilder = formBuilder;
        this.options = options;
        this.dateFormatService = dateFormatService;
        this.placeholder = gettext('Start date');
        this.delayErrors = null;
        this.pickerErrors = null;
        this.DELAY_SECONDS_DEFAULT = 1;
        this.MIN_DELAY_SECONDS_DEFAULT = 0.001;
        this.MAX_DELAY_SECONDS_DEFAULT = 3600;
        this.MINUTES_AHEAD_DEFAULT = 5;
        this.isDelayInSeconds = true;
        this.minutesAhead = this.MINUTES_AHEAD_DEFAULT;
        this.DELAY_KEY_CATEGORY = 'device-control';
        this.MAX_DELAY_KEY_NAME = 'bulkoperation.maxcreationramp';
        this.MIN_DELAY_KEY_NAME = 'bulkoperation.creationramp';
        this.currentUnit = 'seconds';
    }
    ngOnInit() {
        this.minDate = new Date();
        this.initialDate = new Date(this.minDate.setMinutes(this.minDate.getMinutes() + this.minutesAhead));
        this.fgOperationScheduler = this.formBuilder.group({
            picker: ['', [Validators.required, this.dateValidation]],
            time: ['', [Validators.required, this.timeValidation]],
            delay: ['', [Validators.required]],
            unit: ['seconds']
        });
        this.fgOperationScheduler.patchValue({
            picker: this.initialDate,
            time: this.initialDate,
            delay: this.DELAY_SECONDS_DEFAULT
        });
        // Due to the validation of picker and time it could be possible that value changes
        // are emitted more than once. Therefore we throttle the emits.
        const valueChanges$ = this.fgOperationScheduler.valueChanges.pipe(throttleTime(100));
        this.subscription = valueChanges$.subscribe(data => {
            this.delayErrors = this.fgOperationScheduler.controls.delay.errors;
            this.pickerErrors = this.fgOperationScheduler.controls.picker.errors;
            this.convertDelayHandler(data.unit);
            this.emitData(data);
        });
        this.updateDelayValidation();
        this.dateInputFormat = this.dateFormatService.getDateFormat();
    }
    ngOnDestroy() {
        if (this.subscription && !this.subscription.closed) {
            this.subscription.unsubscribe();
        }
    }
    writeValue(value) {
        if (value) {
            this.fgOperationScheduler.patchValue({
                picker: value.scheduledDate,
                time: value.scheduledDate,
                delay: value.delayInSeconds > 1 ? value.delayInSeconds : value.delayInSeconds * 1000,
                unit: value.delayInSeconds > 1 ? 'seconds' : 'milliseconds'
            });
        }
    }
    registerOnChange(fn) {
        this.onChange = fn;
    }
    registerOnTouched(fn) {
        this.onTouched = fn;
    }
    setDisabledState(isDisabled) {
        if (this.fgOperationScheduler?.disabled === isDisabled) {
            return;
        }
        isDisabled ? this.fgOperationScheduler.disable() : this.fgOperationScheduler.enable();
    }
    validate() {
        if (this.fgOperationScheduler.invalid) {
            return {
                ...this.fgOperationScheduler.controls.picker.errors,
                ...this.fgOperationScheduler.controls.time.errors,
                ...this.fgOperationScheduler.controls.delay.errors
            };
        }
    }
    registerOnValidatorChange(fn) {
        this.onValidatorChanged = fn;
    }
    markAsTouched() {
        if (this.onTouched) {
            this.onTouched();
        }
    }
    convertDelayHandler(unit) {
        if (this.currentUnit === unit) {
            return;
        }
        this.currentUnit = unit;
        this.convertDelay(this.currentUnit);
        // update validator on delay control to make sure that
        // switching from minutes to seconds or vice versa does not harm validation.
        this.fgOperationScheduler.controls.delay.setValidators([
            Validators.required,
            Validators.min(this.minDelay),
            Validators.max(this.maxDelay)
        ]);
        this.fgOperationScheduler.controls.delay.updateValueAndValidity();
    }
    emitData(data) {
        if (this.onValidatorChanged) {
            this.onValidatorChanged();
        }
        if (data.picker && data.time) {
            data.picker = this.combineDateAndTime(data.picker, data.time);
        }
        this.convertDelay(this.currentUnit);
        data.delayInSeconds = this.delayInSeconds;
        if (this.onChange) {
            this.onChange({
                delayInSeconds: data.delayInSeconds,
                scheduledDate: data.picker
            });
        }
    }
    async updateDelayValidation() {
        const minSystem = await this.options.getSystemOption(this.DELAY_KEY_CATEGORY, this.MIN_DELAY_KEY_NAME);
        const maxSystem = await this.options.getSystemOption(this.DELAY_KEY_CATEGORY, this.MAX_DELAY_KEY_NAME);
        this.maxDelay = maxSystem ? Number(maxSystem) : this.MAX_DELAY_SECONDS_DEFAULT;
        this.minDelay = minSystem ? Number(minSystem) : this.MIN_DELAY_SECONDS_DEFAULT;
        this.fgOperationScheduler
            .get('delay')
            .setValidators([
            Validators.required,
            Validators.min(this.minDelay),
            Validators.max(this.maxDelay)
        ]);
        this.fgOperationScheduler.updateValueAndValidity();
    }
    convertDelay(unit) {
        this.delayInSeconds = this.fgOperationScheduler.controls.delay.value;
        if (unit === 'seconds' && !this.isDelayInSeconds) {
            this.maxDelay = this.maxDelay / 1000;
            this.minDelay = this.minDelay / 1000;
            this.isDelayInSeconds = true;
        }
        if (unit === 'milliseconds') {
            this.delayInSeconds = this.fgOperationScheduler.controls.delay.value / 1000;
            if (this.isDelayInSeconds) {
                this.maxDelay = this.maxDelay * 1000;
                this.minDelay = this.minDelay * 1000;
                this.isDelayInSeconds = false;
            }
        }
    }
    combineDateAndTime(date, time) {
        return new Date(date.getFullYear(), date.getMonth(), date.getDate(), time.getHours(), time.getMinutes());
    }
    dateValidation(fControl) {
        if (fControl.value) {
            const date = fControl.value;
            fControl.parent.get('time').setValue(date);
            return date >= new Date()
                ? null
                : {
                    dateValidation: true
                };
        }
        return { dateValidation: true };
    }
    timeValidation(fControl) {
        if (fControl.value) {
            const date = fControl.value;
            const result = date >= new Date()
                ? null
                : {
                    dateValidation: true
                };
            const picker = fControl.parent.get('picker');
            if (result) {
                picker.setErrors(result);
                picker.markAsTouched();
                return result;
            }
            if (picker && picker.errors && picker.errors.dateValidation) {
                delete picker.errors.dateValidation;
                if (isEmpty(picker.errors)) {
                    picker.setErrors(null);
                    return result;
                }
                picker.setErrors(picker.errors);
            }
            return result;
        }
        return { dateValidation: true };
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: OperationSchedulerComponent, deps: [{ token: i1.FormBuilder }, { token: i2.OptionsService }, { token: i2.DateFormatService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: OperationSchedulerComponent, isStandalone: true, selector: "c8y-operation-scheduler", inputs: { _minutesAhead: ["minutesAhead", "_minutesAhead"] }, providers: [
            {
                provide: NG_VALUE_ACCESSOR,
                multi: true,
                useExisting: forwardRef(() => OperationSchedulerComponent)
            },
            {
                provide: NG_VALIDATORS,
                multi: true,
                useExisting: forwardRef(() => OperationSchedulerComponent)
            }
        ], ngImport: i0, template: "<div [formGroup]=\"fgOperationScheduler\">\n  <div class=\"form-group\">\n    <label translate>Start date</label>\n    <div class=\"datetime-picker\">\n      <c8y-form-group class=\"datepicker\">\n        <input\n          class=\"form-control\"\n          placeholder=\"{{ placeholder | translate }}\"\n          required\n          formControlName=\"picker\"\n          [bsConfig]=\"{ customTodayClass: 'today', dateInputFormat: dateInputFormat }\"\n          [minDate]=\"minDate\"\n          bsDatepicker\n          (blur)=\"markAsTouched()\"\n        />\n        <c8y-messages>\n          <c8y-message\n            [name]=\"'dateValidation'\"\n            [text]=\"'Select time in the future.' | translate\"\n          ></c8y-message>\n        </c8y-messages>\n      </c8y-form-group>\n      <timepicker\n        class=\"form-group\"\n        [showSpinners]=\"false\"\n        [showMeridian]=\"false\"\n        formControlName=\"time\"\n        (blur)=\"markAsTouched()\"\n      ></timepicker>\n    </div>\n  </div>\n  <div class=\"form-group\">\n    <c8y-form-group [hasError]=\"delayErrors\">\n      <label translate>Delay</label>\n      <div class=\"input-group\">\n        <input\n          class=\"form-control\"\n          placeholder=\"{{ 'e.g.' | translate }} 15\"\n          type=\"number\"\n          required\n          formControlName=\"delay\"\n          (blur)=\"markAsTouched()\"\n        />\n        <div class=\"input-group-btn\">\n          <div class=\"c8y-select-wrapper\">\n            <select\n              class=\"form-control m-r-sm-32 m-r-xs-56\"\n              [attr.aria-label]=\"'Delay units' | translate\"\n              formControlName=\"unit\"\n              (blur)=\"markAsTouched()\"\n            >\n              <option\n                value=\"seconds\"\n                translate\n              >\n                Seconds\n              </option>\n              <option\n                value=\"milliseconds\"\n                translate\n              >\n                Milliseconds\n              </option>\n            </select>\n            <span></span>\n          </div>\n        </div>\n      </div>\n    </c8y-form-group>\n  </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { 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.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { 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.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { 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: "directive", type: RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "directive", type: BsDatepickerInputDirective, selector: "input[bsDatepicker]" }, { kind: "directive", type: BsDatepickerDirective, selector: "[bsDatepicker]", inputs: ["placement", "triggers", "outsideClick", "container", "outsideEsc", "isDisabled", "minDate", "maxDate", "ignoreMinMaxErrors", "minMode", "daysDisabled", "datesDisabled", "datesEnabled", "dateCustomClasses", "dateTooltipTexts", "isOpen", "bsValue", "bsConfig"], outputs: ["onShown", "onHidden", "bsValueChange"], exportAs: ["bsDatepicker"] }, { kind: "component", type: MessagesComponent, selector: "c8y-messages", inputs: ["show", "defaults", "helpMessage", "additionalMessages"] }, { kind: "directive", type: MessageDirective, selector: "c8y-message", inputs: ["name", "text"] }, { kind: "component", type: TimepickerComponent, selector: "timepicker", inputs: ["hourStep", "minuteStep", "secondsStep", "readonlyInput", "disabled", "mousewheel", "arrowkeys", "showSpinners", "showMeridian", "showMinutes", "showSeconds", "meridians", "min", "max", "hoursPlaceholder", "minutesPlaceholder", "secondsPlaceholder"], outputs: ["isValid", "meridianChange"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: OperationSchedulerComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-operation-scheduler', providers: [
                        {
                            provide: NG_VALUE_ACCESSOR,
                            multi: true,
                            useExisting: forwardRef(() => OperationSchedulerComponent)
                        },
                        {
                            provide: NG_VALIDATORS,
                            multi: true,
                            useExisting: forwardRef(() => OperationSchedulerComponent)
                        }
                    ], imports: [
                        FormsModule,
                        ReactiveFormsModule,
                        C8yTranslateDirective,
                        FormGroupComponent,
                        RequiredInputPlaceholderDirective,
                        BsDatepickerInputDirective,
                        BsDatepickerDirective,
                        MessagesComponent,
                        MessageDirective,
                        TimepickerComponent,
                        C8yTranslatePipe
                    ], template: "<div [formGroup]=\"fgOperationScheduler\">\n  <div class=\"form-group\">\n    <label translate>Start date</label>\n    <div class=\"datetime-picker\">\n      <c8y-form-group class=\"datepicker\">\n        <input\n          class=\"form-control\"\n          placeholder=\"{{ placeholder | translate }}\"\n          required\n          formControlName=\"picker\"\n          [bsConfig]=\"{ customTodayClass: 'today', dateInputFormat: dateInputFormat }\"\n          [minDate]=\"minDate\"\n          bsDatepicker\n          (blur)=\"markAsTouched()\"\n        />\n        <c8y-messages>\n          <c8y-message\n            [name]=\"'dateValidation'\"\n            [text]=\"'Select time in the future.' | translate\"\n          ></c8y-message>\n        </c8y-messages>\n      </c8y-form-group>\n      <timepicker\n        class=\"form-group\"\n        [showSpinners]=\"false\"\n        [showMeridian]=\"false\"\n        formControlName=\"time\"\n        (blur)=\"markAsTouched()\"\n      ></timepicker>\n    </div>\n  </div>\n  <div class=\"form-group\">\n    <c8y-form-group [hasError]=\"delayErrors\">\n      <label translate>Delay</label>\n      <div class=\"input-group\">\n        <input\n          class=\"form-control\"\n          placeholder=\"{{ 'e.g.' | translate }} 15\"\n          type=\"number\"\n          required\n          formControlName=\"delay\"\n          (blur)=\"markAsTouched()\"\n        />\n        <div class=\"input-group-btn\">\n          <div class=\"c8y-select-wrapper\">\n            <select\n              class=\"form-control m-r-sm-32 m-r-xs-56\"\n              [attr.aria-label]=\"'Delay units' | translate\"\n              formControlName=\"unit\"\n              (blur)=\"markAsTouched()\"\n            >\n              <option\n                value=\"seconds\"\n                translate\n              >\n                Seconds\n              </option>\n              <option\n                value=\"milliseconds\"\n                translate\n              >\n                Milliseconds\n              </option>\n            </select>\n            <span></span>\n          </div>\n        </div>\n      </div>\n    </c8y-form-group>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i1.FormBuilder }, { type: i2.OptionsService }, { type: i2.DateFormatService }], propDecorators: { _minutesAhead: [{
                type: Input,
                args: ['minutesAhead']
            }] } });

/**
 * This module provides components for scheduling bulk operations.
 */
class BulkOperationSchedulerModule {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: BulkOperationSchedulerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.19", ngImport: i0, type: BulkOperationSchedulerModule, imports: [CoreModule,
            ReactiveFormsModule, i1$1.BsDatepickerModule, i2$1.TimepickerModule, OperationSchedulerComponent], exports: [OperationSchedulerComponent] }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: BulkOperationSchedulerModule, imports: [CoreModule,
            ReactiveFormsModule,
            BsDatepickerModule.forRoot(),
            TimepickerModule.forRoot(),
            OperationSchedulerComponent] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: BulkOperationSchedulerModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [
                        CoreModule,
                        ReactiveFormsModule,
                        BsDatepickerModule.forRoot(),
                        TimepickerModule.forRoot(),
                        OperationSchedulerComponent
                    ],
                    providers: [],
                    exports: [OperationSchedulerComponent]
                }]
        }] });

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

export { BulkOperationSchedulerModule, OperationSchedulerComponent };
//# sourceMappingURL=c8y-ngx-components-operations-bulk-operation-scheduler.mjs.map
