import rxjs from '@iotize/common/rxjs';
import deviceClient from '@iotize/device-client.js';
import api from '@iotize/device-client.js/protocol/api';
import impl from '@iotize/device-client.js/client/impl';
import rxjs$1 from 'rxjs';
import operators from 'rxjs/operators';

var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};

function commonjsRequire () {
	throw new Error('Dynamic requires are not currently supported by rollup-plugin-commonjs');
}

function unwrapExports (x) {
	return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}

function createCommonjsModule(fn, module) {
	return module = { exports: {} }, fn(module, module.exports), module.exports;
}

function getCjsExportFromNamespace (n) {
	return n && n['default'] || n;
}

var firmwareUpdate = createCommonjsModule(function (module, exports) {
"use strict";
var __awaiter = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });






class TapNLinkUpdater {
    constructor(tap, options = TapNLinkUpdater.DEFAULT_OPTIONS) {
        this.tap = tap;
        this.options = options;
    }
    // public get events(): Observable<TapNLinkUpdater.Progress> {
    //     if (!this._observable) {
    //         this._observable = new Subject();
    //     }
    //     return this._observable;
    // }
    start(firmwareUpdateData) {
        if (this._observable) {
            // Already running
            return this._observable;
        }
        this.data = firmwareUpdateData;
        // let packetBuilder = new SinglePacketSplitter(
        //     this.options.maxSinglePacketSize
        // );
        // let packets = packetBuilder.chunk(firmwareUpdateData);
        let expectedCrc = 0;
        try {
            expectedCrc = impl.CRC.fromBytes(firmwareUpdateData); // TODO inject crc compute
        }
        catch (err) {
            return rxjs$1.throwError(err);
        }
        this._observable = rxjs$1.concat(rxjs$1.Observable.create((observer) => __awaiter(this, void 0, void 0, function* () {
            try {
                observer.next({
                    step: 'load'
                });
                if (!this.tap.getEncryptionOptions().encryption) {
                    yield this.tap.encryption(true, true, true);
                }
                observer.complete();
            }
            catch (err) {
                observer.error(err);
            }
        })), this.tap.singlePacket.loadInStore(firmwareUpdateData).run().pipe(operators.map((progress, index) => {
            return {
                step: 'load',
                payload: progress
            };
        })), rxjs$1.Observable.create((observer) => __awaiter(this, void 0, void 0, function* () {
            try {
                observer.next({
                    step: 'apply'
                });
                // let expectedCrc = CRC.fromBytes(this.data!); // TODO inject crc compute
                yield this.tap.singlePacket.executeFromStore(expectedCrc);
                observer.next({
                    step: 'finish'
                });
                observer.complete();
            }
            catch (err) {
                if (err.code === api.ComProtocol.ErrorCode.TimeoutError) {
                    observer.next({
                        step: 'finish'
                    });
                    observer.complete();
                }
                else {
                    observer.error(err);
                }
            }
        })), this.options.reconnectAfterUpdate ? this.waitingForReconnection(this.tap) : rxjs$1.empty());
        return this._observable;
    }
    isFirmwareUpdateAvailable() {
        return __awaiter(this, void 0, void 0, function* () {
            let info = (yield this.tap.service.singlePacket.getInfo()).body();
            return info.state == deviceClient.SinglePacketStoreInfo.State.EMPTY;
        });
    }
    waitingForReconnection(tap) {
        let retryCount = 5;
        return rxjs.retryWithDelay(rxjs.callToObservable(() => tap.connect()), {
            delay: 5000,
            retryCount: retryCount
        })
            .pipe(operators.map((v, index) => {
            return {
                step: 'restart'
            };
        }));
    }
}
exports.TapNLinkUpdater = TapNLinkUpdater;
(function (TapNLinkUpdater) {
    TapNLinkUpdater.DEFAULT_OPTIONS = {
        // maxSinglePacketDataPartSize: 192,
        reconnectAfterUpdate: true
    };
})(TapNLinkUpdater = exports.TapNLinkUpdater || (exports.TapNLinkUpdater = {}));

});

var firmwareUpdate$1 = unwrapExports(firmwareUpdate);
var firmwareUpdate_1 = firmwareUpdate.TapNLinkUpdater;

var public_api = createCommonjsModule(function (module, exports) {
"use strict";
function __export(m) {
    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
Object.defineProperty(exports, "__esModule", { value: true });
__export(firmwareUpdate);

});

var public_api$1 = unwrapExports(public_api);

var iotizeDeviceClient_jsFirmwareUpdate = createCommonjsModule(function (module, exports) {
"use strict";
/**
 * Generated bundle index. Do not edit.
 */
function __export(m) {
    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
Object.defineProperty(exports, "__esModule", { value: true });
__export(public_api);

});

var iotizeDeviceClient_jsFirmwareUpdate$1 = unwrapExports(iotizeDeviceClient_jsFirmwareUpdate);

export default iotizeDeviceClient_jsFirmwareUpdate$1;
//# sourceMappingURL=iotize-device-client.js-firmware-update.js.map
