"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getCompressionVersion = getCompressionVersion;
exports.compressData = compressData;
exports.decompressData = decompressData;
const lzma_wasm_1 = require("./lzma-wasm");
const COMPRESSION_VERSION = '1';
const MINIMUM_SIZE_FOR_COMPRESSION = 64;
/** UTIs for formats that are already compressed and won't benefit from additional compression. */
const ALREADY_COMPRESSED_UTIS = new Set([
    // Images
    'public.jpeg',
    'public.jpeg2000',
    'public.png',
    'com.compuserve.gif',
    'com.microsoft.bmp', // low entropy but compression marginal vs overhead
    // Video
    'public.mpeg',
    'public.mpeg4',
    'public.mpegts',
    'com.apple.quicktime-movie',
    // Audio
    'public.mpeg4-audio',
    'public.mp3',
    // Archives / compressed formats
    'com.pkware.zip-archive',
    'org.gnu.gnu-zip-archive',
    'org.bzip.bzip2-archive',
    'com.rarlab.rar-archive',
    'com.allume.stuffit-archive',
    'org.7-zip.7-zip-archive',
    'public.tar-archive',
    'org.gnu.gnu-tar-archive',
    // Legacy UTI variants (pre-v1.0.117 camelCase format)
    'com.pkware.zipArchive',
    'org.gnu.gnuZipArchive',
    'org.bzip.bzip2Archive',
    'com.rarlab.rarArchive',
    'com.allume.stuffitArchive',
    'org.gnu.gnuTarArchive',
    'public.mpeg4Audio',
    'com.apple.quicktimeMovie',
]);
/**
 * Returns the current compression algorithms version string.
 * This version is bumped whenever the set of tried algorithms changes.
 */
function getCompressionVersion() {
    return COMPRESSION_VERSION;
}
/**
 * Attempts to compress the given data using available compression algorithms, picking the best result.
 * If any of the provided UTIs indicates the data is already in a compressed format (jpeg, png, zip, ...),
 * compression is skipped entirely.
 *
 * @param data the raw data to compress.
 * @param utis optional UTIs describing the data format; used to skip compression for already-compressed formats.
 * @returns the (possibly compressed) data and the algorithm used, or undefined if no compression was applied.
 */
function compressData(data, utis) {
    return __awaiter(this, void 0, void 0, function* () {
        const raw = toArrayBuffer(data);
        if ((utis === null || utis === void 0 ? void 0 : utis.some((uti) => ALREADY_COMPRESSED_UTIS.has(uti))) || raw.byteLength < MINIMUM_SIZE_FOR_COMPRESSION) {
            return { data: raw, algorithm: undefined };
        }
        const compressed = yield (0, lzma_wasm_1.lzmaWasmCompress)(data);
        if (compressed.byteLength < raw.byteLength) {
            return { data: compressed, algorithm: 'lzma2' };
        }
        return { data: raw, algorithm: undefined };
    });
}
/**
 * Decompresses data that was compressed using one of the supported algorithms.
 *
 * @param data the compressed data.
 * @param algorithm the compression algorithm that was used (e.g. 'lzma'). If undefined, returns the data as-is.
 * @returns the decompressed data.
 * @throws if the algorithm is not supported or decompression fails.
 */
function decompressData(data, algorithm) {
    return __awaiter(this, void 0, void 0, function* () {
        if (!algorithm) {
            return toArrayBuffer(data);
        }
        if (algorithm === 'lzma2') {
            return (0, lzma_wasm_1.lzmaWasmDecompress)(data);
        }
        throw new Error(`Unsupported compression algorithm: ${algorithm}`);
    });
}
function toArrayBuffer(data) {
    if (data instanceof ArrayBuffer)
        return data;
    return new Uint8Array(data).buffer;
}
//# sourceMappingURL=compression-utils.js.map