"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.register = void 0;
const language_core_1 = require("@volar/language-core");
const protocol_1 = require("../../protocol");
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.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()), () => { });
                        }
                    }
                }
            }
        }
    });
    connection.onRequest(protocol_1.LoadedTSFilesMetaRequest.type, async () => {
        const sourceFilesData = new Map();
        for (const workspace of workspaces.workspaces.values()) {
            for (const _project of (await workspace).projects.values()) {
                const project = await _project;
                const service = project.getLanguageServiceDontCreate();
                const languageService = service?.context.inject('typescript/languageService');
                const program = languageService?.getProgram();
                if (program) {
                    const projectName = typeof project.tsConfig === 'string' ? project.tsConfig : (project.languageHost.workspacePath + '(inferred)');
                    const sourceFiles = program?.getSourceFiles() ?? [];
                    for (const sourceFile of sourceFiles) {
                        if (!sourceFilesData.has(sourceFile)) {
                            let nodes = 0;
                            sourceFile.forEachChild(function walk(node) {
                                nodes++;
                                node.forEachChild(walk);
                            });
                            sourceFilesData.set(sourceFile, {
                                projectNames: [],
                                size: nodes * 128,
                            });
                        }
                        sourceFilesData.get(sourceFile).projectNames.push(projectName);
                    }
                    ;
                }
            }
        }
        const result = {
            inputs: {},
            outputs: {},
        };
        for (const [sourceFile, fileData] of sourceFilesData) {
            let key = fileData.projectNames.sort().join(', ');
            if (fileData.projectNames.length >= 2) {
                key = `Shared in ${fileData.projectNames.length} projects (${key})`;
            }
            result.outputs[key] ??= {
                imports: [],
                exports: [],
                entryPoint: '',
                inputs: {},
                bytes: 0,
            };
            result.outputs[key].inputs[sourceFile.fileName] = { bytesInOutput: fileData.size };
        }
        return result;
    });
}
exports.register = register;
//# sourceMappingURL=customFeatures.js.map