"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.decorateLanguageServiceHost = void 0;
const language_core_1 = require("@volar/language-core");
function decorateLanguageServiceHost(virtualFiles, languageServiceHost, ts, exts) {
    let extraProjectVersion = 0;
    const scripts = new Map();
    const resolveModuleNameLiterals = languageServiceHost.resolveModuleNameLiterals?.bind(languageServiceHost);
    const resolveModuleNames = languageServiceHost.resolveModuleNames?.bind(languageServiceHost);
    const getProjectVersion = languageServiceHost.getProjectVersion?.bind(languageServiceHost);
    const getScriptFileNames = languageServiceHost.getScriptFileNames.bind(languageServiceHost);
    const getScriptSnapshot = languageServiceHost.getScriptSnapshot.bind(languageServiceHost);
    if (resolveModuleNameLiterals) {
        languageServiceHost.resolveModuleNameLiterals = (moduleNames, containingFile, redirectedReference, options, ...rest) => {
            const resolvedModules = resolveModuleNameLiterals(moduleNames, containingFile, redirectedReference, options, ...rest);
            return moduleNames.map((name, i) => {
                if (exts.some(ext => name.text.endsWith(ext))) {
                    return resolveModuleName(name.text, containingFile, options, redirectedReference);
                }
                return resolvedModules[i];
            });
        };
    }
    else if (resolveModuleNames) {
        languageServiceHost.resolveModuleNames = (moduleNames, containingFile, reusedNames, redirectedReference, options, containingSourceFile) => {
            const resolvedModules = resolveModuleNames(moduleNames, containingFile, reusedNames, redirectedReference, options, containingSourceFile);
            return moduleNames.map((name, i) => {
                if (exts.some(ext => name.endsWith(ext))) {
                    return resolveModuleName(name, containingFile, options, redirectedReference).resolvedModule;
                }
                return resolvedModules[i];
            });
        };
    }
    if (getProjectVersion) {
        languageServiceHost.getProjectVersion = () => {
            return getProjectVersion() + ':' + extraProjectVersion;
        };
    }
    languageServiceHost.getScriptFileNames = () => {
        if (languageServiceHost.getCompilationSettings().composite) {
            return [
                ...getScriptFileNames(),
                ...virtualFiles.allSources().map(source => source.fileName),
            ];
        }
        else {
            return getScriptFileNames();
        }
    };
    languageServiceHost.getScriptSnapshot = (fileName) => {
        if (scripts.has(fileName)) {
            updateScript(fileName);
        }
        return scripts.get(fileName)?.snapshot ?? getScriptSnapshot(fileName);
    };
    function resolveModuleName(name, containingFile, options, redirectedReference) {
        const resolved = ts.resolveModuleName(name, containingFile, options, {
            readFile(fileName) {
                return languageServiceHost.readFile(fileName);
            },
            fileExists(fileName) {
                if (exts.some(ext => fileName.endsWith(ext + '.d.ts'))) {
                    return languageServiceHost.fileExists(fileName.slice(0, -'.d.ts'.length));
                }
                return languageServiceHost.fileExists(fileName);
            },
        }, undefined, redirectedReference);
        if (resolved.resolvedModule) {
            resolved.resolvedModule.resolvedFileName = resolved.resolvedModule.resolvedFileName.slice(0, -'.d.ts'.length);
            const script = updateScript(resolved.resolvedModule.resolvedFileName);
            if (script) {
                resolved.resolvedModule.extension = script.extension;
            }
        }
        return resolved;
    }
    function updateScript(fileName) {
        const version = languageServiceHost.getScriptVersion(fileName);
        if (version !== scripts.get(fileName)?.version) {
            const text = languageServiceHost.readFile(fileName);
            let snapshot;
            let extension = '.ts';
            if (text !== undefined) {
                extraProjectVersion++;
                const virtualFile = virtualFiles.updateSource(fileName, ts.ScriptSnapshot.fromString(text), undefined);
                if (virtualFile) {
                    let patchedText = text.split('\n').map(line => ' '.repeat(line.length)).join('\n');
                    (0, language_core_1.forEachEmbeddedFile)(virtualFile, file => {
                        const ext = file.fileName.replace(fileName, '');
                        if (file.kind === language_core_1.FileKind.TypeScriptHostFile && (ext === '.d.ts' || ext.match(/^\.(js|ts)x?$/))) {
                            extension = ext;
                            patchedText += file.snapshot.getText(0, file.snapshot.getLength());
                        }
                    });
                    snapshot = ts.ScriptSnapshot.fromString(patchedText);
                }
            }
            else if (virtualFiles.hasSource(fileName)) {
                extraProjectVersion++;
                virtualFiles.deleteSource(fileName);
            }
            scripts.set(fileName, {
                version,
                snapshot,
                extension,
            });
        }
        return scripts.get(fileName);
    }
}
exports.decorateLanguageServiceHost = decorateLanguageServiceHost;
//# sourceMappingURL=serverPlugin.js.map