import { concat, defer, from, Observable, of, throwError } from "rxjs";
import { catchError, concatMap } from "rxjs/operators";
import { DisconnectedDevice } from "@ledgerhq/errors";
import { withDevice } from "./deviceAccess";
import editDeviceName from "./editDeviceName";
import getAppAndVersion from "./getAppAndVersion";
import { isDashboardName } from "./isDashboardName";
import quitApp from "./quitApp";
export default function renameDevice({ deviceId, request }) {
    const { name } = request;
    return 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 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
             */
            defer(() => from(getAppAndVersion(transport))).pipe(
            /**
             * we get the appAndVersion
             */
            concatMap(appAndVersion => {
                if (isDashboardName(appAndVersion.name)) {
                    /**
                     * If we are on the dashboard, we can rename the device
                     */
                    return concat(of({ type: "permission-requested" }), from(editDeviceName(transport, name)).pipe(concatMap(() => 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 concat(of({ type: "quit-app" }), from(quitApp(transport)).pipe(concatMap(() => of({ type: "disconnected", expected: true }))));
            }));
            const sub = innerSub
                .pipe(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 DisconnectedDevice) {
                    return innerSub;
                }
                return throwError(() => error);
            }))
                .subscribe(o);
            return () => {
                /**
                 * When the observable is unsubscribed, we unsubscribe the innerSub
                 */
                sub.unsubscribe();
            };
        });
    }).pipe(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 DisconnectedDevice) {
            return of({
                type: "disconnected",
                expected: true,
            });
        }
        return throwError(() => error);
    }));
}
//# sourceMappingURL=renameDevice.js.map