"use strict";
/**
 * Tar.gz Archive Extractor
 * Handles extraction of tar.gz archives using Node.js built-in modules.
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractTarGz = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const zlib = __importStar(require("zlib"));
const platform_detector_1 = require("../binary/platform-detector");
/**
 * Extract tar.gz archive using Node.js built-in modules
 */
function extractTarGz(archivePath, destDir, verbose = false, backend = platform_detector_1.DEFAULT_BACKEND) {
    return new Promise((resolve, reject) => {
        const execName = (0, platform_detector_1.getExecutableName)(backend);
        const archiveBinaryName = (0, platform_detector_1.getArchiveBinaryName)(backend);
        const gunzip = zlib.createGunzip();
        const input = fs.createReadStream(archivePath);
        let headerBuffer = Buffer.alloc(0);
        let currentFile = null;
        let bytesRead = 0;
        let fileBuffer = Buffer.alloc(0);
        const processData = (data) => {
            headerBuffer = Buffer.concat([headerBuffer, data]);
            while (headerBuffer.length >= 512) {
                if (!currentFile) {
                    const header = headerBuffer.subarray(0, 512);
                    headerBuffer = headerBuffer.subarray(512);
                    if (header.every((b) => b === 0))
                        return;
                    let name = '';
                    for (let i = 0; i < 100 && header[i] !== 0; i++) {
                        name += String.fromCharCode(header[i]);
                    }
                    let sizeStr = '';
                    for (let i = 124; i < 136 && header[i] !== 0; i++) {
                        sizeStr += String.fromCharCode(header[i]);
                    }
                    const size = parseInt(sizeStr.trim(), 8) || 0;
                    if (name && size > 0) {
                        const baseName = path.basename(name);
                        if (baseName === execName ||
                            baseName === archiveBinaryName ||
                            baseName === 'cli-proxy-api') {
                            currentFile = { name: baseName, size };
                            fileBuffer = Buffer.alloc(0);
                            bytesRead = 0;
                        }
                        else {
                            const paddedSize = Math.ceil(size / 512) * 512;
                            if (headerBuffer.length >= paddedSize) {
                                headerBuffer = headerBuffer.subarray(paddedSize);
                            }
                            else {
                                currentFile = { name: '', size: paddedSize };
                                bytesRead = 0;
                            }
                        }
                    }
                }
                else {
                    const remaining = currentFile.size - bytesRead;
                    const chunk = headerBuffer.subarray(0, Math.min(remaining, headerBuffer.length));
                    headerBuffer = headerBuffer.subarray(chunk.length);
                    if (currentFile.name)
                        fileBuffer = Buffer.concat([fileBuffer, chunk]);
                    bytesRead += chunk.length;
                    if (bytesRead >= currentFile.size) {
                        if (currentFile.name) {
                            const destPath = path.join(destDir, execName);
                            fs.writeFileSync(destPath, fileBuffer);
                            if (verbose)
                                console.error(`[cliproxy] Extracted: ${currentFile.name} -> ${destPath}`);
                        }
                        const paddedSize = Math.ceil(currentFile.size / 512) * 512;
                        const padding = paddedSize - currentFile.size;
                        if (headerBuffer.length >= padding)
                            headerBuffer = headerBuffer.subarray(padding);
                        currentFile = null;
                        fileBuffer = Buffer.alloc(0);
                    }
                }
            }
        };
        input.pipe(gunzip);
        gunzip.on('data', processData);
        gunzip.on('end', resolve);
        gunzip.on('error', reject);
        input.on('error', reject);
    });
}
exports.extractTarGz = extractTarGz;
//# sourceMappingURL=tar-extractor.js.map