import { Injectable, ɵɵdefineInjectable, ɵɵinject, EventEmitter, Component, Input, Output, NgModule } from '@angular/core';
import { Validators, FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { TargetS3PProtocolConfiguration, SerialSettings } from '@iotize/tap/service/impl/target';
import { __awaiter } from 'tslib';
import { deepEqual } from '@iotize/common/utility';
import { BehaviorSubject, Subject } from 'rxjs';
import { CurrentDeviceService, LibCommonModule } from '@iotize/ionic';
import { CommonModule } from '@angular/common';

/**
 * @fileoverview added by tsickle
 * Generated from: lib/definitions.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/** @type {?} */
const SERIAL_SETTINGS_FIELDS = [
    'baudRate',
    'dataBits',
    'bitParity',
    'stopBits',
    'hardwareFlowControl',
    'handshakeDelimiter',
    'timeout'
];
/** @type {?} */
const MODBUS_SETTINGS_FIELDS = [
    ...SERIAL_SETTINGS_FIELDS,
    'offsetFirstRegister',
    'slave'
];
/** @type {?} */
const TAPNPASS_SETTINGS_FIELDS = [
    'physicalPort'
];
/** @type {?} */
const ALL_SETTINGS_FIELDS = [
    ...SERIAL_SETTINGS_FIELDS,
    ...MODBUS_SETTINGS_FIELDS
];
class ProtocolConfigurationError extends Error {
    /**
     * @param {?} msg
     * @param {?=} cause
     */
    constructor(msg, cause) {
        super(msg);
        this.cause = cause;
        this.code = 'ProtocolConfigurationError';
    }
    /**
     * @param {?} err
     * @param {?} msg
     * @return {?}
     */
    static tapResponseError(err, msg) {
        /** @type {?} */
        const fullMsg = `${msg} - ${err.message}`;
        return new ProtocolConfigurationError(fullMsg, err);
    }
}
if (false) {
    /** @type {?} */
    ProtocolConfigurationError.prototype.code;
    /** @type {?} */
    ProtocolConfigurationError.prototype.cause;
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/protocol-configuration.service.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/** @type {?} */
const TAG = 'SerialSettings';
class ProtocolConfigurationService {
    /**
     * @param {?} tapService
     */
    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
        // displayed settings
        this.loading = new BehaviorSubject(false);
        // real settings
        this.errors = new Subject();
        this._tapSettings = undefined;
    }
    /**
     * @param {?} settings
     * @return {?}
     */
    set pendingSettings(settings) {
        this.pendingSettings$.next(settings);
    }
    /**
     * @return {?}
     */
    get pendingSettings() {
        return this.pendingSettings$.value;
    }
    /**
     * @return {?}
     */
    get tap() {
        return this.tapService.tap;
    }
    /**
     * @return {?}
     */
    refresh() {
        return __awaiter(this, void 0, void 0, function* () {
            this.loading.next(true);
            try {
                /** @type {?} */
                const tapSettings = (yield 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) {
                /** @type {?} */
                const error = ProtocolConfigurationError.tapResponseError(err, 'Failed reading serial settings from Tap');
                this.loading.next(false);
                this.onError(error);
                throw error;
            }
        });
    }
    /**
     * @param {?=} temporary
     * @param {?=} reconnectTarget
     * @return {?}
     */
    applyChanges(temporary = true, reconnectTarget = true) {
        return __awaiter(this, void 0, void 0, function* () {
            this.loading.next(true);
            try {
                yield this.setSerialModbusConfiguration(temporary);
                if (reconnectTarget) {
                    yield this.reconnectTarget();
                }
                this._tapSettings = Object.assign({}, this.pendingSettings);
                this.loading.next(false);
            }
            catch (error) {
                this.loading.next(false);
                this.onError(error);
                throw error;
            }
        });
    }
    /**
     * @return {?}
     */
    discardChanges() {
        /** @type {?} */
        const prevSettings = (this._tapSettings ? this._tapSettings : this._defaultSettings);
        this.pendingSettings$.next(prevSettings);
    }
    /**
     * @return {?}
     */
    hasChanges() {
        if (!this._tapSettings) {
            return true;
        }
        return !deepEqual(this.pendingSettings, this._tapSettings);
    }
    /**
     * @private
     * @param {?=} temporary
     * @return {?}
     */
    setSerialModbusConfiguration(temporary = true) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                if (temporary) {
                    (yield this.tap.service.target.setSerialModbusConfiguration(this.pendingSettings)).successful();
                }
                else {
                    (yield this.tap.service.target.putSerialModbusConfiguration(this.pendingSettings)).successful();
                }
            }
            catch (err) {
                throw ProtocolConfigurationError.tapResponseError(err, `Failed writing serial settings to Tap`);
            }
        });
    }
    /**
     * @return {?}
     */
    reconnectTarget() {
        return __awaiter(this, void 0, void 0, function* () {
            yield this.tap.service.target.disconnect();
            yield this.tap.service.target.connect();
        });
    }
    /**
     * @param {?} error
     * @return {?}
     */
    onError(error) {
        this.errors.next(error);
    }
}
ProtocolConfigurationService.decorators = [
    { type: Injectable, args: [{
                providedIn: 'root'
            },] }
];
/** @nocollapse */
ProtocolConfigurationService.ctorParameters = () => [
    { type: CurrentDeviceService }
];
/** @nocollapse */ ProtocolConfigurationService.ɵprov = ɵɵdefineInjectable({ factory: function ProtocolConfigurationService_Factory() { return new ProtocolConfigurationService(ɵɵinject(CurrentDeviceService)); }, token: ProtocolConfigurationService, providedIn: "root" });
if (false) {
    /**
     * @type {?}
     * @protected
     */
    ProtocolConfigurationService.prototype._s3pProtocolConfiguration;
    /**
     * @type {?}
     * @protected
     */
    ProtocolConfigurationService.prototype._defaultSettings;
    /** @type {?} */
    ProtocolConfigurationService.prototype.pendingSettings$;
    /** @type {?} */
    ProtocolConfigurationService.prototype.loading;
    /**
     * @type {?}
     * @private
     */
    ProtocolConfigurationService.prototype._tapSettings;
    /** @type {?} */
    ProtocolConfigurationService.prototype.errors;
    /** @type {?} */
    ProtocolConfigurationService.prototype.tapService;
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/tap-protocol-configuration-form/tap-protocol-configuration-form.component.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/** @type {?} */
const TAG$1 = 'TapProtocolConfiguration';
class TapProtocolConfigurationFormComponent {
    /**
     * @param {?} formBuilder
     * @param {?} protocolConfigurationService
     */
    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
        /** @type {?} */
        const formConfig = {
            baudRate: ['', [Validators.required]],
            bitParity: [''],
            dataBits: [''],
            hardwareFlowControl: [''],
            handshakeDelimiter: [
                SerialSettings.HandshakeDelimiter.NONE
            ],
            physicalPort: [''],
            stopBits: [''],
            offsetFirstRegister: [''],
            // identification: [''],
            // ledStatus: [''],
            slave: [''],
            timeout: [''],
        };
        this.form = formBuilder.group(formConfig);
    }
    /**
     * @param {?} v
     * @return {?}
     */
    set values(v) {
        if (v) {
            this.updateFormValue(v);
        }
    }
    /**
     * @param {?} field
     * @return {?}
     */
    hasField(field) {
        return this.fields.indexOf(field) >= 0;
    }
    /**
     * @return {?}
     */
    get SerialSettings() {
        return SerialSettings;
    }
    /**
     * @param {?} settings
     * @return {?}
     */
    updateFormValue(settings) {
        /** @type {?} */
        const newValues = Object.assign(Object.assign({}, settings.modbus), settings.serial);
        for (const key in newValues) {
            /** @type {?} */
            const field = this.form.get(key);
            if (field) {
                field.setValue(newValues[key], {
                    emitEvent: false
                });
            }
        }
    }
    /**
     * @return {?}
     */
    ngOnInit() {
        // debug(TAG, 'ngOnInit');
        /** @type {?} */
        const settings = this.protocolConfigurationService.pendingSettings;
        this.updateFormValue(settings);
        this.form.valueChanges
            .subscribe((/**
         * @param {?} newValue
         * @return {?}
         */
        (newValue) => {
            // debug(TAG, 'Protocol configuration changed:', newValue);
            /** @type {?} */
            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((/**
         * @param {?} newSettings
         * @return {?}
         */
        (newSettings) => {
            // debug(TAG, 'Refreshing form value', newSettings);
            if (this.baudRates.indexOf(newSettings.serial.baudRate) === -1) {
                this.customBaudRate = true;
            }
            this.form.setValue(newSettings, {
                emitEvent: false
            });
        }));
    }
}
TapProtocolConfigurationFormComponent.decorators = [
    { type: Component, args: [{
                selector: 'tap-protocol-configuration-form',
                template: "<form [formGroup]=\"form\">\r\n    <ion-item *ngIf=\"hasField('baudRate')\">\r\n        <ion-label>\r\n            Baud rate\r\n        </ion-label>\r\n        <!-- <ion-button fill=\"clear\" slot=\"end\" (click)=\"customBaudRate = !customBaudRate\">\r\n                    <ion-icon name=\"swap\"></ion-icon>\r\n                </ion-button> -->\r\n        <ion-input slot=\"end\" *ngIf=\"customBaudRate\" type=\"number\" [formControlName]=\"'baudRate'\"></ion-input>\r\n        <ion-select slot=\"end\" *ngIf=\"!customBaudRate\" [formControlName]=\"'baudRate'\">\r\n            <ion-select-option *ngFor=\"let baud of baudRates\" [value]=\"baud\">\r\n                {{baud}}\r\n                bauds\r\n            </ion-select-option>\r\n        </ion-select>\r\n    </ion-item>\r\n    <ion-item *ngIf=\"hasField('dataBits')\">\r\n        <ion-label>Data bits</ion-label>\r\n        <ion-select [formControlName]=\"'dataBits'\">\r\n            <ion-select-option *ngFor=\"let option of SerialSettings.DataBits | enum\" [value]=\"option.key\">\r\n                {{option.value | trim:'_'}}\r\n            </ion-select-option>\r\n        </ion-select>\r\n    </ion-item>\r\n    <ion-item *ngIf=\"hasField('stopBits')\">\r\n        <ion-label>Stop bit</ion-label>\r\n        <ion-select [formControlName]=\"'stopBits'\">\r\n            <ion-select-option *ngFor=\"let option of SerialSettings.StopBits | enum\" [value]=\"option.key\">{{option.value}}\r\n            </ion-select-option>\r\n        </ion-select>\r\n    </ion-item>\r\n    <ion-item *ngIf=\"hasField('bitParity')\">\r\n        <ion-label>Parity</ion-label>\r\n        <ion-select [formControlName]=\"'bitParity'\">\r\n            <ion-select-option *ngFor=\"let option of SerialSettings.BitParity | enum\" [value]=\"option.key\">\r\n                {{option.value}}\r\n            </ion-select-option>\r\n        </ion-select>\r\n    </ion-item>\r\n\r\n    <ion-item *ngIf=\"hasField('hardwareFlowControl')\">\r\n        <ion-label>Hardware flow control</ion-label>\r\n        <ion-select [formControlName]=\"'hardwareFlowControl'\">\r\n            <ion-select-option *ngFor=\"let option of SerialSettings.HardwareFlowControl | enum\" [value]=\"option.key\">\r\n                {{option.value}}\r\n            </ion-select-option>\r\n        </ion-select>\r\n    </ion-item>\r\n<!-- \r\n    <ion-item *ngIf=\"hasField('handshakeDelimiter')\">\r\n        <ion-label>Handshake delimiter</ion-label>\r\n        <ion-select [formControlName]=\"'handshakeDelimiter'\">\r\n            <ion-select-option *ngFor=\"let option of SerialSettings.HandshakeDelimiter | enum\" [value]=\"option.key\">\r\n                {{option.value}}</ion-select-option>\r\n        </ion-select>\r\n    </ion-item> -->\r\n\r\n    <!-- TAPNPASS -->\r\n    <ion-item *ngIf=\"hasField('slave')\">\r\n        <ion-label>Slave number</ion-label>\r\n        <ion-input slot=\"end\" type=\"number\" [formControlName]=\"'slave'\" ></ion-input>\r\n    </ion-item>\r\n\r\n    <ion-item *ngIf=\"hasField('physicalPort')\">\r\n        <ion-label>Physical port</ion-label>\r\n        <ion-select [formControlName]=\"'physicalPort'\">\r\n            <ion-select-option *ngFor=\"let option of SerialSettings.PhysicalPort | enum\" [value]=\"option.key\">\r\n                {{option.value}}</ion-select-option>\r\n        </ion-select>\r\n    </ion-item>\r\n\r\n    <ion-item *ngIf=\"hasField('timeout')\">\r\n        <ion-label>Timeout</ion-label>\r\n        <ion-input slot=\"end\" type=\"number\" [formControlName]=\"'timeout'\"></ion-input>\r\n    </ion-item>\r\n\r\n    <ion-item *ngIf=\"hasField('offsetFirstRegister')\">\r\n        <ion-label>Offset first register</ion-label>\r\n        <ion-select [formControlName]=\"'offsetFirstRegister'\">\r\n            <ion-select-option [value]=\"false\">No</ion-select-option>\r\n            <ion-select-option [value]=\"true\">Yes</ion-select-option>\r\n        </ion-select>\r\n    </ion-item>\r\n</form>\r\n",
                styles: ["ion-input{text-align:right}"]
            }] }
];
/** @nocollapse */
TapProtocolConfigurationFormComponent.ctorParameters = () => [
    { type: FormBuilder },
    { type: ProtocolConfigurationService }
];
TapProtocolConfigurationFormComponent.propDecorators = {
    customBaudRate: [{ type: Input }],
    baudRates: [{ type: Input }],
    fields: [{ type: Input }],
    values: [{ type: Input }],
    valueChanges: [{ type: Output }]
};
if (false) {
    /** @type {?} */
    TapProtocolConfigurationFormComponent.prototype.customBaudRate;
    /** @type {?} */
    TapProtocolConfigurationFormComponent.prototype.baudRates;
    /** @type {?} */
    TapProtocolConfigurationFormComponent.prototype.fields;
    /** @type {?} */
    TapProtocolConfigurationFormComponent.prototype.valueChanges;
    /** @type {?} */
    TapProtocolConfigurationFormComponent.prototype.form;
    /** @type {?} */
    TapProtocolConfigurationFormComponent.prototype.protocolConfigurationService;
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/tap-protocol-configuration.module.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
class TapProtocolConfigurationModule {
}
TapProtocolConfigurationModule.decorators = [
    { type: NgModule, args: [{
                declarations: [
                    TapProtocolConfigurationFormComponent
                ],
                exports: [
                    TapProtocolConfigurationFormComponent
                ],
                imports: [
                    CommonModule,
                    LibCommonModule,
                    FormsModule,
                    ReactiveFormsModule
                ],
                providers: [
                    ProtocolConfigurationService
                ]
            },] }
];

/**
 * @fileoverview added by tsickle
 * Generated from: public_api.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */

/**
 * @fileoverview added by tsickle
 * Generated from: iotize-ionic-target-common.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */

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