"use strict";
/**
 * Base compression utilities using Web Streams API
 * Shared between Node.js and Browser implementations
 *
 * Uses CompressionStream/DecompressionStream API with "deflate-raw" format
 * (raw DEFLATE without zlib header/trailer, required for ZIP files)
 *
 * Browser fallback: For browsers without deflate-raw support (Firefox < 113, Safari < 16.4),
 * see deflate-fallback.ts for pure JS implementation
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.DEFAULT_COMPRESS_THRESHOLD_BYTES = void 0;
exports.resolveCompressThresholdBytes = resolveCompressThresholdBytes;
exports.hasCompressionStream = hasCompressionStream;
exports.probeDeflateRawCompressionStream = probeDeflateRawCompressionStream;
exports.probeDeflateRawDecompressionStream = probeDeflateRawDecompressionStream;
exports.probeDeflateRawWebStreams = probeDeflateRawWebStreams;
exports.hasDeflateRawCompressionStream = hasDeflateRawCompressionStream;
exports.hasDeflateRawDecompressionStream = hasDeflateRawDecompressionStream;
exports.hasDeflateRawWebStreams = hasDeflateRawWebStreams;
exports.compressWithStream = compressWithStream;
exports.decompressWithStream = decompressWithStream;
const byte_queue_1 = require("../internal/byte-queue.js");
/**
 * Default threshold (in bytes) to choose the lower-overhead path.
 *
 * This is a performance knob, not a correctness requirement.
 * Default: 8MB.
 */
exports.DEFAULT_COMPRESS_THRESHOLD_BYTES = 8 * 1024 * 1024;
/**
 * Resolve the effective threshold bytes.
 */
function resolveCompressThresholdBytes(options) {
    const value = options.thresholdBytes;
    if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
        return exports.DEFAULT_COMPRESS_THRESHOLD_BYTES;
    }
    return value;
}
/**
 * Check if CompressionStream is available
 */
function hasCompressionStream() {
    return typeof CompressionStream !== "undefined";
}
/**
 * Non-cached probe for CompressionStream("deflate-raw") support.
 *
 * Prefer this in code paths that want up-to-date environment checks
 * (e.g. tests that stub globals).
 */
function probeDeflateRawCompressionStream() {
    try {
        if (typeof CompressionStream === "undefined") {
            return false;
        }
        new CompressionStream("deflate-raw");
        return true;
    }
    catch {
        return false;
    }
}
/**
 * Non-cached probe for DecompressionStream("deflate-raw") support.
 */
function probeDeflateRawDecompressionStream() {
    try {
        if (typeof DecompressionStream === "undefined") {
            return false;
        }
        new DecompressionStream("deflate-raw");
        return true;
    }
    catch {
        return false;
    }
}
/**
 * Non-cached probe for full deflate-raw Web Streams support.
 *
 * Returns true only if BOTH CompressionStream("deflate-raw") and
 * DecompressionStream("deflate-raw") are supported.
 */
function probeDeflateRawWebStreams() {
    return probeDeflateRawCompressionStream() && probeDeflateRawDecompressionStream();
}
let _hasDeflateRawCompressionStream = null;
let _hasDeflateRawDecompressionStream = null;
/**
 * Check if CompressionStream supports the "deflate-raw" format.
 *
 * This is a stricter check than {@link hasCompressionStream} because some
 * environments expose CompressionStream but do not support "deflate-raw".
 */
function hasDeflateRawCompressionStream() {
    if (typeof CompressionStream === "undefined") {
        return false;
    }
    if (_hasDeflateRawCompressionStream !== null) {
        return _hasDeflateRawCompressionStream;
    }
    _hasDeflateRawCompressionStream = probeDeflateRawCompressionStream();
    return _hasDeflateRawCompressionStream;
}
/**
 * Check if DecompressionStream supports the "deflate-raw" format.
 */
function hasDeflateRawDecompressionStream() {
    if (typeof DecompressionStream === "undefined") {
        return false;
    }
    if (_hasDeflateRawDecompressionStream !== null) {
        return _hasDeflateRawDecompressionStream;
    }
    _hasDeflateRawDecompressionStream = probeDeflateRawDecompressionStream();
    return _hasDeflateRawDecompressionStream;
}
/**
 * Cached check for full deflate-raw Web Streams support.
 *
 * Returns true only if BOTH CompressionStream("deflate-raw") and
 * DecompressionStream("deflate-raw") are supported.
 */
function hasDeflateRawWebStreams() {
    return hasDeflateRawCompressionStream() && hasDeflateRawDecompressionStream();
}
async function streamToUint8Array(reader) {
    const out = new byte_queue_1.ByteQueue();
    while (true) {
        const { done, value } = await reader.read();
        if (done) {
            break;
        }
        out.append(value);
    }
    return out.read(out.length);
}
async function transformWithStream(data, stream) {
    const writer = stream.writable.getWriter();
    const reader = stream.readable.getReader();
    try {
        // Start reading immediately to avoid potential backpressure deadlocks
        // (writer.write/close may wait for the readable side to be consumed).
        const readPromise = streamToUint8Array(reader);
        await writer.write(data);
        await writer.close();
        return await readPromise;
    }
    finally {
        try {
            writer.releaseLock();
        }
        catch {
            // ignore
        }
        try {
            reader.releaseLock();
        }
        catch {
            // ignore
        }
    }
}
/**
 * Compress using CompressionStream API
 * Uses "deflate-raw" format (required for ZIP files)
 *
 * @param data - Data to compress
 * @returns Compressed data
 */
async function compressWithStream(data) {
    const cs = new CompressionStream("deflate-raw");
    return transformWithStream(data, cs);
}
/**
 * Decompress using DecompressionStream API
 *
 * @param data - Compressed data (deflate-raw format)
 * @returns Decompressed data
 */
async function decompressWithStream(data) {
    const ds = new DecompressionStream("deflate-raw");
    return transformWithStream(data, ds);
}
