"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/**
 * @author NovaStepStudios
 * @alias StepnickaSantiago
 * @license Apache-2.0
 * @link https://www.apache.org/licenses/LICENSE-2.0
 */
const os_1 = __importDefault(require("os"));
const path_1 = __importDefault(require("path"));
const fs_1 = __importDefault(require("fs"));
const events_1 = __importDefault(require("events"));
const node_fetch_1 = __importDefault(require("node-fetch"));
const Download_1 = require("../Utils/Download");
class RuntimeDownloader extends events_1.default {
    root;
    javaVersion;
    variant;
    constructor(options) {
        super();
        this.root = options.root;
        this.javaVersion = options.javaVersion || "17";
        this.variant = options.variant || "beta";
    }
    async start() {
        try {
            const javaDir = path_1.default.join(this.root, "runtime", `jre-${this.javaVersion}`);
            fs_1.default.mkdirSync(javaDir, { recursive: true });
            const result = await this.downloadJava(javaDir);
            this.emit("done", result.path);
        }
        catch (err) {
            this.emit("error", err);
        }
    }
    async downloadJava(javaDir) {
        const platformMap = {
            win32: "windows-x64",
            darwin: "mac-os",
            linux: "linux",
        };
        const platform = platformMap[os_1.default.platform()] || os_1.default.platform();
        const metaUrl = "https://launchermeta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json";
        const res = await (0, node_fetch_1.default)(metaUrl);
        if (!res.ok)
            throw new Error(`No se pudo obtener metadata de Mojang: ${res.status}`);
        const meta = (await res.json());
        const platformData = meta[platform];
        if (!platformData)
            throw new Error(`No hay datos para la plataforma ${platform}`);
        let runtimes = platformData[`java-runtime-${this.variant}`] ?? [];
        if (!runtimes.length) {
            const fallback = Object.entries(platformData).find(([_, arr]) => arr && arr.length > 0);
            if (!fallback)
                throw new Error(`No se encontraron runtimes para ${platform}`);
            const [fallbackVariant] = fallback;
            this.variant = fallbackVariant;
            runtimes = platformData[`java-runtime-${this.variant}`] ?? [];
            this.emit("warn", `Variant "${this.variant}" no disponible, usando "${fallbackVariant}"`);
        }
        const selected = runtimes[runtimes.length - 1];
        if (!selected)
            throw new Error(`No se pudo seleccionar versión de Java`);
        const manifestRes = await (0, node_fetch_1.default)(selected.manifest.url);
        if (!manifestRes.ok)
            throw new Error(`No se pudo descargar el manifest: ${manifestRes.status}`);
        const manifestJson = (await manifestRes.json());
        const files = [];
        const manifestEntries = Object.entries(manifestJson.files).filter(([_, info]) => info.downloads);
        const totalSize = manifestEntries.reduce((acc, [_, info]) => {
            const dl = info.downloads.raw || info.downloads.lzma;
            return acc + (dl?.size || 0);
        }, 0);
        let downloadedSize = 0;
        for (const [relPath, info] of manifestEntries) {
            const downloadInfo = info.downloads.raw || info.downloads.lzma;
            if (!downloadInfo?.url)
                continue;
            const localPath = path_1.default.join(javaDir, relPath.replace(/\//g, path_1.default.sep));
            fs_1.default.mkdirSync(path_1.default.dirname(localPath), { recursive: true });
            await (0, Download_1.fromURL)(downloadInfo.url, localPath);
            downloadedSize += downloadInfo.size || 0;
            let percent = totalSize ? (downloadedSize / totalSize) * 100 : 0;
            if (percent > 100)
                percent = 100;
            this.emit("progress", percent, totalSize, `Descargando: ${relPath}`);
            if (info.executable)
                fs_1.default.chmodSync(localPath, 0o777);
            const fileItem = {
                path: localPath,
                executable: !!info.executable,
                type: "Java",
                url: downloadInfo.url,
            };
            if (downloadInfo.sha1)
                fileItem.sha1 = downloadInfo.sha1;
            if (downloadInfo.size !== undefined)
                fileItem.size = downloadInfo.size;
            files.push(fileItem);
        }
        const exePath = path_1.default.join(javaDir, os_1.default.platform() === "win32" ? "bin/javaw.exe" : "bin/java");
        return { files, path: exePath };
    }
}
exports.default = RuntimeDownloader;
