import { from, Observable } from "rxjs";
import { mergeMap, retryWhen } from "rxjs/operators";
import { LockedDeviceError } from "@ledgerhq/errors";
import getDeviceInfo from "./getDeviceInfo";
import { retryWhileErrors, withDevice } from "./deviceAccess";
import genuineCheck from "./genuineCheck";
/**
 * Get a genuine check for a device only from its id
 * @param deviceId A device id, or an empty string if device is usb plugged
 * @param lockedDeviceTimeoutMs Time of no response from device after which the device is considered locked, in ms. Default 1000ms.
 * @returns An Observable pushing objects containing:
 * - socketEvent: a SocketEvent giving the current status of the genuine check,
 *     null if the genuine check process did not reach any state yet
 * - lockedDevice: a boolean set to true if the device is currently locked, false otherwise
 */
export const getGenuineCheckFromDeviceId = ({ deviceId, deviceName, lockedDeviceTimeoutMs = 1000, }) => {
    return new Observable(subscriber => {
        // In order to know if a device is locked or not.
        // As we're not timing out inside the genuineCheckObservable flow (with rxjs timeout for ex)
        // once the device is unlock, getDeviceInfo should return the device info and
        // the flow will continue. No need to handle a retry strategy
        const lockedDeviceTimeout = setTimeout(() => {
            subscriber.next({ socketEvent: null, lockedDevice: true });
        }, lockedDeviceTimeoutMs);
        // Returns a Subscription that can be unsubscribed/cleaned
        return (withDevice(deviceId, deviceName ? { matchDeviceByName: deviceName } : undefined)(t => from(getDeviceInfo(t)).pipe(mergeMap(deviceInfo => {
            clearTimeout(lockedDeviceTimeout);
            subscriber.next({ socketEvent: null, lockedDevice: false });
            return genuineCheck(t, deviceInfo);
        })))
            // Needs to retry with withDevice
            .pipe(retryWhen(retryWhileErrors((e) => {
            // Cancels the locked-device unresponsive/timeout strategy if received any response/error
            clearTimeout(lockedDeviceTimeout);
            if (e instanceof LockedDeviceError) {
                subscriber.next({ socketEvent: null, lockedDevice: true });
                return true;
            }
            return false;
        })))
            .subscribe({
            next: (socketEvent) => subscriber.next({ socketEvent, lockedDevice: false }),
            error: e => subscriber.error(e),
            complete: () => subscriber.complete(),
        }));
    });
};
//# sourceMappingURL=getGenuineCheckFromDeviceId.js.map