"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.register = void 0;
const protocol_1 = require("../../protocol");
const language_core_1 = require("@volar/language-core");
function register(connection, workspaces, env) {
    const scriptVersions = new Map();
    const scriptVersionSnapshots = new WeakSet();
    connection.onRequest(protocol_1.GetMatchTsConfigRequest.type, async (params) => {
        const project = (await workspaces.getProject(params.uri));
        if (project?.tsconfig) {
            return { uri: env.fileNameToUri(project.tsconfig) };
        }
    });
    connection.onRequest(protocol_1.GetProjectsRequest.type, async (params) => {
        const matchProject = params ? (await workspaces.getProject(params.uri)) : undefined;
        const result = [];
        for (const [workspaceUri, _workspace] of workspaces.workspaces) {
            const workspace = (await _workspace);
            result.push({
                isInferredProject: true,
                rootUri: workspaceUri,
                tsconfig: undefined,
                created: !!workspace.getInferredProjectDontCreate(),
                isSelected: !!matchProject && await workspace.getInferredProjectDontCreate() === matchProject.project,
            });
            for (const _project of workspace.projects.values()) {
                const project = await _project;
                result.push({
                    isInferredProject: false,
                    rootUri: workspaceUri,
                    tsconfig: project.tsConfig,
                    created: !!project.getLanguageServiceDontCreate(),
                    isSelected: !!matchProject && project === matchProject.project,
                });
            }
        }
        return result;
    });
    connection.onRequest(protocol_1.GetProjectFilesRequest.type, async (params) => {
        const workspace = await workspaces.workspaces.get(params.rootUri);
        if (!workspace)
            return [];
        if (!params.tsconfig) {
            const project = await workspace.getInferredProject();
            if (!project)
                return [];
            return project.languageHost.getScriptFileNames();
        }
        for (const _project of workspace.projects.values()) {
            const project = await _project;
            if (project.tsConfig === params.tsconfig) {
                return project.languageHost.getScriptFileNames();
            }
        }
        return [];
    });
    connection.onRequest(protocol_1.GetVirtualFilesRequest.type, async (document) => {
        const project = await workspaces.getProject(document.uri);
        if (project) {
            const file = project.project?.getLanguageService()?.context.virtualFiles.getSource(env.uriToFileName(document.uri))?.root;
            return file ? prune(file) : undefined;
            function prune(file) {
                let version = scriptVersions.get(file.fileName) ?? 0;
                if (!scriptVersionSnapshots.has(file.snapshot)) {
                    version++;
                    scriptVersions.set(file.fileName, version);
                    scriptVersionSnapshots.add(file.snapshot);
                }
                return {
                    fileName: file.fileName,
                    kind: file.kind,
                    capabilities: file.capabilities,
                    embeddedFiles: file.embeddedFiles.map(prune),
                    version,
                };
            }
        }
    });
    connection.onRequest(protocol_1.GetVirtualFileRequest.type, async (params) => {
        const project = await workspaces.getProject(params.sourceFileUri);
        const service = project?.project?.getLanguageService();
        if (service) {
            let content = '';
            let codegenStacks = [];
            const mappings = {};
            for (const [file, map] of service.context.documents.getMapsByVirtualFileName(params.virtualFileName)) {
                content = map.virtualFileDocument.getText();
                codegenStacks = file.codegenStacks;
                mappings[map.sourceFileDocument.uri] = map.map.mappings;
            }
            return {
                content,
                mappings,
                codegenStacks,
            };
        }
    });
    connection.onNotification(protocol_1.ReloadProjectNotification.type, () => {
        workspaces.reloadProject();
    });
    connection.onNotification(protocol_1.WriteVirtualFilesNotification.type, async (params) => {
        const fs = await Promise.resolve().then(() => require('fs'));
        const project = await workspaces.getProject(params.uri);
        if (project) {
            const ls = (await project.project)?.getLanguageServiceDontCreate();
            if (ls) {
                const rootPath = ls.context.env.uriToFileName(ls.context.env.rootUri.toString());
                for (const { root } of ls.context.virtualFiles.allSources()) {
                    (0, language_core_1.forEachEmbeddedFile)(root, virtualFile => {
                        if (virtualFile.kind === language_core_1.FileKind.TypeScriptHostFile) {
                            if (virtualFile.fileName.startsWith(rootPath)) {
                                const snapshot = virtualFile.snapshot;
                                fs.writeFile(virtualFile.fileName, snapshot.getText(0, snapshot.getLength()), () => { });
                            }
                        }
                    });
                }
                // global virtual files
                for (const fileName of ls.context.host.getScriptFileNames()) {
                    if (!fs.existsSync(fileName)) {
                        const snapshot = ls.context.host.getScriptSnapshot(fileName);
                        if (snapshot) {
                            fs.writeFile(fileName, snapshot.getText(0, snapshot.getLength()), () => { });
                        }
                    }
                }
            }
        }
    });
}
exports.register = register;
//# sourceMappingURL=customFeatures.js.map