"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MobileAppFileCache = void 0;
const path_1 = require("path");
const stream_1 = require("stream");
const promises_1 = require("fs/promises");
const mablApi_1 = require("../mablApi");
const util_1 = require("../core/util");
const FileCache_1 = require("./FileCache");
const loggingProvider_1 = require("../providers/logging/loggingProvider");
const MOBILE_APP_FILE_CACHE_DIRECTORY = 'mobile-app-files';
const DEFAULT_MAX_MOBILE_APP_FILES = 10;
const DEFAULT_MAX_MOBILE_APP_FILE_AGE_MINUTES = 60 * 24;
const MOBILE_APP_FILE_IMMUTABLE_FIELDS = [
    'content_type',
    'crc32c_hex',
    'created_by_id',
    'created_time',
    'extension',
    'id',
    'name',
    'platform',
    'size',
    'version',
    'workspace_id',
];
const MOBILE_APP_FILE_IMMUTABLE_FIELD_SET = new Set(MOBILE_APP_FILE_IMMUTABLE_FIELDS);
class MobileAppFileCache extends FileCache_1.FileCache {
    constructor(options) {
        super({
            ...options,
            cacheName: MOBILE_APP_FILE_CACHE_DIRECTORY,
            maximumCachedFiles: options?.maximumCachedFiles ?? DEFAULT_MAX_MOBILE_APP_FILES,
            maximumCachedFileAgeMinutes: options?.maximumCachedFileAgeMinutes ??
                DEFAULT_MAX_MOBILE_APP_FILE_AGE_MINUTES,
        });
        this.mablApiClientPromise = options?.mablApiClient
            ? Promise.resolve(options.mablApiClient)
            : (0, util_1.getApiClient)();
    }
    async getMobileAppFileImmutableFields(id) {
        const getReader = async () => {
            const apiClient = await this.mablApiClientPromise;
            const mobileAppFile = this.retainImmutableFields(await apiClient.getMobileAppFile(id));
            return stream_1.Readable.from(Buffer.from(JSON.stringify(mobileAppFile, undefined, 0), 'utf-8'));
        };
        const path = await this.getOrCreateFile((0, path_1.join)(id, 'MobileAppFile.json'), getReader);
        return JSON.parse((await (0, promises_1.readFile)(path)).toString());
    }
    async getMobileAppFile(id) {
        const mobileAppFile = await this.getMobileAppFileImmutableFields(id);
        const { crc32c_hex: crc32cHex, size: sizeBytes } = mobileAppFile;
        const getReader = async () => {
            loggingProvider_1.logger.info(`Downloading mobile app file ${id}`);
            try {
                const apiClient = await this.mablApiClientPromise;
                const { download_url: downloadUrl } = await apiClient.getMobileAppFile(id, true);
                return (await apiClient.httpClient.get(downloadUrl, {
                    responseType: 'stream',
                })).data;
            }
            catch (e) {
                throw Error(`Failed to download mobile app file ${id}. ${e}`);
            }
        };
        const extension = this.getMobileAppFileExtension(mobileAppFile);
        if (!extension) {
            throw new Error(`Unable to determine file extension for mobile app file ${id}`);
        }
        const path = await this.getOrCreateFile((0, path_1.join)(id, `MobileAppFile.${extension}`), getReader, {
            crc32cHex: crc32cHex,
            sizeBytes: sizeBytes,
        });
        return { ...mobileAppFile, path };
    }
    retainImmutableFields(mobileAppFile) {
        const immutableFields = { ...mobileAppFile };
        Object.keys(immutableFields).forEach((field) => {
            if (!MOBILE_APP_FILE_IMMUTABLE_FIELD_SET.has(field)) {
                delete immutableFields[field];
            }
        });
        return immutableFields;
    }
    getMobileAppFileExtension({ extension, id, name, platform, }) {
        let resolvedExtension = extension;
        if (!resolvedExtension && name) {
            resolvedExtension = (0, path_1.extname)(name);
        }
        if (!resolvedExtension && platform) {
            switch (platform) {
                case mablApi_1.MobilePlatformEnum.Android:
                    resolvedExtension = 'apk';
                    break;
                case mablApi_1.MobilePlatformEnum.Ios:
                    resolvedExtension = 'app.zip';
                    break;
                default:
                    throw new Error(`Mobile app file ${id} has unknown platform ${platform}`);
            }
        }
        if (resolvedExtension?.startsWith('.')) {
            resolvedExtension = resolvedExtension.substring(1);
        }
        return resolvedExtension;
    }
}
exports.MobileAppFileCache = MobileAppFileCache;
