import * as i0 from '@angular/core';
import { Injectable, EventEmitter, Component, Input, Output, NgModule } from '@angular/core';
import * as i1$1 from '@angular/forms';
import { Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { TargetS3PProtocolConfiguration, SerialSettings } from '@iotize/tap/service/impl/target';
import { deepEqual } from '@iotize/common/utility';
import { BehaviorSubject, Subject } from 'rxjs';
import * as i1 from '@iotize/ionic';
import { LibCommonModule } from '@iotize/ionic';
import * as i3 from '@ionic/angular';
import * as i4 from '@angular/common';
import { CommonModule } from '@angular/common';

const SERIAL_SETTINGS_FIELDS = [
    'baudRate',
    'dataBits',
    'bitParity',
    'stopBits',
    'hardwareFlowControl',
    'handshakeDelimiter',
    'timeout',
];
const MODBUS_SETTINGS_FIELDS = [...SERIAL_SETTINGS_FIELDS, 'offsetFirstRegister', 'slave'];
const TAPNPASS_SETTINGS_FIELDS = ['physicalPort'];
const ALL_SETTINGS_FIELDS = [
    ...SERIAL_SETTINGS_FIELDS,
    ...MODBUS_SETTINGS_FIELDS,
];
class ProtocolConfigurationError extends Error {
    constructor(msg, cause) {
        super(msg);
        this.cause = cause;
        this.code = 'ProtocolConfigurationError';
    }
    static tapResponseError(err, msg) {
        const fullMsg = `${msg} - ${err.message}`;
        return new ProtocolConfigurationError(fullMsg, err);
    }
}

const TAG = 'SerialSettings';
class ProtocolConfigurationService {
    constructor(tapService) {
        this.tapService = tapService;
        this._s3pProtocolConfiguration = {
            mode: TargetS3PProtocolConfiguration.Mode.INDEXED,
            delay: 1,
        };
        this._defaultSettings = {
            serial: {
                physicalPort: SerialSettings.PhysicalPort.AUTO,
                stopBits: SerialSettings.StopBits.ONE,
                bitParity: SerialSettings.BitParity.NONE,
                dataBits: SerialSettings.DataBits._8,
                hardwareFlowControl: SerialSettings.HardwareFlowControl.NONE,
                handshakeDelimiter: SerialSettings.HandshakeDelimiter.NONE,
                timeout: 50,
                baudRate: 187500,
            },
            modbus: {
                offsetFirstRegister: false,
                slave: 0,
            },
        };
        this.pendingSettings$ = new BehaviorSubject(this._defaultSettings); // displayed settings
        this.loading = new BehaviorSubject(false);
        this.errors = new Subject();
        this._tapSettings = undefined;
    }
    set pendingSettings(settings) {
        this.pendingSettings$.next(settings);
    }
    get pendingSettings() {
        return this.pendingSettings$.value;
    }
    get tap() {
        return this.tapService.tap;
    }
    async refresh() {
        this.loading.next(true);
        try {
            const tapSettings = (await this.tap.service.target.getSerialModbusConfiguration()).body();
            this._tapSettings = tapSettings;
            this.pendingSettings$.next(tapSettings);
            // debug(TAG, 'Refreshed settings: ', this.pendingSettings);
            this.loading.next(false);
        }
        catch (err) {
            const error = ProtocolConfigurationError.tapResponseError(err, 'Failed reading serial settings from Tap');
            this.loading.next(false);
            this.onError(error);
            throw error;
        }
    }
    async applyChanges(temporary = true, reconnectTarget = true) {
        this.loading.next(true);
        try {
            await this.setSerialModbusConfiguration(temporary);
            if (reconnectTarget) {
                await this.reconnectTarget();
            }
            this._tapSettings = {
                ...this.pendingSettings,
            };
            this.loading.next(false);
        }
        catch (err) {
            this.loading.next(false);
            this.onError(err);
            throw err;
        }
    }
    discardChanges() {
        const prevSettings = this._tapSettings
            ? this._tapSettings
            : this._defaultSettings;
        this.pendingSettings$.next(prevSettings);
    }
    hasChanges() {
        if (!this._tapSettings) {
            return true;
        }
        return !deepEqual(this.pendingSettings, this._tapSettings);
    }
    async setSerialModbusConfiguration(temporary = true) {
        try {
            if (temporary) {
                (await this.tap.service.target.setSerialModbusConfiguration(this.pendingSettings)).successful();
            }
            else {
                (await this.tap.service.target.putSerialModbusConfiguration(this.pendingSettings)).successful();
            }
        }
        catch (err) {
            throw ProtocolConfigurationError.tapResponseError(err, 'Failed writing serial settings to Tap');
        }
    }
    async reconnectTarget() {
        await this.tap.service.target.disconnect();
        await this.tap.service.target.connect();
    }
    onError(error) {
        this.errors.next(error);
    }
}
/** @nocollapse */ /** @nocollapse */ ProtocolConfigurationService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.0", ngImport: i0, type: ProtocolConfigurationService, deps: [{ token: i1.CurrentDeviceService }], target: i0.ɵɵFactoryTarget.Injectable });
/** @nocollapse */ /** @nocollapse */ ProtocolConfigurationService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.0", ngImport: i0, type: ProtocolConfigurationService, providedIn: 'root' });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.0", ngImport: i0, type: ProtocolConfigurationService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root',
                }]
        }], ctorParameters: function () { return [{ type: i1.CurrentDeviceService }]; } });

class TapProtocolConfigurationFormComponent {
    constructor(formBuilder, protocolConfigurationService) {
        this.protocolConfigurationService = protocolConfigurationService;
        this.customBaudRate = false;
        this.baudRates = [
            300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 187500, 230400,
            460800, 921600,
        ];
        this.fields = ALL_SETTINGS_FIELDS;
        this.valueChanges = new EventEmitter();
        // TODO add validators
        const formConfig = {
            baudRate: [187500, [Validators.required, Validators.min(0)]],
            bitParity: [''],
            dataBits: [''],
            hardwareFlowControl: [''],
            handshakeDelimiter: [SerialSettings.HandshakeDelimiter.NONE],
            physicalPort: [''],
            stopBits: [''],
            offsetFirstRegister: [''],
            // identification: [''],
            // ledStatus: [''],
            slave: [''],
            timeout: [''],
        };
        this.form = formBuilder.group(formConfig);
    }
    set values(v) {
        if (v) {
            this.updateFormValue(v);
        }
    }
    hasField(field) {
        return this.fields.indexOf(field) >= 0;
    }
    get SerialSettings() {
        return SerialSettings;
    }
    updateFormValue(settings) {
        const newValues = {
            ...settings.modbus,
            ...settings.serial,
        };
        for (const key in newValues) {
            const field = this.form.get(key);
            if (field) {
                field.setValue(newValues[key], {
                    emitEvent: false,
                });
            }
        }
    }
    ngOnInit() {
        // debug(TAG, 'ngOnInit');
        const settings = this.protocolConfigurationService.pendingSettings;
        this.updateFormValue(settings);
        this.form.valueChanges.subscribe((newValue) => {
            // debug(TAG, 'Protocol configuration changed:', newValue);
            const netProtocolConfig = {
                modbus: {
                    offsetFirstRegister: newValue.offsetFirstRegister,
                    slave: newValue.slave,
                },
                serial: {
                    baudRate: newValue.baudRate,
                    bitParity: newValue.bitParity,
                    dataBits: newValue.dataBits,
                    handshakeDelimiter: newValue.handshakeDelimiter,
                    hardwareFlowControl: newValue.hardwareFlowControl,
                    physicalPort: newValue.physicalPort,
                    stopBits: newValue.stopBits,
                    timeout: newValue.timeout,
                },
            };
            this.valueChanges.emit(netProtocolConfig);
            this.protocolConfigurationService.pendingSettings = netProtocolConfig;
        });
        this.protocolConfigurationService.pendingSettings$.subscribe((newSettings) => {
            // debug(TAG, 'Refreshing form value', newSettings);
            if (this.baudRates.indexOf(newSettings.serial.baudRate) === -1) {
                this.customBaudRate = true;
            }
            this.updateFormValue(newSettings);
        });
    }
}
/** @nocollapse */ /** @nocollapse */ TapProtocolConfigurationFormComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.0", ngImport: i0, type: TapProtocolConfigurationFormComponent, deps: [{ token: i1$1.FormBuilder }, { token: ProtocolConfigurationService }], target: i0.ɵɵFactoryTarget.Component });
/** @nocollapse */ /** @nocollapse */ TapProtocolConfigurationFormComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.0", type: TapProtocolConfigurationFormComponent, selector: "tap-protocol-configuration-form", inputs: { customBaudRate: "customBaudRate", baudRates: "baudRates", fields: "fields", values: "values" }, outputs: { valueChanges: "valueChanges" }, ngImport: i0, template: "<form [formGroup]=\"form\">\n  <ion-item *ngIf=\"hasField('baudRate')\">\n    <ion-label> Baud rate </ion-label>\n    <!-- <ion-button fill=\"clear\" slot=\"end\" (click)=\"customBaudRate = !customBaudRate\">\n                    <ion-icon name=\"swap\"></ion-icon>\n                </ion-button> -->\n    <ion-input\n      slot=\"end\"\n      *ngIf=\"customBaudRate\"\n      type=\"number\"\n      [formControlName]=\"'baudRate'\"\n    ></ion-input>\n    <ion-select\n      slot=\"end\"\n      *ngIf=\"!customBaudRate\"\n      [formControlName]=\"'baudRate'\"\n    >\n      <ion-select-option *ngFor=\"let baud of baudRates\" [value]=\"baud\">\n        {{ baud }}\n        bauds\n      </ion-select-option>\n    </ion-select>\n  </ion-item>\n  <ion-item *ngIf=\"hasField('dataBits')\">\n    <ion-label>Data bits</ion-label>\n    <ion-select [formControlName]=\"'dataBits'\">\n      <ion-select-option\n        *ngFor=\"let option of SerialSettings.DataBits | enum\"\n        [value]=\"option.key\"\n      >\n        {{ option.value | trim: '_' }}\n      </ion-select-option>\n    </ion-select>\n  </ion-item>\n  <ion-item *ngIf=\"hasField('stopBits')\">\n    <ion-label>Stop bit</ion-label>\n    <ion-select [formControlName]=\"'stopBits'\">\n      <ion-select-option\n        *ngFor=\"let option of SerialSettings.StopBits | enum\"\n        [value]=\"option.key\"\n        >{{ option.value }}\n      </ion-select-option>\n    </ion-select>\n  </ion-item>\n  <ion-item *ngIf=\"hasField('bitParity')\">\n    <ion-label>Parity</ion-label>\n    <ion-select [formControlName]=\"'bitParity'\">\n      <ion-select-option\n        *ngFor=\"let option of SerialSettings.BitParity | enum\"\n        [value]=\"option.key\"\n      >\n        {{ option.value }}\n      </ion-select-option>\n    </ion-select>\n  </ion-item>\n\n  <ion-item *ngIf=\"hasField('hardwareFlowControl')\">\n    <ion-label>Hardware flow control</ion-label>\n    <ion-select [formControlName]=\"'hardwareFlowControl'\">\n      <ion-select-option\n        *ngFor=\"let option of SerialSettings.HardwareFlowControl | enum\"\n        [value]=\"option.key\"\n      >\n        {{ option.value }}\n      </ion-select-option>\n    </ion-select>\n  </ion-item>\n  <!-- \n    <ion-item *ngIf=\"hasField('handshakeDelimiter')\">\n        <ion-label>Handshake delimiter</ion-label>\n        <ion-select [formControlName]=\"'handshakeDelimiter'\">\n            <ion-select-option *ngFor=\"let option of SerialSettings.HandshakeDelimiter | enum\" [value]=\"option.key\">\n                {{option.value}}</ion-select-option>\n        </ion-select>\n    </ion-item> -->\n\n  <!-- TAPNPASS -->\n  <ion-item *ngIf=\"hasField('slave')\">\n    <ion-label>Slave number</ion-label>\n    <ion-input slot=\"end\" type=\"number\" [formControlName]=\"'slave'\"></ion-input>\n  </ion-item>\n\n  <ion-item *ngIf=\"hasField('physicalPort')\">\n    <ion-label>Physical port</ion-label>\n    <ion-select [formControlName]=\"'physicalPort'\">\n      <ion-select-option\n        *ngFor=\"let option of SerialSettings.PhysicalPort | enum\"\n        [value]=\"option.key\"\n      >\n        {{ option.value }}</ion-select-option\n      >\n    </ion-select>\n  </ion-item>\n\n  <ion-item *ngIf=\"hasField('timeout')\">\n    <ion-label>Timeout</ion-label>\n    <ion-input\n      slot=\"end\"\n      type=\"number\"\n      [formControlName]=\"'timeout'\"\n    ></ion-input>\n  </ion-item>\n\n  <ion-item *ngIf=\"hasField('offsetFirstRegister')\">\n    <ion-label>Offset first register</ion-label>\n    <ion-select [formControlName]=\"'offsetFirstRegister'\">\n      <ion-select-option [value]=\"false\">No</ion-select-option>\n      <ion-select-option [value]=\"true\">Yes</ion-select-option>\n    </ion-select>\n  </ion-item>\n</form>\n", styles: ["ion-input{text-align:right}\n"], components: [{ type: i3.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { type: i3.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { type: i3.IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "size", "spellcheck", "step", "type", "value"] }, { type: i3.IonSelect, selector: "ion-select", inputs: ["cancelText", "compareWith", "disabled", "interface", "interfaceOptions", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "value"] }, { type: i3.IonSelectOption, selector: "ion-select-option", inputs: ["disabled", "value"] }], directives: [{ type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NumericValueAccessor, selector: "ion-input[type=number]" }, { type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { type: i3.SelectValueAccessor, selector: "ion-range, ion-select, ion-radio-group, ion-segment, ion-datetime" }, { type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], pipes: { "enum": i1.EnumPipe, "trim": i1.TrimPipe } });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.0", ngImport: i0, type: TapProtocolConfigurationFormComponent, decorators: [{
            type: Component,
            args: [{ selector: 'tap-protocol-configuration-form', template: "<form [formGroup]=\"form\">\n  <ion-item *ngIf=\"hasField('baudRate')\">\n    <ion-label> Baud rate </ion-label>\n    <!-- <ion-button fill=\"clear\" slot=\"end\" (click)=\"customBaudRate = !customBaudRate\">\n                    <ion-icon name=\"swap\"></ion-icon>\n                </ion-button> -->\n    <ion-input\n      slot=\"end\"\n      *ngIf=\"customBaudRate\"\n      type=\"number\"\n      [formControlName]=\"'baudRate'\"\n    ></ion-input>\n    <ion-select\n      slot=\"end\"\n      *ngIf=\"!customBaudRate\"\n      [formControlName]=\"'baudRate'\"\n    >\n      <ion-select-option *ngFor=\"let baud of baudRates\" [value]=\"baud\">\n        {{ baud }}\n        bauds\n      </ion-select-option>\n    </ion-select>\n  </ion-item>\n  <ion-item *ngIf=\"hasField('dataBits')\">\n    <ion-label>Data bits</ion-label>\n    <ion-select [formControlName]=\"'dataBits'\">\n      <ion-select-option\n        *ngFor=\"let option of SerialSettings.DataBits | enum\"\n        [value]=\"option.key\"\n      >\n        {{ option.value | trim: '_' }}\n      </ion-select-option>\n    </ion-select>\n  </ion-item>\n  <ion-item *ngIf=\"hasField('stopBits')\">\n    <ion-label>Stop bit</ion-label>\n    <ion-select [formControlName]=\"'stopBits'\">\n      <ion-select-option\n        *ngFor=\"let option of SerialSettings.StopBits | enum\"\n        [value]=\"option.key\"\n        >{{ option.value }}\n      </ion-select-option>\n    </ion-select>\n  </ion-item>\n  <ion-item *ngIf=\"hasField('bitParity')\">\n    <ion-label>Parity</ion-label>\n    <ion-select [formControlName]=\"'bitParity'\">\n      <ion-select-option\n        *ngFor=\"let option of SerialSettings.BitParity | enum\"\n        [value]=\"option.key\"\n      >\n        {{ option.value }}\n      </ion-select-option>\n    </ion-select>\n  </ion-item>\n\n  <ion-item *ngIf=\"hasField('hardwareFlowControl')\">\n    <ion-label>Hardware flow control</ion-label>\n    <ion-select [formControlName]=\"'hardwareFlowControl'\">\n      <ion-select-option\n        *ngFor=\"let option of SerialSettings.HardwareFlowControl | enum\"\n        [value]=\"option.key\"\n      >\n        {{ option.value }}\n      </ion-select-option>\n    </ion-select>\n  </ion-item>\n  <!-- \n    <ion-item *ngIf=\"hasField('handshakeDelimiter')\">\n        <ion-label>Handshake delimiter</ion-label>\n        <ion-select [formControlName]=\"'handshakeDelimiter'\">\n            <ion-select-option *ngFor=\"let option of SerialSettings.HandshakeDelimiter | enum\" [value]=\"option.key\">\n                {{option.value}}</ion-select-option>\n        </ion-select>\n    </ion-item> -->\n\n  <!-- TAPNPASS -->\n  <ion-item *ngIf=\"hasField('slave')\">\n    <ion-label>Slave number</ion-label>\n    <ion-input slot=\"end\" type=\"number\" [formControlName]=\"'slave'\"></ion-input>\n  </ion-item>\n\n  <ion-item *ngIf=\"hasField('physicalPort')\">\n    <ion-label>Physical port</ion-label>\n    <ion-select [formControlName]=\"'physicalPort'\">\n      <ion-select-option\n        *ngFor=\"let option of SerialSettings.PhysicalPort | enum\"\n        [value]=\"option.key\"\n      >\n        {{ option.value }}</ion-select-option\n      >\n    </ion-select>\n  </ion-item>\n\n  <ion-item *ngIf=\"hasField('timeout')\">\n    <ion-label>Timeout</ion-label>\n    <ion-input\n      slot=\"end\"\n      type=\"number\"\n      [formControlName]=\"'timeout'\"\n    ></ion-input>\n  </ion-item>\n\n  <ion-item *ngIf=\"hasField('offsetFirstRegister')\">\n    <ion-label>Offset first register</ion-label>\n    <ion-select [formControlName]=\"'offsetFirstRegister'\">\n      <ion-select-option [value]=\"false\">No</ion-select-option>\n      <ion-select-option [value]=\"true\">Yes</ion-select-option>\n    </ion-select>\n  </ion-item>\n</form>\n", styles: ["ion-input{text-align:right}\n"] }]
        }], ctorParameters: function () { return [{ type: i1$1.FormBuilder }, { type: ProtocolConfigurationService }]; }, propDecorators: { customBaudRate: [{
                type: Input
            }], baudRates: [{
                type: Input
            }], fields: [{
                type: Input
            }], values: [{
                type: Input
            }], valueChanges: [{
                type: Output
            }] } });

class TapProtocolConfigurationModule {
}
/** @nocollapse */ /** @nocollapse */ TapProtocolConfigurationModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.0", ngImport: i0, type: TapProtocolConfigurationModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
/** @nocollapse */ /** @nocollapse */ TapProtocolConfigurationModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.3.0", ngImport: i0, type: TapProtocolConfigurationModule, declarations: [TapProtocolConfigurationFormComponent], imports: [CommonModule, LibCommonModule, FormsModule, ReactiveFormsModule], exports: [TapProtocolConfigurationFormComponent] });
/** @nocollapse */ /** @nocollapse */ TapProtocolConfigurationModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.3.0", ngImport: i0, type: TapProtocolConfigurationModule, providers: [ProtocolConfigurationService], imports: [[CommonModule, LibCommonModule, FormsModule, ReactiveFormsModule]] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.0", ngImport: i0, type: TapProtocolConfigurationModule, decorators: [{
            type: NgModule,
            args: [{
                    declarations: [TapProtocolConfigurationFormComponent],
                    exports: [TapProtocolConfigurationFormComponent],
                    imports: [CommonModule, LibCommonModule, FormsModule, ReactiveFormsModule],
                    providers: [ProtocolConfigurationService],
                }]
        }] });

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

export { ALL_SETTINGS_FIELDS, MODBUS_SETTINGS_FIELDS, ProtocolConfigurationError, ProtocolConfigurationService, SERIAL_SETTINGS_FIELDS, TAPNPASS_SETTINGS_FIELDS, TapProtocolConfigurationFormComponent, TapProtocolConfigurationModule };
//# sourceMappingURL=iotize-ionic-target-common.mjs.map
