"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 fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const Index_1 = require("../Utils/Index");
class MinecraftBundle {
    options;
    constructor(options) {
        this.options = options;
    }
    async checkBundle(bundle) {
        const toDownload = [];
        for (const file of bundle) {
            if (!file.path)
                continue;
            file.path = path_1.default.resolve(this.options.path, file.path).replace(/\\/g, '/');
            file.folder = path_1.default.dirname(file.path);
            if (file.type === 'CFILE') {
                await this.#writeCFile(file);
                continue;
            }
            const exists = fs_1.default.existsSync(file.path);
            const ignored = this.#shouldIgnore(file.path);
            if (!exists || (file.sha1 && !ignored && (await (0, Index_1.getFileHash)(file.path)) !== file.sha1)) {
                toDownload.push(file);
            }
        }
        return toDownload;
    }
    async getTotalSize(bundle) {
        return bundle.reduce((acc, f) => acc + (f.size ?? 0), 0);
    }
    async checkFiles(bundle) {
        const instancePath = this.options.instance ? `/instances/${this.options.instance}` : '';
        const basePath = path_1.default.join(this.options.path, instancePath);
        const allFiles = this.getFiles(basePath);
        const allowed = new Set([
            ...this.getFiles(path_1.default.join(this.options.path, 'loader')),
            ...this.getFiles(path_1.default.join(this.options.path, 'runtime')),
            ...bundle.map(f => f.path),
            ...this.options.ignored.map(f => path_1.default.join(basePath, f))
        ]);
        for (const filePath of allFiles) {
            if (!allowed.has(filePath)) {
                try {
                    const stats = fs_1.default.statSync(filePath);
                    if (stats.isDirectory()) {
                        fs_1.default.rmSync(filePath, { recursive: true, force: true });
                    }
                    else {
                        fs_1.default.unlinkSync(filePath);
                        this.#cleanupEmptyDirs(filePath, basePath);
                    }
                }
                catch { /* ignorar errores */ }
            }
        }
    }
    getFiles(dirPath, collected = []) {
        if (!fs_1.default.existsSync(dirPath))
            return collected;
        for (const entry of fs_1.default.readdirSync(dirPath)) {
            const full = path_1.default.join(dirPath, entry);
            const stats = fs_1.default.statSync(full);
            stats.isDirectory() ? this.getFiles(full, collected) : collected.push(full);
        }
        return collected;
    }
    async #writeCFile(file) {
        const folder = file.folder ?? path_1.default.dirname(file.path ?? '');
        const filePath = file.path ?? '';
        if (!filePath)
            throw new Error('BundleItem.path no puede ser undefined para CFILE');
        if (!fs_1.default.existsSync(folder))
            fs_1.default.mkdirSync(folder, { recursive: true, mode: 0o777 });
        fs_1.default.writeFileSync(filePath, file.content ?? '', { encoding: 'utf8', mode: 0o755 });
    }
    #shouldIgnore(filePath) {
        const prefix = this.options.instance
            ? path_1.default.join(this.options.path, 'instances', this.options.instance)
            : this.options.path;
        const rel = path_1.default.relative(prefix, filePath).replace(/\\/g, '/');
        return this.options.ignored.includes(rel);
    }
    #cleanupEmptyDirs(filePath, basePath) {
        let current = path_1.default.dirname(filePath);
        while (current.startsWith(basePath) && current !== basePath) {
            if (fs_1.default.existsSync(current) && fs_1.default.readdirSync(current).length === 0) {
                fs_1.default.rmdirSync(current);
            }
            current = path_1.default.dirname(current);
        }
    }
}
exports.default = MinecraftBundle;
