"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createServerPlugin = void 0;
const vue = require("@volar/vue-language-service");
const vue2 = require("@volar/vue-language-core");
const nameCasing = require("@volar/vue-language-service");
const protocol_1 = require("./protocol");
const componentMeta = require("vue-component-meta");
function createServerPlugin(connection) {
    const plugin = (initOptions, modules) => {
        if (!modules.typescript) {
            console.warn('No typescript found, vue-language-server will not work.');
            return {};
        }
        const ts = modules.typescript;
        const vueFileExtensions = ['vue'];
        const hostToVueOptions = new WeakMap();
        if (initOptions.additionalExtensions) {
            for (const additionalExtension of initOptions.additionalExtensions) {
                vueFileExtensions.push(additionalExtension);
            }
        }
        return {
            extraFileExtensions: vueFileExtensions.map(ext => ({ extension: ext, isMixedContent: true, scriptKind: ts.ScriptKind.Deferred })),
            watchFileExtensions: ['js', 'cjs', 'mjs', 'ts', 'cts', 'mts', 'jsx', 'tsx', 'json', ...vueFileExtensions],
            resolveConfig(config, ctx) {
                const vueOptions = getVueCompilerOptions();
                const vueLanguageServiceSettings = getVueLanguageServiceSettings();
                if (ctx) {
                    hostToVueOptions.set(ctx.host, vueOptions);
                }
                return vue.resolveConfig(config, ts, ctx?.host.getCompilationSettings() ?? {}, vueOptions, vueLanguageServiceSettings);
                function getVueCompilerOptions() {
                    const ts = modules.typescript;
                    if (!ts) {
                        return {};
                    }
                    let vueOptions = {};
                    if (typeof ctx?.project.tsConfig === 'string') {
                        vueOptions = vue2.createParsedCommandLine(ts, ctx.sys, ctx.project.tsConfig, []).vueOptions;
                    }
                    vueOptions.extensions = [
                        ...vueOptions.extensions ?? ['.vue'],
                        ...vueFileExtensions.map(ext => '.' + ext),
                    ];
                    vueOptions.extensions = [...new Set(vueOptions.extensions)];
                    return vueOptions;
                }
                function getVueLanguageServiceSettings() {
                    const settings = {};
                    if (initOptions.json && ctx) {
                        settings.json = { schemas: [] };
                        for (const blockType in initOptions.json.customBlockSchemaUrls) {
                            const url = initOptions.json.customBlockSchemaUrls[blockType];
                            settings.json.schemas?.push({
                                fileMatch: [`*.customBlock_${blockType}_*.json*`],
                                uri: new URL(url, ctx.project.rootUri.toString() + '/').toString(),
                            });
                        }
                    }
                    return settings;
                }
            },
            onInitialized(getService, env) {
                connection.onRequest(protocol_1.ParseSFCRequest.type, params => {
                    return vue2.parse(params);
                });
                connection.onRequest(protocol_1.DetectNameCasingRequest.type, async (params) => {
                    const languageService = await getService(params.textDocument.uri);
                    if (languageService?.context.typescript) {
                        return nameCasing.detect(languageService.context, languageService.context.typescript, params.textDocument.uri);
                    }
                });
                connection.onRequest(protocol_1.GetConvertTagCasingEditsRequest.type, async (params) => {
                    const languageService = await getService(params.textDocument.uri);
                    if (languageService?.context.typescript) {
                        return nameCasing.convertTagName(languageService.context, languageService.context.typescript, params.textDocument.uri, params.casing);
                    }
                });
                connection.onRequest(protocol_1.GetConvertAttrCasingEditsRequest.type, async (params) => {
                    const languageService = await getService(params.textDocument.uri);
                    if (languageService?.context.typescript) {
                        const vueOptions = hostToVueOptions.get(languageService.context.host);
                        if (vueOptions) {
                            return nameCasing.convertAttrName(languageService.context, languageService.context.typescript, params.textDocument.uri, params.casing);
                        }
                    }
                });
                const checkers = new WeakMap();
                connection.onRequest(protocol_1.GetComponentMeta.type, async (params) => {
                    const languageService = await getService(params.uri);
                    if (!languageService?.context.typescript)
                        return;
                    let checker = checkers.get(languageService.context.host);
                    if (!checker) {
                        checker = componentMeta.baseCreate({
                            ...languageService.context.host,
                            getVueCompilationSettings: () => hostToVueOptions.get(languageService.context.host) ?? {},
                        }, {}, languageService.context.host.getCurrentDirectory() + '/tsconfig.json.global.vue', languageService.context.typescript.module);
                        checkers.set(languageService.context.host, checker);
                    }
                    return checker.getComponentMeta(env.uriToFileName(params.uri));
                });
            },
        };
    };
    return plugin;
}
exports.createServerPlugin = createServerPlugin;
//# sourceMappingURL=languageServerPlugin.js.map