"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FormattingService = void 0;
const node_1 = require("vscode-languageserver/node");
const formatter_1 = require("@herb-tools/formatter");
const config_1 = require("./config");
const glob_1 = require("glob");
class FormattingService {
    constructor(connection, documents, project, settings) {
        this.connection = connection;
        this.documents = documents;
        this.project = project;
        this.settings = settings;
    }
    async initialize() {
        try {
            this.config = await config_1.Config.fromPathOrNew(this.project.projectPath);
            this.connection.console.log("Herb formatter initialized successfully");
        }
        catch (error) {
            this.connection.console.error(`Failed to initialize Herb formatter: ${error}`);
        }
    }
    async refreshConfig() {
        this.config = await config_1.Config.fromPathOrNew(this.project.projectPath);
    }
    async shouldFormatFile(filePath) {
        var _a;
        if (!((_a = this.config) === null || _a === void 0 ? void 0 : _a.options.formatter)) {
            return true;
        }
        const formatter = this.config.options.formatter;
        // Check if formatting is disabled in project config
        if (formatter.enabled === false) {
            return false;
        }
        // Check exclude patterns first
        if (formatter.exclude) {
            for (const pattern of formatter.exclude) {
                try {
                    const matches = await new Promise((resolve, reject) => {
                        (0, glob_1.glob)(pattern, { cwd: this.project.projectPath }).then(resolve).catch(reject);
                    });
                    if (Array.isArray(matches) && matches.some((match) => filePath.includes(match) || filePath.endsWith(match))) {
                        return false;
                    }
                }
                catch (error) {
                    continue;
                }
            }
        }
        if (formatter.include && formatter.include.length > 0) {
            for (const pattern of formatter.include) {
                try {
                    const matches = await new Promise((resolve, reject) => {
                        (0, glob_1.glob)(pattern, { cwd: this.project.projectPath }).then(resolve).catch(reject);
                    });
                    if (Array.isArray(matches) && matches.some((match) => filePath.includes(match) || filePath.endsWith(match))) {
                        return true;
                    }
                }
                catch (error) {
                    continue;
                }
            }
            return false;
        }
        return true;
    }
    async getFormatterOptions(uri) {
        var _a, _b, _c, _d, _e, _f, _g;
        // Get VS Code settings
        const settings = await this.settings.getDocumentSettings(uri);
        // Get project config options
        const projectFormatter = ((_a = this.config) === null || _a === void 0 ? void 0 : _a.options.formatter) || {};
        // Merge options with precedence: project config > VS Code settings > defaults
        return {
            indentWidth: (_d = (_b = projectFormatter.indentWidth) !== null && _b !== void 0 ? _b : (_c = settings.formatter) === null || _c === void 0 ? void 0 : _c.indentWidth) !== null && _d !== void 0 ? _d : formatter_1.defaultFormatOptions.indentWidth,
            maxLineLength: (_g = (_e = projectFormatter.maxLineLength) !== null && _e !== void 0 ? _e : (_f = settings.formatter) === null || _f === void 0 ? void 0 : _f.maxLineLength) !== null && _g !== void 0 ? _g : formatter_1.defaultFormatOptions.maxLineLength
        };
    }
    async performFormatting(params) {
        const document = this.documents.get(params.textDocument.uri);
        if (!document) {
            return [];
        }
        try {
            const options = await this.getFormatterOptions(params.textDocument.uri);
            const formatter = new formatter_1.Formatter(this.project.herbBackend, options);
            const text = document.getText();
            const newText = formatter.format(text);
            if (newText === text) {
                return [];
            }
            const range = {
                start: node_1.Position.create(0, 0),
                end: node_1.Position.create(document.lineCount, 0)
            };
            return [{ range, newText }];
        }
        catch (error) {
            this.connection.console.error(`Formatting failed: ${error}`);
            return [];
        }
    }
    async formatDocument(params) {
        var _a;
        // Check VS Code settings first
        const settings = await this.settings.getDocumentSettings(params.textDocument.uri);
        if (((_a = settings.formatter) === null || _a === void 0 ? void 0 : _a.enabled) === false) {
            return [];
        }
        // Check project config and file patterns
        const filePath = params.textDocument.uri.replace(/^file:\/\//, '');
        if (!(await this.shouldFormatFile(filePath))) {
            return [];
        }
        return this.performFormatting(params);
    }
    async formatDocumentIgnoreConfig(params) {
        return this.performFormatting(params);
    }
}
exports.FormattingService = FormattingService;
//# sourceMappingURL=formatting_service.js.map