import deepmerge from 'deepmerge';
import path from 'node:path';
import API from './utils/api.js';
const DEFAULT_TSSERVER_PREFERENCES = {
    allowIncompleteCompletions: true,
    allowRenameOfImportPath: true,
    allowTextChangesInNewFiles: true,
    autoImportFileExcludePatterns: [],
    disableSuggestions: false,
    displayPartsForJSDoc: true,
    generateReturnInDocTemplate: true,
    importModuleSpecifierEnding: 'auto',
    importModuleSpecifierPreference: 'shortest',
    includeAutomaticOptionalChainCompletions: true,
    includeCompletionsForImportStatements: true,
    includeCompletionsForModuleExports: true,
    includeCompletionsWithClassMemberSnippets: true,
    includeCompletionsWithInsertText: true,
    includeCompletionsWithObjectLiteralMethodSnippets: true,
    includeCompletionsWithSnippetText: true,
    includeInlayEnumMemberValueHints: false,
    includeInlayFunctionLikeReturnTypeHints: false,
    includeInlayFunctionParameterTypeHints: false,
    includeInlayParameterNameHints: 'none',
    includeInlayParameterNameHintsWhenArgumentMatchesName: false,
    includeInlayPropertyDeclarationTypeHints: false,
    includeInlayVariableTypeHints: false,
    includeInlayVariableTypeHintsWhenTypeMatchesName: false,
    includePackageJsonAutoImports: 'auto',
    jsxAttributeCompletionStyle: 'auto',
    lazyConfiguredProjectsFromExternalProject: false,
    providePrefixAndSuffixTextForRename: true,
    provideRefactorNotApplicableReason: true,
    quotePreference: 'auto',
    useLabelDetailsInCompletionEntries: true,
};
const DEFAULT_IMPLICIT_PROJECT_CONFIGURATION = {
    checkJs: false,
    experimentalDecorators: false,
    module: "ESNext" /* tsp.ModuleKind.ESNext */,
    strictFunctionTypes: true,
    strictNullChecks: true,
    target: "ES2020" /* tsp.ScriptTarget.ES2020 */,
};
const DEFAULT_WORKSPACE_CONFIGURATION = {
    implicitProjectConfiguration: DEFAULT_IMPLICIT_PROJECT_CONFIGURATION,
};
export class ConfigurationManager {
    constructor(documents) {
        this.documents = documents;
        this.tsPreferences = deepmerge({}, DEFAULT_TSSERVER_PREFERENCES);
        this.workspaceConfiguration = deepmerge({}, DEFAULT_WORKSPACE_CONFIGURATION);
        this.tspClient = null;
    }
    mergeTsPreferences(preferences) {
        this.tsPreferences = deepmerge(this.tsPreferences, preferences);
    }
    setWorkspaceConfiguration(configuration) {
        this.workspaceConfiguration = deepmerge(DEFAULT_WORKSPACE_CONFIGURATION, configuration);
    }
    setAndConfigureTspClient(workspaceFolder, client, hostInfo) {
        this.tspClient = client;
        const formatOptions = {
            // We can use \n here since the editor should normalize later on to its line endings.
            newLineCharacter: '\n',
        };
        const args = {
            ...hostInfo ? { hostInfo } : {},
            formatOptions,
            preferences: {
                ...this.tsPreferences,
                autoImportFileExcludePatterns: this.getAutoImportFileExcludePatternsPreference(workspaceFolder),
            },
        };
        client.executeWithoutWaitingForResponse("configure" /* CommandTypes.Configure */, args);
    }
    async configureGloballyFromDocument(filename, formattingOptions) {
        const args = {
            formatOptions: this.getFormattingOptions(filename, formattingOptions),
            preferences: this.getPreferences(filename),
        };
        await this.tspClient?.request("configure" /* CommandTypes.Configure */, args);
    }
    getPreferences(filename) {
        if (this.tspClient?.apiVersion.lt(API.v290)) {
            return {};
        }
        const workspacePreferences = this.getWorkspacePreferencesForFile(filename);
        const preferences = Object.assign({}, this.tsPreferences, workspacePreferences?.inlayHints || {});
        return {
            ...preferences,
            quotePreference: this.getQuoteStylePreference(preferences),
        };
    }
    getFormattingOptions(filename, formattingOptions) {
        const workspacePreferences = this.getWorkspacePreferencesForFile(filename);
        const opts = {
            ...workspacePreferences?.format,
            ...formattingOptions,
        };
        if (opts.convertTabsToSpaces === undefined) {
            opts.convertTabsToSpaces = formattingOptions?.insertSpaces;
        }
        if (opts.indentSize === undefined) {
            opts.indentSize = formattingOptions?.tabSize;
        }
        return opts;
    }
    getQuoteStylePreference(preferences) {
        switch (preferences.quotePreference) {
            case 'single': return 'single';
            case 'double': return 'double';
            default: return this.tspClient?.apiVersion.gte(API.v333) ? 'auto' : undefined;
        }
    }
    getWorkspacePreferencesForFile(filename) {
        const document = this.documents.get(filename);
        const languageId = document?.languageId.startsWith('typescript') ? 'typescript' : 'javascript';
        return this.workspaceConfiguration[languageId] || {};
    }
    getAutoImportFileExcludePatternsPreference(workspaceFolder) {
        if (!workspaceFolder || this.tsPreferences.autoImportFileExcludePatterns.length === 0) {
            return;
        }
        return this.tsPreferences.autoImportFileExcludePatterns.map(p => {
            // Normalization rules: https://github.com/microsoft/TypeScript/pull/49578
            const slashNormalized = p.replace(/\\/g, '/');
            const isRelative = /^\.\.?($|\/)/.test(slashNormalized);
            return path.posix.isAbsolute(p) ? p :
                p.startsWith('*') ? '/' + slashNormalized :
                    isRelative ? path.posix.join(workspaceFolder, p) :
                        '/**/' + slashNormalized;
        });
    }
}
//# sourceMappingURL=configuration-manager.js.map