"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const logs_1 = require("@ledgerhq/logs");
const rxjs_1 = require("rxjs");
const operators_1 = require("rxjs/operators");
const errors_1 = require("@ledgerhq/errors");
const deviceAccess_1 = require("./deviceAccess");
const getDeviceInfo_1 = __importDefault(require("./getDeviceInfo"));
const flash_1 = __importDefault(require("./flash"));
const installFinalFirmware_1 = __importDefault(require("./installFinalFirmware"));
const hasFinalFirmware_1 = require("./hasFinalFirmware");
const wait2s = (0, rxjs_1.of)({
    type: "wait",
}).pipe((0, operators_1.delay)(2000));
const main = (deviceId, { final, shouldFlashMCU }) => {
    (0, logs_1.log)("hw", "firmwareUpdate-main started");
    const withFinal = (0, hasFinalFirmware_1.hasFinalFirmware)(final);
    const withDeviceInfo = (0, deviceAccess_1.withDevicePolling)(deviceId)(transport => (0, rxjs_1.from)((0, getDeviceInfo_1.default)(transport)), () => true);
    const withDeviceInstall = install => (0, deviceAccess_1.withDevicePolling)(deviceId)(install, e => e instanceof errors_1.CantOpenDevice);
    const waitForBootloader = withDeviceInfo.pipe((0, operators_1.concatMap)(deviceInfo => (deviceInfo.isBootloader ? rxjs_1.EMPTY : (0, rxjs_1.concat)(wait2s, waitForBootloader))));
    const potentialAutoFlash = withDeviceInfo.pipe((0, operators_1.concatMap)(deviceInfo => deviceInfo.isOSU
        ? rxjs_1.EMPTY
        : (0, deviceAccess_1.withDevice)(deviceId)(transport => new rxjs_1.Observable(o => {
            const timeout = setTimeout(() => {
                (0, logs_1.log)("firmware", "potentialAutoFlash timeout");
                o.complete();
            }, 20000);
            const disconnect = () => {
                (0, logs_1.log)("firmware", "potentialAutoFlash disconnect");
                o.complete();
            };
            transport.on("disconnect", disconnect);
            return () => {
                clearTimeout(timeout);
                transport.off("disconnect", disconnect);
            };
        }))));
    const bootloaderLoop = withDeviceInfo.pipe((0, operators_1.concatMap)(deviceInfo => deviceInfo.isBootloader
        ? (0, rxjs_1.concat)(withDeviceInstall((0, flash_1.default)(final)), wait2s, bootloaderLoop)
        : rxjs_1.EMPTY));
    const finalStep = !withFinal
        ? rxjs_1.EMPTY
        : withDeviceInfo.pipe((0, operators_1.concatMap)(deviceInfo => !deviceInfo.isOSU
            ? (0, rxjs_1.throwError)(() => new errors_1.DeviceInOSUExpected())
            : withDeviceInstall(installFinalFirmware_1.default)));
    const all = shouldFlashMCU
        ? (0, rxjs_1.concat)(waitForBootloader, bootloaderLoop, finalStep)
        : (0, rxjs_1.concat)(potentialAutoFlash, finalStep);
    return all.pipe((0, operators_1.scan)((acc, e) => {
        if (e.type === "install") {
            return {
                installing: e.step,
                progress: 0,
            };
        }
        if (e.type === "bulk-progress") {
            return { ...acc, progress: e.progress };
        }
        return acc;
    }, {
        progress: 0,
        installing: null,
    }), (0, operators_1.distinctUntilChanged)(), (0, operators_1.throttleTime)(100));
};
exports.default = main;
//# sourceMappingURL=firmwareUpdate-main.js.map