"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MinecraftLauncher = void 0;
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const child_process_1 = require("child_process");
const events_1 = require("events");
const Version_1 = require("./Minecraft/Handler/Version");
const Arguments_1 = require("./Minecraft/Handler/Arguments");
const Classpath_1 = require("./Minecraft/Handler/Classpath");
class MinecraftLauncher extends events_1.EventEmitter {
    options;
    timers = {};
    constructor(options) {
        super();
        this.options = options;
    }
    startTimer(label) {
        this.timers[label] = Date.now();
    }
    endTimer(label) {
        if (!this.timers[label])
            return;
        const elapsed = Date.now() - this.timers[label];
        this.emit("speed", `${label} completado en ${elapsed}ms`);
        delete this.timers[label];
    }
    async launch() {
        const { root, version, javaPath, authenticator, debug, memory, jvmArgs = [], mcArgs = [] } = this.options;
        try {
            if (!fs_1.default.existsSync(javaPath)) {
                const msg = `No se encontró el ejecutable de Java en: ${javaPath}`;
                this.emit("error", msg);
                throw new Error(msg);
            }
            this.emit("debug", `Cargando versión: ${version}`);
            this.startTimer("Carga de versión");
            const versionHandler = new Version_1.VersionHandler(root);
            const versionData = versionHandler.loadVersion(version);
            // versionSafe: Todos los valores obligatorios con fallback
            const versionSafe = {
                id: versionData.id,
                type: versionData.type || "release",
                mainClass: versionData.mainClass || "net.minecraft.client.main.Main",
                assets: versionData.assets || "legacy",
                assetIndex: versionData.assetIndex || { id: "legacy", url: "" },
                minecraftArguments: versionData.minecraftArguments || "",
                arguments: versionData.arguments ?? { game: [], jvm: [] },
                inheritsFrom: versionData.inheritsFrom || "",
                libraries: versionData.libraries ?? [],
                logging: versionData.logging ?? undefined,
                javaVersion: versionData.javaVersion ?? { majorVersion: 8 },
            };
            this.endTimer("Carga de versión");
            this.emit("debug", `Construyendo classpath...`);
            this.startTimer("Construcción de classpath");
            const classpathManager = new Classpath_1.ClasspathManager(root, versionSafe);
            const { classpath } = classpathManager.buildClasspath();
            this.endTimer("Construcción de classpath");
            this.emit("debug", `Classpath listo con ${classpath.length} entradas.`);
            const classpathString = classpath.join(path_1.default.delimiter);
            this.emit("debug", `Classpath: ${classpathString}`);
            this.emit("debug", `Generando argumentos de inicio...`);
            this.startTimer("Generación de argumentos");
            const args = Arguments_1.ArgumentBuilder.build({
                opts: {
                    root,
                    memory: memory ?? { min: "512M", max: "2G" },
                    window: {
                        width: this.options.window?.width ?? 854,
                        height: this.options.window?.height ?? 480,
                        fullscreen: this.options.window?.fullscreen ?? false,
                    },
                    debug: Boolean(debug),
                },
                version: versionSafe,
                auth: {
                    name: authenticator?.name ?? "Player",
                    uuid: authenticator?.uuid ?? "00000000-0000-0000-0000-000000000000",
                    accessToken: authenticator?.access_token ?? "",
                    provider: authenticator?.meta?.type ?? "mojang",
                    userProperties: { value: authenticator?.user_properties ?? "{}" },
                    clientId: authenticator?.client_token ?? "",
                    offline: !authenticator,
                },
                classPath: classpath,
            });
            this.endTimer("Generación de argumentos");
            const finalArgs = [...jvmArgs, ...args, ...mcArgs];
            this.emit("debug", `Ejecutando Java desde: ${javaPath}`);
            this.emit("debug", `Argumentos finales: ${finalArgs.join(" ")}`);
            const childProcess = (0, child_process_1.spawn)(javaPath, finalArgs, { cwd: root, detached: false, stdio: ["pipe", "pipe", "pipe"] });
            childProcess.stdout?.on("data", (data) => this.emit("data", data.toString().trim()));
            childProcess.stderr?.on("data", (data) => {
                const msg = data.toString().trim();
                if (msg.toLowerCase().includes("error"))
                    this.emit("error", msg);
                else
                    this.emit("warn", msg);
            });
            childProcess.on("error", (err) => this.emit("error", `Error al iniciar el proceso: ${err}`));
            childProcess.on("close", (code) => {
                if (code === 0)
                    this.emit("debug", `Minecraft salió correctamente con código ${code}`);
                else
                    this.emit("error", `Minecraft salió con código ${code}`);
            });
        }
        catch (err) {
            this.emit("error", err instanceof Error ? err.message : String(err));
            throw err;
        }
    }
}
exports.MinecraftLauncher = MinecraftLauncher;
