"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const rxjs_1 = require("rxjs");
const operators_1 = require("rxjs/operators");
const errors_1 = require("@ledgerhq/errors");
const deviceAccess_1 = require("./deviceAccess");
const editDeviceName_1 = __importDefault(require("./editDeviceName"));
const getAppAndVersion_1 = __importDefault(require("./getAppAndVersion"));
const isDashboardName_1 = require("./isDashboardName");
const quitApp_1 = __importDefault(require("./quitApp"));
function renameDevice({ deviceId, request }) {
    const { name } = request;
    return (0, deviceAccess_1.withDevice)(deviceId)(transport => {
        /**
         * We create a new observable that will be returned to the caller
         * that will be used to subscribe to the RenameDeviceEvent events
         */
        return new rxjs_1.Observable(o => {
            /**
             * Inner function that will be called recursively until the device is on the dashboard
             * and we can send the renameDevice command to the device
             */
            const innerSub = 
            /**
             * defer takes a factory function that returns an observable, thus
             * calling the function again will not use the same output as the previous call
             */
            (0, rxjs_1.defer)(() => (0, rxjs_1.from)((0, getAppAndVersion_1.default)(transport))).pipe(
            /**
             * we get the appAndVersion
             */
            (0, operators_1.concatMap)(appAndVersion => {
                if ((0, isDashboardName_1.isDashboardName)(appAndVersion.name)) {
                    /**
                     * If we are on the dashboard, we can rename the device
                     */
                    return (0, rxjs_1.concat)((0, rxjs_1.of)({ type: "permission-requested" }), (0, rxjs_1.from)((0, editDeviceName_1.default)(transport, name)).pipe((0, operators_1.concatMap)(() => (0, rxjs_1.of)({ type: "device-renamed", name }))));
                }
                /**
                 * If we are not on dashboard, we quit the app
                 * and send an exepected disconnected event while withDevice will retry to run the innerSub
                 */
                return (0, rxjs_1.concat)((0, rxjs_1.of)({ type: "quit-app" }), (0, rxjs_1.from)((0, quitApp_1.default)(transport)).pipe((0, operators_1.concatMap)(() => (0, rxjs_1.of)({ type: "disconnected", expected: true }))));
            }));
            const sub = innerSub
                .pipe((0, operators_1.catchError)((error) => {
                /**
                 * If the error is that the device is not on the dashboard, we retry the innerSub
                 */
                if (error.message === "not on dashboard" || error instanceof errors_1.DisconnectedDevice) {
                    return innerSub;
                }
                return (0, rxjs_1.throwError)(() => error);
            }))
                .subscribe(o);
            return () => {
                /**
                 * When the observable is unsubscribed, we unsubscribe the innerSub
                 */
                sub.unsubscribe();
            };
        });
    }).pipe((0, operators_1.catchError)((error) => {
        /**
         *
         * If the error is that the device is not on the dashboard or Disconnected, we return a waiting-device event
         * which is not used in the renameDevice reducer, just to trick the UI not to flicker.
         * We do have a global timeout so that we are not in a infinite loop
         *
         */
        if (error.message === "not on dashboard" || error instanceof errors_1.DisconnectedDevice) {
            return (0, rxjs_1.of)({
                type: "disconnected",
                expected: true,
            });
        }
        return (0, rxjs_1.throwError)(() => error);
    }));
}
exports.default = renameDevice;
//# sourceMappingURL=renameDevice.js.map