/*
 * Copyright (C) 2017, 2018 TypeFox and others.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 */
import { platform } from 'node:os';
import * as path from 'node:path';
import * as fs from 'node:fs';
import { fileURLToPath } from 'node:url';
import deepmerge from 'deepmerge';
import * as lsp from 'vscode-languageserver';
import { TextDocument } from 'vscode-languageserver-textdocument';
import { normalizePath, pathToUri } from './protocol-translation.js';
import { LspServer } from './lsp-server.js';
import { ConsoleLogger, LogLevel } from './utils/logger.js';
import { TypeScriptVersionProvider } from './tsServer/versionProvider.js';
import { TsServerLogLevel } from './utils/configuration.js';
const CONSOLE_LOG_LEVEL = LogLevel.fromString(process.env.CONSOLE_LOG_LEVEL);
export const PACKAGE_ROOT = fileURLToPath(new URL('..', import.meta.url));
const DEFAULT_TEST_CLIENT_CAPABILITIES = {
    textDocument: {
        completion: {
            completionItem: {
                insertReplaceSupport: true,
                snippetSupport: true,
                labelDetailsSupport: true,
            },
        },
        documentSymbol: {
            hierarchicalDocumentSymbolSupport: true,
        },
        publishDiagnostics: {
            tagSupport: {
                valueSet: [
                    lsp.DiagnosticTag.Unnecessary,
                    lsp.DiagnosticTag.Deprecated,
                ],
            },
        },
        moniker: {},
    },
};
const DEFAULT_TEST_CLIENT_INITIALIZATION_OPTIONS = {
    plugins: [],
    preferences: {
        allowIncompleteCompletions: true,
        allowRenameOfImportPath: true,
        allowTextChangesInNewFiles: true,
        displayPartsForJSDoc: true,
        generateReturnInDocTemplate: true,
        includeAutomaticOptionalChainCompletions: true,
        includeCompletionsForImportStatements: true,
        includeCompletionsForModuleExports: true,
        includeCompletionsWithClassMemberSnippets: true,
        includeCompletionsWithInsertText: true,
        includeCompletionsWithSnippetText: true,
        jsxAttributeCompletionStyle: 'auto',
        providePrefixAndSuffixTextForRename: true,
    },
};
const DEFAULT_WORKSPACE_SETTINGS = {};
export function uri(...components) {
    const resolved = filePath(...components);
    return pathToUri(resolved, undefined);
}
export function filePath(...components) {
    return normalizePath(path.resolve(PACKAGE_ROOT, 'test-data', ...components));
}
export function readContents(path) {
    return fs.readFileSync(path, 'utf-8').toString();
}
export function positionAt(document, idx) {
    const doc = TextDocument.create(document.uri, document.languageId, document.version, document.text);
    const pos = doc.positionAt(idx);
    return {
        line: pos.line,
        character: pos.character,
    };
}
export function position(document, match) {
    return positionAt(document, document.text.indexOf(match));
}
export function positionAfter(document, match) {
    return positionAt(document, document.text.indexOf(match) + match.length);
}
export function lastPosition(document, match) {
    return positionAt(document, document.text.lastIndexOf(match));
}
export function toPlatformEOL(text) {
    if (platform() === 'win32') {
        return text.replace(/(?!\r)\n/g, '\r\n');
    }
    return text;
}
export class TestLspClient {
    constructor(options, logger) {
        this.options = options;
        this.logger = logger;
        this.workspaceEditsListener = null;
    }
    async createProgressReporter(_token, _workDoneProgress) {
        const reporter = new class {
            begin(_title, _percentage, _message, _cancellable) { }
            report(_message) { }
            done() { }
        };
        return reporter;
    }
    async withProgress(_options, task) {
        const progress = await this.createProgressReporter();
        return await task(progress);
    }
    publishDiagnostics(args) {
        return this.options.publishDiagnostics(args);
    }
    showErrorMessage(message) {
        this.logger.error(`[showErrorMessage] ${message}`);
    }
    logMessage(args) {
        this.logger.log('logMessage', JSON.stringify(args));
    }
    addApplyWorkspaceEditListener(listener) {
        this.workspaceEditsListener = listener;
    }
    async applyWorkspaceEdit(args) {
        if (this.workspaceEditsListener) {
            this.workspaceEditsListener(args);
        }
        return { applied: true };
    }
    rename() {
        throw new Error('unsupported');
    }
}
export class TestLspServer extends LspServer {
    constructor() {
        super(...arguments);
        this.workspaceEdits = [];
    }
    updateWorkspaceSettings(settings) {
        const configuration = {
            settings: deepmerge(DEFAULT_WORKSPACE_SETTINGS, settings),
        };
        this.didChangeConfiguration(configuration);
    }
}
export async function createServer(options) {
    const logger = new ConsoleLogger(CONSOLE_LOG_LEVEL);
    const lspClient = new TestLspClient(options, logger);
    const serverOptions = {
        logger,
        lspClient,
        tsserverLogVerbosity: TsServerLogLevel.Off,
    };
    const typescriptVersionProvider = new TypeScriptVersionProvider(serverOptions.tsserverPath, logger);
    const bundled = typescriptVersionProvider.bundledVersion();
    const server = new TestLspServer({
        ...serverOptions,
        tsserverPath: bundled.tsServerPath,
    });
    lspClient.addApplyWorkspaceEditListener(args => {
        server.workspaceEdits.push(args);
    });
    await server.initialize({
        rootPath: undefined,
        rootUri: options.rootUri,
        processId: 42,
        capabilities: deepmerge(DEFAULT_TEST_CLIENT_CAPABILITIES, options.clientCapabilitiesOverride || {}),
        initializationOptions: DEFAULT_TEST_CLIENT_INITIALIZATION_OPTIONS,
        workspaceFolders: null,
    });
    server.updateWorkspaceSettings({});
    return server;
}
//# sourceMappingURL=test-utils.js.map