"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.backupAppData = void 0;
const device_core_1 = require("@ledgerhq/device-core");
const rxjs_1 = require("rxjs");
const types_1 = require("./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}
 */
function backupAppData(transport, appName) {
    const obs = new rxjs_1.Observable(subscriber => {
        const sub = (0, rxjs_1.from)((0, device_core_1.getAppStorageInfo)(transport, appName))
            .pipe((0, rxjs_1.switchMap)(async (appDataInfo) => {
            subscriber.next({ type: types_1.BackupAppDataEventType.AppDataInfoFetched, data: appDataInfo });
            const dataSize = appDataInfo.size;
            // Check if there is any data to backup
            if (dataSize === 0) {
                subscriber.next({ type: types_1.BackupAppDataEventType.NoAppDataToBackup });
                subscriber.complete();
                return;
            }
            // Backup app data by chunks
            let appData = Buffer.from([]);
            let offset = 0;
            while (offset < dataSize) {
                const chunk = await (0, device_core_1.backupAppStorage)(transport);
                // Make sure that the process advances
                if (chunk.length === 0) {
                    subscriber.error(new types_1.BackupAppDataError("Chunk data is empty"));
                    return;
                }
                appData = Buffer.concat([appData, chunk]);
                offset += chunk.length;
                subscriber.next({
                    type: types_1.BackupAppDataEventType.Progress,
                    data: Number((offset / dataSize).toFixed(2)),
                });
            }
            // Check data size
            if (appData.length !== dataSize) {
                subscriber.error(new types_1.BackupAppDataError("App data size mismatch"));
                return;
            }
            subscriber.next({
                type: types_1.BackupAppDataEventType.AppDataBackedUp,
                data: appData.toString("base64"),
            });
            subscriber.complete();
        }), (0, rxjs_1.catchError)(e => {
            if (e instanceof device_core_1.AppNotFound) {
                subscriber.next({ type: types_1.BackupAppDataEventType.NoAppDataToBackup });
                subscriber.complete();
                return (0, rxjs_1.of)(null);
            }
            throw e;
        }))
            .subscribe();
        return () => {
            sub.unsubscribe();
        };
    });
    return obs;
}
exports.backupAppData = backupAppData;
//# sourceMappingURL=backupAppData.js.map