"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createHybridModeProject = createHybridModeProject;
const simpleProject_1 = require("@volar/language-server/lib/project/simpleProject");
const language_core_1 = require("@vue/language-core");
const language_service_1 = require("@vue/language-service");
const utils_1 = require("@vue/typescript-plugin/lib/utils");
const vscode_uri_1 = require("vscode-uri");
function createHybridModeProject(create) {
    let simpleLs;
    let server;
    const tsconfigProjects = (0, language_service_1.createUriMap)();
    const project = {
        setup(_server) {
            server = _server;
            utils_1.onServerReady.push(() => {
                server.languageFeatures.requestRefresh(false);
            });
            server.fileWatcher.onDidChangeWatchedFiles(({ changes }) => {
                for (const change of changes) {
                    const changeUri = vscode_uri_1.URI.parse(change.uri);
                    if (tsconfigProjects.has(changeUri)) {
                        tsconfigProjects.get(changeUri)?.then(project => project.dispose());
                        tsconfigProjects.delete(changeUri);
                    }
                }
            });
            const end = Date.now() + 60000;
            const pipeWatcher = setInterval(() => {
                for (const server of utils_1.configuredServers) {
                    server.update();
                }
                for (const server of utils_1.inferredServers) {
                    server.update();
                }
                if (Date.now() > end) {
                    clearInterval(pipeWatcher);
                }
            }, 2500);
        },
        async getLanguageService(uri) {
            const fileName = asFileName(uri);
            const namedPipeServer = await (0, utils_1.getBestServer)(fileName);
            if (namedPipeServer?.projectInfo?.kind === 1) {
                const tsconfig = namedPipeServer.projectInfo.name;
                const tsconfigUri = vscode_uri_1.URI.file(tsconfig);
                if (!tsconfigProjects.has(tsconfigUri)) {
                    tsconfigProjects.set(tsconfigUri, createLs(server, tsconfig));
                }
                return await tsconfigProjects.get(tsconfigUri);
            }
            else {
                simpleLs ??= createLs(server, undefined);
                return await simpleLs;
            }
        },
        getExistingLanguageServices() {
            return Promise.all([
                ...tsconfigProjects.values(),
                simpleLs,
            ].filter(promise => !!promise));
        },
        reload() {
            for (const ls of [
                ...tsconfigProjects.values(),
                simpleLs,
            ]) {
                ls?.then(ls => ls.dispose());
            }
            tsconfigProjects.clear();
            simpleLs = undefined;
        },
    };
    return project;
    function asFileName(uri) {
        return uri.fsPath.replace(/\\/g, '/');
    }
    async function createLs(server, tsconfig) {
        const { languagePlugins, setup } = await create({
            configFileName: tsconfig,
            asFileName,
        });
        const language = (0, language_core_1.createLanguage)([
            { getLanguageId: uri => server.documents.get(uri)?.languageId },
            ...languagePlugins,
        ], (0, language_service_1.createUriMap)(), uri => {
            const document = server.documents.get(uri);
            if (document) {
                language.scripts.set(uri, document.getSnapshot(), document.languageId);
            }
            else {
                language.scripts.delete(uri);
            }
        });
        const project = {};
        setup?.({ language, project });
        return (0, language_service_1.createLanguageService)(language, server.languageServicePlugins, (0, simpleProject_1.createLanguageServiceEnvironment)(server, [...server.workspaceFolders.all]), project);
    }
}
//# sourceMappingURL=hybridModeProject.js.map