import { AppNotFound, backupAppStorage, getAppStorageInfo, } from "@ledgerhq/device-core";
import { Observable, catchError, from, of, switchMap } from "rxjs";
import { BackupAppDataError, BackupAppDataEventType } from "./types";
/**
 * Backs up the application data for a specific app on a Ledger device.
 * @param transport - The transport object used to communicate with the Ledger device.
 * @param appName - The name of the application to backup.
 * @returns An observable that emits BackupAppDataEvent according to the backup process.
 * @throws {BackupAppDataError}
 */
export function backupAppData(transport, appName) {
    const obs = new Observable(subscriber => {
        const sub = from(getAppStorageInfo(transport, appName))
            .pipe(switchMap(async (appDataInfo) => {
            subscriber.next({ type: BackupAppDataEventType.AppDataInfoFetched, data: appDataInfo });
            const dataSize = appDataInfo.size;
            // Check if there is any data to backup
            if (dataSize === 0) {
                subscriber.next({ type: BackupAppDataEventType.NoAppDataToBackup });
                subscriber.complete();
                return;
            }
            // Backup app data by chunks
            let appData = Buffer.from([]);
            let offset = 0;
            while (offset < dataSize) {
                const chunk = await backupAppStorage(transport);
                // Make sure that the process advances
                if (chunk.length === 0) {
                    subscriber.error(new BackupAppDataError("Chunk data is empty"));
                    return;
                }
                appData = Buffer.concat([appData, chunk]);
                offset += chunk.length;
                subscriber.next({
                    type: BackupAppDataEventType.Progress,
                    data: Number((offset / dataSize).toFixed(2)),
                });
            }
            // Check data size
            if (appData.length !== dataSize) {
                subscriber.error(new BackupAppDataError("App data size mismatch"));
                return;
            }
            subscriber.next({
                type: BackupAppDataEventType.AppDataBackedUp,
                data: appData.toString("base64"),
            });
            subscriber.complete();
        }), catchError(e => {
            if (e instanceof AppNotFound) {
                subscriber.next({ type: BackupAppDataEventType.NoAppDataToBackup });
                subscriber.complete();
                return of(null);
            }
            throw e;
        }))
            .subscribe();
        return () => {
            sub.unsubscribe();
        };
    });
    return obs;
}
//# sourceMappingURL=backupAppData.js.map