import axios from 'axios';
import fs from '../../../utils/fsExtraCompat.js';
import { promises as fsPromises, existsSync, readdirSync } from 'fs';
import { createWriteStream } from 'fs';
import * as path from 'path';
import { spawn } from 'child_process';
export class ApiService {
    static async getServerClassify() {
        try {
            const response = await axios.get(`${this.BASE_URL}/query/server_classify`);
            if (response.data.code !== 200) {
                throw new Error(`API错误: ${response.data.message}`);
            }
            return response.data.data;
        }
        catch (error) {
            if (axios.isAxiosError(error)) {
                throw new Error(`网络请求失败: ${error.message}`);
            }
            throw error;
        }
    }
    static async getAvailableVersions(server) {
        try {
            const response = await axios.get(`${this.BASE_URL}/query/available_versions/${server}`);
            if (response.data.code !== 200) {
                throw new Error(`API错误: ${response.data.message}`);
            }
            return response.data.data.versionList;
        }
        catch (error) {
            if (axios.isAxiosError(error)) {
                throw new Error(`网络请求失败: ${error.message}`);
            }
            throw error;
        }
    }
    static async getDownloadUrl(server, version) {
        try {
            const response = await axios.get(`${this.BASE_URL}/download/server/${server}/${version}`);
            if (response.data.code !== 200) {
                throw new Error(`API错误: ${response.data.message}`);
            }
            return response.data.data;
        }
        catch (error) {
            if (axios.isAxiosError(error)) {
                throw new Error(`网络请求失败: ${error.message}`);
            }
            throw error;
        }
    }
    static async downloadFile(url, filePath, onProgress, onLog) {
        try {
            if (onLog && !onLog.length) {
                onLog('开始下载文件...', 'info');
            }
            const response = await axios({
                method: 'GET',
                url: url,
                responseType: 'stream',
                timeout: 300000,
                onDownloadProgress: (progressEvent) => {
                    if (progressEvent.total && onProgress) {
                        const percentage = Math.round((progressEvent.loaded * 100) / progressEvent.total);
                        onProgress({
                            loaded: progressEvent.loaded,
                            total: progressEvent.total,
                            percentage
                        });
                    }
                }
            });
            const writer = createWriteStream(filePath);
            response.data.pipe(writer);
            return new Promise((resolve, reject) => {
                writer.on('finish', () => {
                    if (onLog) {
                        onLog('文件下载完成!', 'success');
                    }
                    resolve();
                });
                writer.on('error', (error) => {
                    if (onLog) {
                        onLog('文件写入失败!', 'error');
                    }
                    reject(error);
                });
                const timeout = setTimeout(() => {
                    writer.destroy();
                    reject(new Error('下载超时'));
                }, 300000);
                writer.on('finish', () => clearTimeout(timeout));
                writer.on('error', () => clearTimeout(timeout));
            });
        }
        catch (error) {
            if (axios.isAxiosError(error)) {
                if (error.code === 'ECONNABORTED') {
                    throw new Error('下载超时，请检查网络连接');
                }
                throw new Error(`文件下载失败: ${error.message}`);
            }
            throw error;
        }
    }
}
ApiService.BASE_URL = 'https://api.mslmc.cn/v3';
export class FileManager {
    static normalizePath(inputPath) {
        if (!path.isAbsolute(inputPath)) {
            inputPath = path.resolve(process.cwd(), inputPath);
        }
        return path.normalize(inputPath);
    }
    static async checkDirectoryPermissions(dirPath) {
        try {
            const testFile = path.join(dirPath, '.write-test-' + Date.now());
            await fsPromises.writeFile(testFile, 'test');
            await fs.remove(testFile);
            return true;
        }
        catch (error) {
            return false;
        }
    }
    static async createTempDirectory() {
        await fs.ensureDir(this.tempDir);
        return this.tempDir;
    }
    static getServerJarPath(server, version) {
        return path.join(this.tempDir, `${server}-${version}.jar`);
    }
    static async fileExists(filePath) {
        try {
            await fsPromises.access(filePath);
            return true;
        }
        catch {
            return false;
        }
    }
    static isForgeInstaller(jarPath) {
        const fileName = path.basename(jarPath).toLowerCase();
        return fileName.startsWith('forge-') || fileName.startsWith('neoforge-');
    }
    static async runForgeInstaller(jarPath, onLog) {
        return new Promise(async (resolve, reject) => {
            if (onLog) {
                onLog('检测到Forge/NeoForge安装器，正在执行静默安装...', 'info');
            }
            const installerProcess = spawn('java', ['-jar', path.basename(jarPath), '--installServer'], {
                cwd: path.dirname(jarPath),
                stdio: ['pipe', 'pipe', 'pipe']
            });
            let installerCompleted = false;
            installerProcess.stdout?.on('data', async (data) => {
                const output = data.toString();
                if (onLog) {
                    onLog(output, 'info');
                }
                if (output.includes('You can delete this installer file now if you wish')) {
                    installerCompleted = true;
                    if (onLog) {
                        onLog('Forge/NeoForge安装器安装完成，准备运行服务端...', 'success');
                    }
                    try {
                        if (onLog) {
                            onLog(`开始调用runForgeServer，目录: ${path.dirname(jarPath)}`, 'info');
                        }
                        await this.runForgeServer(path.dirname(jarPath), onLog);
                        if (onLog) {
                            onLog('runForgeServer执行完成', 'success');
                        }
                        if (!installerProcess.killed) {
                            installerProcess.kill('SIGTERM');
                        }
                        resolve();
                    }
                    catch (error) {
                        if (onLog) {
                            onLog(`runForgeServer执行失败: ${error}`, 'error');
                        }
                        if (!installerProcess.killed) {
                            installerProcess.kill('SIGTERM');
                        }
                        reject(error);
                    }
                }
            });
            installerProcess.stderr?.on('data', (data) => {
                const output = data.toString();
                if (onLog) {
                    onLog(output, 'error');
                }
            });
            installerProcess.on('close', async (code) => {
                if (installerCompleted) {
                    if (onLog) {
                        onLog('Forge/NeoForge安装器进程已退出。', 'info');
                    }
                    return;
                }
                if (code === 0) {
                    if (onLog) {
                        onLog('Forge/NeoForge安装器执行完成，但未检测到完成标志。', 'warn');
                    }
                    resolve();
                }
                else {
                    reject(new Error(`Forge/NeoForge安装器异常退出，退出码: ${code}`));
                }
            });
            installerProcess.on('error', (error) => {
                reject(new Error(`启动Forge/NeoForge安装器失败: ${error.message}`));
            });
            setTimeout(() => {
                if (!installerProcess.killed) {
                    if (onLog) {
                        onLog('Forge/NeoForge安装器运行超时，正在强制关闭...', 'warn');
                    }
                    installerProcess.kill('SIGKILL');
                    resolve();
                }
            }, 10 * 60 * 1000);
        });
    }
    static async runForgeServer(serverDir, onLog) {
        return new Promise((resolve, reject) => {
            const isWindows = process.platform === 'win32';
            const scriptName = isWindows ? 'run.bat' : 'run.sh';
            const scriptPath = path.join(serverDir, scriptName);
            if (onLog) {
                onLog(`正在检查启动脚本: ${scriptPath}`, 'info');
            }
            if (!existsSync(scriptPath)) {
                if (onLog) {
                    onLog(`启动脚本${scriptName}不存在于目录${serverDir}，跳过服务端运行`, 'warn');
                    try {
                        const files = readdirSync(serverDir);
                        onLog(`目录${serverDir}中的文件: ${files.join(', ')}`, 'info');
                    }
                    catch (err) {
                        onLog(`无法读取目录${serverDir}: ${err}`, 'error');
                    }
                }
                resolve();
                return;
            }
            if (onLog) {
                onLog(`找到启动脚本${scriptName}，正在运行...`, 'info');
            }
            const serverProcess = isWindows
                ? spawn('cmd', ['/c', scriptName], {
                    cwd: serverDir,
                    stdio: ['pipe', 'pipe', 'pipe']
                })
                : spawn('bash', [scriptName], {
                    cwd: serverDir,
                    stdio: ['pipe', 'pipe', 'pipe']
                });
            let hasEulaMessage = false;
            serverProcess.stdout?.on('data', (data) => {
                const output = data.toString();
                if (onLog) {
                    onLog(output, 'info');
                }
                if (output.toLowerCase().includes('eula') ||
                    output.toLowerCase().includes('you need to agree to the eula')) {
                    hasEulaMessage = true;
                    if (onLog) {
                        onLog('检测到EULA协议提示，正在关闭服务端...', 'info');
                    }
                    serverProcess.kill('SIGTERM');
                }
            });
            serverProcess.stderr?.on('data', (data) => {
                const output = data.toString();
                if (onLog) {
                    onLog(output, 'error');
                }
                if (output.toLowerCase().includes('eula')) {
                    hasEulaMessage = true;
                    if (onLog) {
                        onLog('检测到EULA协议提示，正在关闭服务端...', 'info');
                    }
                    serverProcess.kill('SIGTERM');
                }
            });
            serverProcess.on('close', (code) => {
                if (hasEulaMessage) {
                    if (onLog) {
                        onLog('服务端已关闭，EULA协议检测完成。', 'success');
                    }
                    resolve();
                }
                else if (code === 0) {
                    if (onLog) {
                        onLog('服务端正常退出。', 'success');
                    }
                    resolve();
                }
                else {
                    if (onLog) {
                        onLog(`服务端退出，退出码: ${code}`, 'info');
                    }
                    resolve();
                }
            });
            serverProcess.on('error', (error) => {
                if (onLog) {
                    onLog(`启动服务端失败: ${error.message}`, 'error');
                }
                resolve();
            });
            setTimeout(() => {
                if (!serverProcess.killed) {
                    if (onLog) {
                        onLog('服务端运行超时，正在强制关闭...', 'warn');
                    }
                    serverProcess.kill('SIGKILL');
                    resolve();
                }
            }, 10 * 60 * 1000);
        });
    }
    static async runServerUntilEula(jarPath, onLog) {
        if (this.isForgeInstaller(jarPath)) {
            return this.runForgeInstaller(jarPath, onLog);
        }
        return new Promise((resolve, reject) => {
            if (onLog) {
                onLog('正在启动服务端...', 'info');
            }
            const serverProcess = spawn('java', ['-jar', path.basename(jarPath)], {
                cwd: path.dirname(jarPath),
                stdio: ['pipe', 'pipe', 'pipe']
            });
            let hasEulaMessage = false;
            serverProcess.stdout?.on('data', (data) => {
                const output = data.toString();
                if (onLog) {
                    onLog(output, 'info');
                }
                if (output.toLowerCase().includes('eula') ||
                    output.toLowerCase().includes('you need to agree to the eula')) {
                    hasEulaMessage = true;
                    if (onLog) {
                        onLog('检测到EULA协议提示，正在关闭服务端...', 'info');
                    }
                    serverProcess.kill('SIGTERM');
                }
            });
            serverProcess.stderr?.on('data', (data) => {
                const output = data.toString();
                if (onLog) {
                    onLog(output, 'error');
                }
                if (output.toLowerCase().includes('eula')) {
                    hasEulaMessage = true;
                    if (onLog) {
                        onLog('检测到EULA协议提示，正在关闭服务端...', 'info');
                    }
                    serverProcess.kill('SIGTERM');
                }
            });
            serverProcess.on('close', (code) => {
                if (hasEulaMessage) {
                    if (onLog) {
                        onLog('服务端已关闭，EULA协议检测完成。', 'success');
                    }
                    resolve();
                }
                else if (code === 0) {
                    if (onLog) {
                        onLog('服务端正常退出。', 'success');
                    }
                    resolve();
                }
                else {
                    reject(new Error(`服务端异常退出，退出码: ${code}`));
                }
            });
            serverProcess.on('error', (error) => {
                reject(new Error(`启动服务端失败: ${error.message}`));
            });
            setTimeout(() => {
                if (!serverProcess.killed) {
                    if (onLog) {
                        onLog('服务端运行超时，正在强制关闭...', 'warn');
                    }
                    serverProcess.kill('SIGKILL');
                    resolve();
                }
            }, 10 * 60 * 1000);
        });
    }
    static async moveFilesToTarget(targetDir, onLog) {
        const normalizedTargetDir = this.normalizePath(targetDir);
        await fs.ensureDir(normalizedTargetDir);
        const hasPermission = await this.checkDirectoryPermissions(normalizedTargetDir);
        if (!hasPermission) {
            throw new Error(`目标目录没有写权限: ${normalizedTargetDir}。请检查目录权限或使用sudo运行。`);
        }
        const files = await fsPromises.readdir(this.tempDir);
        if (onLog) {
            onLog(`正在移动 ${files.length} 个文件到目标目录: ${normalizedTargetDir}`, 'info');
        }
        for (const file of files) {
            const sourcePath = path.join(this.tempDir, file);
            const targetPath = path.join(normalizedTargetDir, file);
            try {
                const sourceExists = await this.fileExists(sourcePath);
                if (!sourceExists) {
                    if (onLog) {
                        onLog(`跳过不存在的文件: ${file}`, 'warn');
                    }
                    continue;
                }
                await fs.move(sourcePath, targetPath, { overwrite: true });
                const targetExists = await this.fileExists(targetPath);
                if (!targetExists) {
                    throw new Error(`文件移动后验证失败: ${file}`);
                }
                const stat = await fsPromises.stat(targetPath);
                if (stat.isFile()) {
                    if (onLog) {
                        onLog(`已移动文件: ${file}`, 'info');
                    }
                }
                else if (stat.isDirectory()) {
                    if (onLog) {
                        onLog(`已移动目录: ${file}`, 'info');
                    }
                }
            }
            catch (error) {
                const errorMessage = error instanceof Error ? error.message : String(error);
                if (onLog) {
                    onLog(`移动失败: ${file} - ${errorMessage}`, 'error');
                }
                if (process.platform !== 'win32' && errorMessage.includes('EACCES')) {
                    throw new Error(`权限被拒绝，无法移动文件 ${file}。请检查文件权限或使用sudo运行。`);
                }
                else if (errorMessage.includes('ENOSPC')) {
                    throw new Error(`磁盘空间不足，无法移动文件 ${file}。`);
                }
                else if (errorMessage.includes('EXDEV')) {
                    throw new Error(`跨设备移动文件失败 ${file}。尝试复制后删除源文件。`);
                }
                throw new Error(`移动文件失败: ${file} - ${errorMessage}`);
            }
        }
    }
    static async cleanupTempDirectory(onLog) {
        try {
            if (await this.fileExists(this.tempDir)) {
                await fs.remove(this.tempDir);
                if (onLog) {
                    onLog('临时目录已清理。', 'info');
                }
            }
        }
        catch (error) {
            if (onLog) {
                onLog(`清理临时目录时出现警告: ${error}`, 'warn');
            }
        }
    }
    static async forceCleanupDirectory(dirPath, onLog) {
        try {
            if (await this.fileExists(dirPath)) {
                await fs.remove(dirPath);
                if (onLog) {
                    onLog(`已清理目录: ${dirPath}`, 'info');
                }
            }
        }
        catch (error) {
            if (onLog) {
                onLog(`清理目录时出现警告: ${dirPath} - ${error}`, 'warn');
            }
        }
    }
    static getTempDirectory() {
        return this.tempDir;
    }
    static async validateJavaEnvironment() {
        return new Promise((resolve) => {
            const javaProcess = spawn('java', ['-version'], { stdio: 'pipe' });
            javaProcess.on('close', (code) => {
                resolve(code === 0);
            });
            javaProcess.on('error', () => {
                resolve(false);
            });
        });
    }
}
FileManager.tempDir = path.join(process.cwd(), 'temp-minecraft-server');
export class MinecraftServerDownloader {
    constructor(onProgress, onLog) {
        this.cancelled = false;
        this.onProgress = onProgress;
        this.onLog = onLog;
    }
    cancel() {
        this.cancelled = true;
        if (this.currentProcess && !this.currentProcess.killed) {
            this.currentProcess.kill('SIGTERM');
            setTimeout(() => {
                if (this.currentProcess && !this.currentProcess.killed) {
                    this.currentProcess.kill('SIGKILL');
                }
            }, 5000);
        }
        if (this.tempDir) {
            FileManager.cleanupTempDirectory(this.onLog).catch(() => {
            });
        }
        if (this.onLog) {
            this.onLog('Minecraft服务端部署已取消', 'warn');
        }
    }
    isCancelled() {
        return this.cancelled;
    }
    async downloadServer(options) {
        const { server, version, targetDirectory = './minecraft-server', skipJavaCheck = false, skipServerRun = false, silent = false } = options;
        const normalizedTargetDirectory = FileManager.normalizePath(targetDirectory);
        const log = silent ? undefined : this.onLog;
        this.cancelled = false;
        try {
            if (this.cancelled) {
                throw new Error('操作已取消');
            }
            if (!skipJavaCheck) {
                if (log)
                    log('检查Java环境...', 'info');
                const hasJava = await FileManager.validateJavaEnvironment();
                if (!hasJava) {
                    throw new Error('未检测到Java环境，请确保已安装Java并添加到PATH环境变量中。');
                }
                if (log)
                    log('Java环境检查通过。', 'success');
            }
            if (!server || !version) {
                throw new Error('缺少必要参数：server 和 version');
            }
            if (this.cancelled) {
                throw new Error('操作已取消');
            }
            if (log)
                log('创建临时工作目录...', 'info');
            this.tempDir = await FileManager.createTempDirectory();
            if (log)
                log(`临时目录创建成功: ${this.tempDir}`, 'success');
            try {
                if (this.cancelled) {
                    throw new Error('操作已取消');
                }
                if (log)
                    log('正在获取下载地址...', 'info');
                const downloadData = await ApiService.getDownloadUrl(server, version);
                if (log)
                    log('下载地址获取成功。', 'success');
                if (this.cancelled) {
                    throw new Error('操作已取消');
                }
                const jarPath = FileManager.getServerJarPath(server, version);
                if (log)
                    log(`正在下载服务端核心到: ${jarPath}`, 'info');
                await ApiService.downloadFile(downloadData.url, jarPath, this.onProgress, log);
                if (log)
                    log('服务端核心下载完成。', 'success');
                if (this.cancelled) {
                    throw new Error('操作已取消');
                }
                if (!skipServerRun) {
                    if (log)
                        log('正在运行服务端核心...', 'info');
                    if (log)
                        log('注意: 服务端将运行直到出现EULA协议提示，然后自动关闭。', 'info');
                    this.currentProcess = await this.runServerUntilEulaWithCancel(jarPath, log);
                    if (log)
                        log('服务端运行完成。', 'success');
                }
                if (this.cancelled) {
                    throw new Error('操作已取消');
                }
                if (log)
                    log(`正在移动文件到目标目录: ${normalizedTargetDirectory}`, 'info');
                await FileManager.moveFilesToTarget(normalizedTargetDirectory, log);
                if (log)
                    log('文件移动完成。', 'success');
            }
            finally {
                if (log)
                    log('正在清理临时文件...', 'info');
                await FileManager.cleanupTempDirectory(log);
                if (log)
                    log('临时文件清理完成。', 'success');
                this.tempDir = undefined;
            }
            if (!this.cancelled && log) {
                log('=== 所有操作完成 ===', 'success');
                log(`服务端文件已保存到: ${normalizedTargetDirectory}`, 'info');
                log('您现在可以在目标目录中找到服务端文件。', 'info');
                if (!skipServerRun) {
                    log('如需同意EULA协议，请编辑 eula.txt 文件并将 eula=false 改为 eula=true', 'info');
                }
            }
        }
        catch (error) {
            try {
                await FileManager.cleanupTempDirectory();
                this.tempDir = undefined;
            }
            catch (cleanupError) {
                if (log)
                    log(`清理临时目录时出现问题: ${cleanupError}`, 'warn');
            }
            throw error;
        }
    }
    async getServerCategories() {
        const serverClassifyData = await ApiService.getServerClassify();
        return this.formatServerCategories(serverClassifyData);
    }
    async getAvailableVersions(server) {
        return await ApiService.getAvailableVersions(server);
    }
    async getDownloadInfo(server, version) {
        return await ApiService.getDownloadUrl(server, version);
    }
    async runForgeInstallerWithCancel(jarPath, onLog) {
        return new Promise((resolve, reject) => {
            if (this.cancelled) {
                reject(new Error('操作已取消'));
                return;
            }
            if (onLog) {
                onLog('检测到Forge/NeoForge安装器，正在执行静默安装...', 'info');
            }
            const installerProcess = spawn('java', ['-jar', path.basename(jarPath), '--installServer'], {
                cwd: path.dirname(jarPath),
                stdio: ['pipe', 'pipe', 'pipe']
            });
            this.currentProcess = installerProcess;
            installerProcess.stdout?.on('data', (data) => {
                if (this.cancelled) {
                    installerProcess.kill('SIGTERM');
                    return;
                }
                const output = data.toString();
                if (onLog) {
                    onLog(output, 'info');
                }
            });
            installerProcess.stderr?.on('data', (data) => {
                if (this.cancelled) {
                    installerProcess.kill('SIGTERM');
                    return;
                }
                const output = data.toString();
                if (onLog) {
                    onLog(output, 'error');
                }
            });
            installerProcess.on('close', (code) => {
                this.currentProcess = undefined;
                if (this.cancelled) {
                    reject(new Error('操作已取消'));
                    return;
                }
                if (code === 0) {
                    if (onLog) {
                        onLog('Forge/NeoForge安装器执行完成。', 'success');
                    }
                    resolve(installerProcess);
                }
                else {
                    reject(new Error(`Forge/NeoForge安装器异常退出，退出码: ${code}`));
                }
            });
            installerProcess.on('error', (error) => {
                this.currentProcess = undefined;
                reject(new Error(`启动Forge/NeoForge安装器失败: ${error.message}`));
            });
            setTimeout(() => {
                if (!installerProcess.killed && !this.cancelled) {
                    if (onLog) {
                        onLog('Forge/NeoForge安装器运行超时，正在强制关闭...', 'warn');
                    }
                    installerProcess.kill('SIGKILL');
                    this.currentProcess = undefined;
                    resolve(installerProcess);
                }
            }, 10 * 60 * 1000);
        });
    }
    async runServerUntilEulaWithCancel(jarPath, onLog) {
        if (FileManager.isForgeInstaller(jarPath)) {
            return this.runForgeInstallerWithCancel(jarPath, onLog);
        }
        return new Promise((resolve, reject) => {
            if (this.cancelled) {
                reject(new Error('操作已取消'));
                return;
            }
            if (onLog) {
                onLog('正在启动服务端...', 'info');
            }
            const serverProcess = spawn('java', ['-jar', path.basename(jarPath)], {
                cwd: path.dirname(jarPath),
                stdio: ['pipe', 'pipe', 'pipe']
            });
            this.currentProcess = serverProcess;
            let hasEulaMessage = false;
            serverProcess.stdout?.on('data', (data) => {
                if (this.cancelled) {
                    serverProcess.kill('SIGTERM');
                    return;
                }
                const output = data.toString();
                if (onLog) {
                    onLog(output, 'info');
                }
                if (output.toLowerCase().includes('eula') ||
                    output.toLowerCase().includes('you need to agree to the eula')) {
                    hasEulaMessage = true;
                    if (onLog) {
                        onLog('检测到EULA协议提示，正在关闭服务端...', 'info');
                    }
                    serverProcess.kill('SIGTERM');
                }
            });
            serverProcess.stderr?.on('data', (data) => {
                if (this.cancelled) {
                    serverProcess.kill('SIGTERM');
                    return;
                }
                const output = data.toString();
                if (onLog) {
                    onLog(output, 'error');
                }
                if (output.toLowerCase().includes('eula')) {
                    hasEulaMessage = true;
                    if (onLog) {
                        onLog('检测到EULA协议提示，正在关闭服务端...', 'info');
                    }
                    serverProcess.kill('SIGTERM');
                }
            });
            serverProcess.on('close', (code) => {
                this.currentProcess = undefined;
                if (this.cancelled) {
                    reject(new Error('操作已取消'));
                    return;
                }
                if (hasEulaMessage) {
                    if (onLog) {
                        onLog('服务端已关闭，EULA协议检测完成。', 'success');
                    }
                    resolve(serverProcess);
                }
                else if (code === 0) {
                    if (onLog) {
                        onLog('服务端正常退出。', 'success');
                    }
                    resolve(serverProcess);
                }
                else {
                    reject(new Error(`服务端异常退出，退出码: ${code}`));
                }
            });
            serverProcess.on('error', (error) => {
                this.currentProcess = undefined;
                reject(new Error(`启动服务端失败: ${error.message}`));
            });
            setTimeout(() => {
                if (!serverProcess.killed && !this.cancelled) {
                    if (onLog) {
                        onLog('服务端运行超时，正在强制关闭...', 'warn');
                    }
                    serverProcess.kill('SIGKILL');
                    this.currentProcess = undefined;
                    resolve(serverProcess);
                }
            }, 10 * 60 * 1000);
        });
    }
    async validateJava() {
        return await FileManager.validateJavaEnvironment();
    }
    formatServerCategories(data) {
        const categories = [
            {
                name: 'pluginsCore',
                displayName: '插件服务端核心',
                servers: data.pluginsCore || []
            },
            {
                name: 'pluginsAndModsCore_Forge',
                displayName: '插件+模组服务端核心 (Forge)',
                servers: data.pluginsAndModsCore_Forge || []
            },
            {
                name: 'pluginsAndModsCore_Fabric',
                displayName: '插件+模组服务端核心 (Fabric)',
                servers: data.pluginsAndModsCore_Fabric || []
            },
            {
                name: 'modsCore_Forge',
                displayName: '模组服务端核心 (Forge)',
                servers: data.modsCore_Forge || []
            },
            {
                name: 'modsCore_Fabric',
                displayName: '模组服务端核心 (Fabric)',
                servers: data.modsCore_Fabric || []
            },
            {
                name: 'vanillaCore',
                displayName: '原版服务端核心',
                servers: data.vanillaCore || []
            },
            {
                name: 'bedrockCore',
                displayName: '基岩版服务端核心',
                servers: data.bedrockCore || []
            },
            {
                name: 'proxyCore',
                displayName: '代理服务端核心',
                servers: data.proxyCore || []
            }
        ];
        return categories.filter(cat => cat.servers.length > 0);
    }
}
export async function downloadMinecraftServer(server, version, targetDirectory, options) {
    const downloader = new MinecraftServerDownloader();
    await downloader.downloadServer({
        server,
        version,
        targetDirectory,
        ...options
    });
}
export async function getServerCategories() {
    const downloader = new MinecraftServerDownloader();
    return await downloader.getServerCategories();
}
export async function getAvailableVersions(server) {
    const downloader = new MinecraftServerDownloader();
    return await downloader.getAvailableVersions(server);
}
export async function getDownloadInfo(server, version) {
    const downloader = new MinecraftServerDownloader();
    return await downloader.getDownloadInfo(server, version);
}
export async function validateJavaEnvironment() {
    return await FileManager.validateJavaEnvironment();
}
export default MinecraftServerDownloader;
