/**
 * @license MIT
 * @copyright Copyright (c) 2026, GoldFrite
 */
import EventEmitter from '../utils/events.js';
import manifests from '../utils/manifests.js';
import path_ from 'node:path';
import Downloader from '../utils/downloader.js';
import utils from '../utils/utils.js';
import { spawn } from 'node:child_process';
import { EMLLibError, ErrorType } from '../../types/errors.js';
export default class Java extends EventEmitter {
    constructor(arg1, arg2, arg3) {
        super();
        if (typeof arg1 === 'object' && arg1 !== null) {
            this.minecraftVersion = arg1.minecraft?.version;
            this.root = arg1.root;
            this.url = arg1.url;
        }
        else {
            this.minecraftVersion = arg1 ?? undefined;
            this.root = arg2;
            this.url = arg3;
        }
    }
    /**
     * Get the files of the Java version to download.
     *
     * **You should not use this method directly. Use `Java.download()` instead.**
     * @param manifest [Optional]The manifest of the Minecraft version. If not provided, the manifest
     * will be fetched.
     * @returns The files of the Java version.
     */
    async getFiles(manifest) {
        manifest =
            manifest ??
                (await manifests.getMinecraftManifest({ minecraft: { version: this.minecraftVersion ?? undefined }, url: this.url }));
        const jreVersion = (manifest.javaVersion?.component ?? 'jre-legacy');
        const jreV = manifest.javaVersion?.majorVersion.toString() ?? '8';
        const jreManifest = await manifests.getJavaManifest(jreVersion, jreV);
        let files = [];
        Object.entries(jreManifest.files).forEach((file) => {
            const normalizedPath = this.normalizeJavaPath(file[0], jreV);
            if (!normalizedPath)
                return;
            if (file[1].type === 'directory') {
                files.push({
                    name: path_.basename(file[0]),
                    path: normalizedPath,
                    url: '',
                    type: 'FOLDER'
                });
            }
            else if (file[1].downloads) {
                files.push({
                    name: path_.basename(file[0]),
                    path: normalizedPath,
                    url: file[1].downloads.raw.url,
                    size: file[1].downloads.raw.size,
                    sha1: file[1].downloads.raw.sha1,
                    type: 'JAVA',
                    executable: file[1].executable === true
                });
            }
        });
        return files;
    }
    /**
     * Download Java for the Minecraft version.
     */
    async download() {
        const files = await this.getFiles();
        const downloader = new Downloader(utils.getServerFolder(this.root));
        downloader.forwardEvents(this);
        await downloader.download(files);
    }
    /**
     * Check if Java is correctly installed.
     * @param absolutePath [Optional: defaults to `path.join(utils.getServerFolder(this.root),
     * 'runtime', 'jre-${X}', 'bin', 'java')`]
     * Absolute path to the Java executable. You can use  `${X}` to replace it with the major
     * version of Java.
     * @param majorVersion [Optional: defaults to `8`]
     * Major version of Java to check.
     * @returns The version and architecture of Java.
     */
    async check(absolutePath = path_.join(utils.getServerFolder(this.root), 'runtime', 'jre-${X}', 'bin', 'java'), majorVersion = 8) {
        return new Promise((resolve, reject) => {
            const javaExec = absolutePath.replace('${X}', majorVersion + '');
            const process = spawn(javaExec, ['-version']);
            let output = '';
            process.stdout.on('data', (data) => {
                output += data.toString();
            });
            process.stderr.on('data', (data) => {
                output += data.toString();
            });
            process.on('error', (err) => {
                reject(new EMLLibError(ErrorType.JAVA_ERROR, `Java is not correctly installed: ${err.message}`));
            });
            process.on('close', (code) => {
                if (code !== 0 && output.length === 0) {
                    reject(new EMLLibError(ErrorType.JAVA_ERROR, `Java exited with code ${code}`));
                    return;
                }
                const versionMatch = output.match(/"(.*?)"/);
                const version = versionMatch ? versionMatch.pop() : majorVersion + '';
                const arch = output.includes('64-Bit') ? '64-bit' : '32-bit';
                const res = { version: version, arch: arch };
                this.emit('java_info', res);
                resolve(res);
            });
        });
    }
    normalizeJavaPath(filePath, jreV) {
        if (filePath.endsWith('.bundle'))
            return null;
        if (filePath.includes('.bundle/')) {
            const homeIndex = filePath.indexOf('.bundle/Contents/Home/');
            if (homeIndex === -1)
                return null;
            const relativePath = filePath.slice(homeIndex + '.bundle/Contents/Home/'.length);
            return path_.join('runtime', `jre-${jreV}`, path_.dirname(relativePath), '/');
        }
        return path_.join('runtime', `jre-${jreV}`, path_.dirname(filePath), '/');
    }
}
//# sourceMappingURL=java.js.map