/*---------------------------------------------------------
 * Copyright (C) Microsoft Corporation. All rights reserved.
 * Modification copyright 2020 The Go Authors. All rights reserved.
 * Licensed under the MIT License. See LICENSE in the project root for license information.
 *--------------------------------------------------------*/

'use strict';

import cp = require('child_process');
import deepEqual = require('deep-equal');
import fs = require('fs');
import moment = require('moment');
import path = require('path');
import semver = require('semver');
import util = require('util');
import vscode = require('vscode');
import {
	CancellationToken,
	CloseAction,
	CompletionItemKind,
	ConfigurationParams,
	ConfigurationRequest,
	ErrorAction,
	HandleDiagnosticsSignature,
	InitializeError,
	Message,
	ProvideCodeLensesSignature,
	ProvideCompletionItemsSignature,
	ResponseError,
	RevealOutputChannelOn
} from 'vscode-languageclient';
import {
	LanguageClient
} from 'vscode-languageclient/node';
import { extensionId } from './const';
import { GoCodeActionProvider } from './goCodeAction';
import { GoDefinitionProvider } from './goDeclaration';
import { toolExecutionEnvironment } from './goEnv';
import { GoHoverProvider } from './goExtraInfo';
import { GoDocumentFormattingEditProvider } from './goFormat';
import { GoImplementationProvider } from './goImplementations';
import { installTools, promptForMissingTool, promptForUpdatingTool } from './goInstallTools';
import { parseLiveFile } from './goLiveErrors';
import { restartLanguageServer } from './goMain';
import { GO_MODE } from './goMode';
import { GoDocumentSymbolProvider } from './goOutline';
import { GoReferenceProvider } from './goReferences';
import { GoRenameProvider } from './goRename';
import { GoSignatureHelpProvider } from './goSignature';
import { outputChannel, updateLanguageServerIconGoStatusBar } from './goStatus';
import { GoCompletionItemProvider } from './goSuggest';
import { GoWorkspaceSymbolProvider } from './goSymbol';
import { getTool, Tool } from './goTools';
import { GoTypeDefinitionProvider } from './goTypeDefinition';
import { getFromGlobalState, updateGlobalState } from './stateUtils';
import {
	getBinPath,
	getCheckForToolsUpdatesConfig,
	getCurrentGoPath,
	getGoConfig,
	getGoplsConfig,
	getGoVersion,
	getWorkspaceFolderPath
} from './util';
import { getToolFromToolPath } from './utils/pathUtils';

import WebRequest = require('web-request');

export interface LanguageServerConfig {
	serverName: string;
	path: string;
	version: string;
	modtime: Date;
	enabled: boolean;
	flags: string[];
	env: any;
	checkForUpdates: string;
}

// Global variables used for management of the language client.
// They are global so that the server can be easily restarted with
// new configurations.
let languageClient: LanguageClient;
let languageServerDisposable: vscode.Disposable;
let latestConfig: LanguageServerConfig;
export let serverOutputChannel: vscode.OutputChannel;
export let languageServerIsRunning = false;
// TODO: combine languageServerIsRunning & languageServerStartInProgress
// as one languageServerStatus variable.
let languageServerStartInProgress = false;
let serverTraceChannel: vscode.OutputChannel;
let crashCount = 0;

// defaultLanguageProviders is the list of providers currently registered.
let defaultLanguageProviders: vscode.Disposable[] = [];

// restartCommand is the command used by the user to restart the language
// server.
let restartCommand: vscode.Disposable;

// lastUserAction is the time of the last user-triggered change.
// A user-triggered change is a didOpen, didChange, didSave, or didClose event.
let lastUserAction: Date = new Date();

// startLanguageServerWithFallback starts the language server, if enabled,
// or falls back to the default language providers.
export async function startLanguageServerWithFallback(ctx: vscode.ExtensionContext, activation: boolean) {
	for (const folder of vscode.workspace.workspaceFolders || []) {
		if (folder.uri.scheme === 'vsls') {
			outputChannel.appendLine(`Language service on the guest side is disabled. ` +
				`The server-side language service will provide the language features.`);
			return;
		}
	}

	if (!activation && languageServerStartInProgress) {
		console.log('language server restart is already in progress...');
		return;
	}

	const goConfig = getGoConfig();
	const cfg = buildLanguageServerConfig(goConfig);

	// If the language server is gopls, we enable a few additional features.
	// These include prompting for updates and surveys.
	if (cfg.serverName === 'gopls') {
		const tool = getTool(cfg.serverName);
		if (tool) {
			if (activation) {
				scheduleGoplsSuggestions(tool);
			}

			// If the language server is turned on because it is enabled by default,
			// make sure that the user is using a new enough version.
			if (cfg.enabled && languageServerUsingDefault(goConfig)) {
				const updated = await forceUpdateGopls(tool, cfg);
				if (updated) {
					// restartLanguageServer will be called when the new version of gopls was installed.
					return;
				}
			}
		}
	}

	languageServerStartInProgress = true;
	const progressMsg = languageServerIsRunning ? 'Restarting language service' : 'Starting language service';
	await vscode.window.withProgress({
		title: progressMsg,
		cancellable: !activation,
		location: vscode.ProgressLocation.Notification,
	}, async (progress, token) => {
		let disposable: vscode.Disposable;
		if (token) {
			disposable = token.onCancellationRequested(async () => {
				const choice = await vscode.window.showErrorMessage(
					'Language service restart request was interrupted and language service may be in a bad state. ' +
					'Please reload the window.',
					'Reload Window');
				if (choice === 'Reload Window') {
					await vscode.commands.executeCommand('workbench.action.reloadWindow');
				}
			});
		}

		const started = await startLanguageServer(ctx, cfg);

		if (!started && goConfig['useLanguageServer'] === true) {
			// We already created various notification - e.g. missing gopls, ...
			// So, just leave a log message here instead of issuing one more notification.
			outputChannel.appendLine(
				`Failed to start the language server (${cfg.serverName}). Falling back to default language providers...`);
		}
		// If the server has been disabled, or failed to start,
		// fall back to the default providers, while making sure not to
		// re-register any providers.
		if (!started && defaultLanguageProviders.length === 0) {
			registerDefaultProviders(ctx);
		}

		if (disposable) { disposable.dispose(); }
		languageServerIsRunning = started;
		updateLanguageServerIconGoStatusBar(started, cfg.serverName);
		languageServerStartInProgress = false;
	});
}

// scheduleGoplsSuggestions sets timeouts for the various gopls-specific
// suggestions. We check user's gopls versions once per day to prompt users to
// update to the latest version. We also check if we should prompt users to
// fill out the survey.
function scheduleGoplsSuggestions(tool: Tool) {
	const update = async () => {
		setTimeout(update, timeDay);

		const cfg = buildLanguageServerConfig(getGoConfig());
		if (!cfg.enabled) {
			return;
		}
		const versionToUpdate = await shouldUpdateLanguageServer(tool, cfg);
		if (versionToUpdate) {
			promptForUpdatingTool(tool.name, versionToUpdate);
		}
	};
	const survey = async () => {
		setTimeout(survey, timeDay);

		const cfg = buildLanguageServerConfig(getGoConfig());
		if (!cfg.enabled) {
			return;
		}
		maybePromptForGoplsSurvey();
	};

	setTimeout(update, 10 * timeMinute);
	setTimeout(survey, 30 * timeMinute);
}

async function startLanguageServer(ctx: vscode.ExtensionContext, config: LanguageServerConfig): Promise<boolean> {
	// If the client has already been started, make sure to clear existing
	// diagnostics and stop it.
	if (languageClient) {
		if (languageClient.diagnostics) {
			languageClient.diagnostics.clear();
		}
		await languageClient.stop();
		if (languageServerDisposable) {
			languageServerDisposable.dispose();
		}
	}

	// Check if we should recreate the language client. This may be necessary
	// if the user has changed settings in their config.
	if (!deepEqual(latestConfig, config)) {
		// Track the latest config used to start the language server,
		// and rebuild the language client.
		latestConfig = config;
		languageClient = await buildLanguageClient(buildLanguageClientOption(config));
		crashCount = 0;
	}

	// If the user has not enabled the language server, return early.
	if (!config.enabled) {
		return false;
	}

	// Set up the command to allow the user to manually restart the
	// language server.
	if (!restartCommand) {
		restartCommand = vscode.commands.registerCommand('go.languageserver.restart', async () => {
			await suggestGoplsIssueReport(
				`Looks like you're about to manually restart the language server.`,
				errorKind.manualRestart);
			restartLanguageServer();
		});
		ctx.subscriptions.push(restartCommand);
	}

	// Before starting the language server, make sure to deregister any
	// currently registered language providers.
	disposeDefaultProviders();

	languageServerDisposable = languageClient.start();
	ctx.subscriptions.push(languageServerDisposable);
	return true;
}

export interface BuildLanguageClientOption extends LanguageServerConfig {
	outputChannel?: vscode.OutputChannel;
	traceOutputChannel?: vscode.OutputChannel;
}

// buildLanguageClientOption returns the default, extra configuration
// used in building a new LanguageClient instance. Options specified
// in LanguageServerConfig
function buildLanguageClientOption(cfg: LanguageServerConfig): BuildLanguageClientOption {
	// Reuse the same output channel for each instance of the server.
	if (cfg.enabled) {
		if (!serverOutputChannel) {
			serverOutputChannel = vscode.window.createOutputChannel(cfg.serverName + ' (server)');
		}
		if (!serverTraceChannel) {
			serverTraceChannel = vscode.window.createOutputChannel(cfg.serverName);
		}
	}
	return Object.assign({
		outputChannel: serverOutputChannel,
		traceOutputChannel: serverTraceChannel
	}, cfg);
}

// buildLanguageClient returns a language client built using the given language server config.
// The returned language client need to be started before use.
export async function buildLanguageClient(cfg: BuildLanguageClientOption): Promise<LanguageClient> {
	const goplsWorkspaceConfig = await adjustGoplsWorkspaceConfiguration(cfg, getGoplsConfig(), 'gopls', undefined);
	const c = new LanguageClient(
		'go',  // id
		cfg.serverName,  // name e.g. gopls
		{
			command: cfg.path,
			args: ['-mode=stdio', ...cfg.flags],
			options: { env: cfg.env },
		},
		{
			initializationOptions: goplsWorkspaceConfig,
			documentSelector: [
				// Filter out unsupported document types, e.g. vsls, git.
				// https://docs.microsoft.com/en-us/visualstudio/liveshare/reference/extensions#visual-studio-code-1
				//
				// - files
				{ language: 'go', scheme: 'file' },
				{ language: 'go.mod', scheme: 'file' },
				{ language: 'go.sum', scheme: 'file' },
				{ language: 'tmpl', scheme: 'file'},
				// - unsaved files
				{ language: 'go', scheme: 'untitled' },
				{ language: 'go.mod', scheme: 'untitled' },
				{ language: 'go.sum', scheme: 'untitled' },
				{ language: 'tmpl', scheme: 'untitled'},
			],
			uriConverters: {
				// Apply file:/// scheme to all file paths.
				code2Protocol: (uri: vscode.Uri): string =>
					(uri.scheme ? uri : uri.with({ scheme: 'file' })).toString(),
				protocol2Code: (uri: string) => vscode.Uri.parse(uri)
			},
			outputChannel: cfg.outputChannel,
			traceOutputChannel: cfg.traceOutputChannel,
			revealOutputChannelOn: RevealOutputChannelOn.Never,
			initializationFailedHandler: (error: WebRequest.ResponseError<InitializeError>): boolean => {
				vscode.window.showErrorMessage(
					`The language server is not able to serve any features. Initialization failed: ${error}. `
				);
				suggestGoplsIssueReport(`The gopls server failed to initialize.`, errorKind.initializationFailure);
				return false;
			},
			errorHandler: {
				error: (error: Error, message: Message, count: number): ErrorAction => {
					vscode.window.showErrorMessage(
						`Error communicating with the language server: ${error}: ${message}.`
					);
					// Allow 5 crashes before shutdown.
					if (count < 5) {
						return ErrorAction.Continue;
					}
					return ErrorAction.Shutdown;
				},
				closed: (): CloseAction => {
					// Allow 5 crashes before shutdown.
					crashCount++;
					if (crashCount < 5) {
						return CloseAction.Restart;
					}
					suggestGoplsIssueReport(
						`The connection to gopls has been closed. The gopls server may have crashed.`,
						errorKind.crash);
					return CloseAction.DoNotRestart;
				},
			},
			middleware: {
				provideCodeLenses: async (
					doc: vscode.TextDocument,
					token: vscode.CancellationToken,
					next: ProvideCodeLensesSignature
				): Promise<vscode.CodeLens[]> => {
					const codeLens = await next(doc, token);
					if (!codeLens || codeLens.length === 0) {
						return codeLens;
					}
					const goplsEnabledLens = (getGoConfig().get('overwriteGoplsMiddleware') as any)?.codelens ?? {};
					return codeLens.reduce((lenses: vscode.CodeLens[], lens: vscode.CodeLens) => {
						switch (lens.command.title) {
							case 'run test': {
								if (goplsEnabledLens.test) {
									return [...lenses, lens];
								}
								return [...lenses, ...createTestCodeLens(lens)];
							}
							case 'run benchmark': {
								if (goplsEnabledLens.bench) {
									return [...lenses, lens];
								}
								return [...lenses, ...createBenchmarkCodeLens(lens)];
							}
							default: {
								return [...lenses, lens];
							}
						}
					}, []);
				},
				provideCompletionItem: async (
					document: vscode.TextDocument,
					position: vscode.Position,
					context: vscode.CompletionContext,
					token: vscode.CancellationToken,
					next: ProvideCompletionItemsSignature
				) => {
					const list = await next(document, position, context, token);
					if (!list) {
						return list;
					}
					const items = Array.isArray(list) ? list : list.items;

					// Give all the candidates the same filterText to trick VSCode
					// into not reordering our candidates. All the candidates will
					// appear to be equally good matches, so VSCode's fuzzy
					// matching/ranking just maintains the natural "sortText"
					// ordering. We can only do this in tandem with
					// "incompleteResults" since otherwise client side filtering is
					// important.
					if (!Array.isArray(list) && list.isIncomplete && list.items.length > 1) {
						let hardcodedFilterText = items[0].filterText;
						if (!hardcodedFilterText) {
							// tslint:disable:max-line-length
							// According to LSP spec,
							// https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion
							// if filterText is falsy, the `label` should be used.
							// But we observed that's not the case.
							// Even if vscode picked the label value, that would
							// cause to reorder candiates, which is not ideal.
							// Force to use non-empty `label`.
							// https://github.com/golang/vscode-go/issues/441
							hardcodedFilterText = items[0].label;
						}
						for (const item of items) {
							item.filterText = hardcodedFilterText;
						}
					}
					// TODO(hyangah): when v1.42+ api is available, we can simplify
					// language-specific configuration lookup using the new
					// ConfigurationScope.
					//    const paramHintsEnabled = vscode.workspace.getConfiguration(
					//          'editor.parameterHints',
					//          { languageId: 'go', uri: document.uri });
					const editorParamHintsEnabled = vscode.workspace.getConfiguration(
						'editor.parameterHints',
						document.uri
					)['enabled'];
					const goParamHintsEnabled = vscode.workspace.getConfiguration('[go]', document.uri)[
						'editor.parameterHints.enabled'
					];
					let paramHintsEnabled: boolean = false;
					if (typeof goParamHintsEnabled === 'undefined') {
						paramHintsEnabled = editorParamHintsEnabled;
					} else {
						paramHintsEnabled = goParamHintsEnabled;
					}
					// If the user has parameterHints (signature help) enabled,
					// trigger it for function or method completion items.
					if (paramHintsEnabled) {
						for (const item of items) {
							if (item.kind === CompletionItemKind.Method || item.kind === CompletionItemKind.Function) {
								item.command = { title: 'triggerParameterHints', command: 'editor.action.triggerParameterHints' };
							}
						}
					}
					return list;
				},
				// Keep track of the last file change in order to not prompt
				// user if they are actively working.
				didOpen: (e, next) => {
					lastUserAction = new Date();
					next(e);
				},
				didChange: (e, next) => {
					lastUserAction = new Date();
					next(e);
				},
				didClose: (e, next) => {
					lastUserAction = new Date();
					next(e);
				},
				didSave: (e, next) => {
					lastUserAction = new Date();
					next(e);
				},
				workspace: {
					configuration: async (params: ConfigurationParams, token: CancellationToken, next: ConfigurationRequest.HandlerSignature): Promise<any[] | ResponseError<void>> => {
						const configs = await next(params, token);
						if (!configs || !Array.isArray(configs)) {
							return configs;
						}
						const ret = [] as any[];
						for (let i = 0; i < configs.length; i++) {
							let workspaceConfig = configs[i];
							if (!!workspaceConfig && typeof workspaceConfig === 'object') {
								const scopeUri = params.items[i].scopeUri;
								const resource = scopeUri ? vscode.Uri.parse(scopeUri) : undefined;
								const section = params.items[i].section;
								workspaceConfig = await adjustGoplsWorkspaceConfiguration(cfg, workspaceConfig, section, resource);
							}
							ret.push(workspaceConfig);
						}
						return ret;
					},
				},
			}
		}
	);
	return c;
}

// filterGoplsDefaultConfigValues removes the entries filled based on the default values
// and selects only those the user explicitly specifies in their settings.
// This returns a new object created based on the filtered properties of workspaceConfig.
// Exported for testing.
export function filterGoplsDefaultConfigValues(workspaceConfig: any, resource: vscode.Uri): any {
	if (!workspaceConfig) {
		workspaceConfig = {};
	}
	const cfg = getGoplsConfig(resource);
	const filtered = {} as { [key: string]: any };
	for (const [key, value] of Object.entries(workspaceConfig)) {
		if (typeof value === 'function') {
			continue;
		}
		const c = cfg.inspect(key);
		// select only the field whose current value comes from non-default setting.
		if (!c || !deepEqual(c.defaultValue, value) ||
			// c.defaultValue !== value would be most likely sufficient, except
			// when gopls' default becomes different from extension's default.
			// So, we also forward the key if ever explicitely stated in one of the
			// settings layers.
			c.globalLanguageValue !== undefined ||
			c.globalValue !== undefined ||
			c.workspaceFolderLanguageValue !== undefined ||
			c.workspaceFolderValue !== undefined ||
			c.workspaceLanguageValue !== undefined ||
			c.workspaceValue !== undefined) {
			filtered[key] = value;
		}
	}
	return filtered;
}

// passGoConfigToGoplsConfigValues passes some of the relevant 'go.' settings to gopls settings.
// This assumes `goplsWorkspaceConfig` is an output of filterGoplsDefaultConfigValues,
// so it is modifiable and doesn't contain properties that are not explicitly set.
//   - go.buildTags and go.buildFlags are passed as gopls.build.buildFlags
//     if goplsWorkspaceConfig doesn't explicitly set it yet.
// Exported for testing.
export function passGoConfigToGoplsConfigValues(goplsWorkspaceConfig: any, goWorkspaceConfig: any): any {
	if (!goplsWorkspaceConfig) {
		goplsWorkspaceConfig = {};
	}

	const buildFlags = [] as string[];
	if (goWorkspaceConfig?.buildFlags) {
		buildFlags.push(...goWorkspaceConfig?.buildFlags);
	}
	if (goWorkspaceConfig?.buildTags && buildFlags.indexOf('-tags') === -1) {
		buildFlags.push('-tags', goWorkspaceConfig?.buildTags);
	}
	// If gopls.build.buildFlags is set, don't touch it.
	if (buildFlags.length > 0 && goplsWorkspaceConfig['build.buildFlags'] === undefined) {
		goplsWorkspaceConfig['build.buildFlags'] = buildFlags;
	}
	return goplsWorkspaceConfig;
}

// adjustGoplsWorkspaceConfiguration filters unnecessary options and adds any necessary, additional
// options to the gopls config. See filterGoplsDefaultConfigValues, passGoConfigToGoplsConfigValues.
// If this is for the nightly extension, we also request to activate features under experiments.
async function adjustGoplsWorkspaceConfiguration(cfg: LanguageServerConfig, workspaceConfig: any, section: string, resource: vscode.Uri): Promise<any> {
	// We process only gopls config
	if (section !== 'gopls') {
		return workspaceConfig;
	}

	workspaceConfig = filterGoplsDefaultConfigValues(workspaceConfig, resource);
	// note: workspaceConfig is a modifiable, valid object.
	workspaceConfig = passGoConfigToGoplsConfigValues(workspaceConfig, getGoConfig(resource));

	// Only modify the user's configurations for the Nightly.
	if (extensionId !== 'golang.go-nightly') {
		return workspaceConfig;
	}
	// allExperiments is only available with gopls/v0.5.2 and above.
	const version = await getLocalGoplsVersion(cfg);
	if (!version) {
		return workspaceConfig;
	}
	const sv = semver.parse(version, true);
	if (!sv || semver.lt(sv, 'v0.5.2')) {
		return workspaceConfig;
	}
	if (!workspaceConfig['allExperiments']) {
		workspaceConfig['allExperiments'] = true;
	}
	return workspaceConfig;
}

// createTestCodeLens adds the go.test.cursor and go.debug.cursor code lens
function createTestCodeLens(lens: vscode.CodeLens): vscode.CodeLens[] {
	// CodeLens argument signature in gopls is [fileName: string, testFunctions: string[], benchFunctions: string[]],
	// so this needs to be deconstructured here
	// Note that there will always only be one test function name in this context
	if (lens.command.arguments.length < 2 || lens.command.arguments[1].length < 1) {
		return [lens];
	}
	return [
		new vscode.CodeLens(lens.range, {
			...lens.command,
			command: 'go.test.cursor',
			arguments: [{ functionName: lens.command.arguments[1][0] }],
		}),
		new vscode.CodeLens(lens.range, {
			title: 'debug test',
			command: 'go.debug.cursor',
			arguments: [{ functionName: lens.command.arguments[1][0] }],
		}),
	];
}

function createBenchmarkCodeLens(lens: vscode.CodeLens): vscode.CodeLens[] {
	// CodeLens argument signature in gopls is [fileName: string, testFunctions: string[], benchFunctions: string[]],
	// so this needs to be deconstructured here
	// Note that there will always only be one benchmark function name in this context
	if (lens.command.arguments.length < 3 || lens.command.arguments[2].length < 1) {
		return [lens];
	}
	return [
		new vscode.CodeLens(lens.range, {
			...lens.command,
			command: 'go.benchmark.cursor',
			arguments: [{ functionName: lens.command.arguments[2][0] }],
		}),
		new vscode.CodeLens(lens.range, {
			title: 'debug benchmark',
			command: 'go.debug.cursor',
			arguments: [{ functionName: lens.command.arguments[2][0] }],
		}),
	];
}

// registerUsualProviders registers the language feature providers if the language server is not enabled.
function registerDefaultProviders(ctx: vscode.ExtensionContext) {
	const completionProvider = new GoCompletionItemProvider(ctx.globalState);
	defaultLanguageProviders.push(completionProvider);
	defaultLanguageProviders.push(vscode.languages.registerCompletionItemProvider(GO_MODE, completionProvider, '.', '"'));
	defaultLanguageProviders.push(vscode.languages.registerHoverProvider(GO_MODE, new GoHoverProvider()));
	defaultLanguageProviders.push(vscode.languages.registerDefinitionProvider(GO_MODE, new GoDefinitionProvider()));
	defaultLanguageProviders.push(vscode.languages.registerReferenceProvider(GO_MODE, new GoReferenceProvider()));
	defaultLanguageProviders.push(
		vscode.languages.registerDocumentSymbolProvider(GO_MODE, new GoDocumentSymbolProvider())
	);
	defaultLanguageProviders.push(vscode.languages.registerWorkspaceSymbolProvider(new GoWorkspaceSymbolProvider()));
	defaultLanguageProviders.push(
		vscode.languages.registerSignatureHelpProvider(GO_MODE, new GoSignatureHelpProvider(), '(', ',')
	);
	defaultLanguageProviders.push(
		vscode.languages.registerImplementationProvider(GO_MODE, new GoImplementationProvider())
	);
	defaultLanguageProviders.push(
		vscode.languages.registerDocumentFormattingEditProvider(GO_MODE, new GoDocumentFormattingEditProvider())
	);
	defaultLanguageProviders.push(
		vscode.languages.registerTypeDefinitionProvider(GO_MODE, new GoTypeDefinitionProvider())
	);
	defaultLanguageProviders.push(vscode.languages.registerRenameProvider(GO_MODE, new GoRenameProvider()));
	defaultLanguageProviders.push(vscode.workspace.onDidChangeTextDocument(parseLiveFile, null, ctx.subscriptions));
	defaultLanguageProviders.push(vscode.languages.registerCodeActionsProvider(GO_MODE, new GoCodeActionProvider()));

	for (const provider of defaultLanguageProviders) {
		ctx.subscriptions.push(provider);
	}
}

function disposeDefaultProviders() {
	for (const disposable of defaultLanguageProviders) {
		disposable.dispose();
	}
	defaultLanguageProviders = [];
}

export function watchLanguageServerConfiguration(e: vscode.ConfigurationChangeEvent) {
	if (!e.affectsConfiguration('go')) {
		return;
	}

	if (
		e.affectsConfiguration('go.useLanguageServer') ||
		e.affectsConfiguration('go.languageServerFlags') ||
		e.affectsConfiguration('go.languageServerExperimentalFeatures') ||
		e.affectsConfiguration('go.alternateTools') ||
		e.affectsConfiguration('go.toolsEnvVars')
		// TODO: Should we check http.proxy too? That affects toolExecutionEnvironment too.
	) {
		restartLanguageServer();
	}
}

export function buildLanguageServerConfig(goConfig: vscode.WorkspaceConfiguration): LanguageServerConfig {
	const cfg: LanguageServerConfig = {
		serverName: '',
		path: '',
		version: '', // compute version lazily
		modtime: null,
		enabled: goConfig['useLanguageServer'] === true,
		flags: goConfig['languageServerFlags'] || [],
		env: toolExecutionEnvironment(),
		checkForUpdates: getCheckForToolsUpdatesConfig(goConfig),
	};
	// Don't look for the path if the server is not enabled.
	if (!cfg.enabled) {
		return cfg;
	}
	const languageServerPath = getLanguageServerToolPath();
	if (!languageServerPath) {
		// Assume the getLanguageServerToolPath will show the relevant
		// errors to the user. Disable the language server.
		cfg.enabled = false;
		return cfg;
	}
	cfg.path = languageServerPath;
	cfg.serverName = getToolFromToolPath(cfg.path);

	// Get the mtime of the language server binary so that we always pick up
	// the right version.
	const stats = fs.statSync(languageServerPath);
	if (!stats) {
		vscode.window.showErrorMessage(`Unable to stat path to language server binary: ${languageServerPath}.
Please try reinstalling it.`);
		// Disable the language server.
		cfg.enabled = false;
		return cfg;
	}
	cfg.modtime = stats.mtime;

	return cfg;
}

/**
 *
 * Return the absolute path to the correct binary. If the required tool is not available,
 * prompt the user to install it. Only gopls is officially supported.
 */
export function getLanguageServerToolPath(): string {
	const goConfig = getGoConfig();
	// Check that all workspace folders are configured with the same GOPATH.
	if (!allFoldersHaveSameGopath()) {
		vscode.window.showInformationMessage(
			'The Go language server is currently not supported in a multi-root set-up with different GOPATHs.'
		);
		return;
	}
	// Get the path to gopls (getBinPath checks for alternate tools).
	const goplsBinaryPath = getBinPath('gopls');
	if (path.isAbsolute(goplsBinaryPath)) {
		return goplsBinaryPath;
	}
	const alternateTools = goConfig['alternateTools'];
	if (alternateTools) {
		// The user's alternate language server was not found.
		const goplsAlternate = alternateTools['gopls'];
		if (goplsAlternate) {
			vscode.window.showErrorMessage(
				`Cannot find the alternate tool ${goplsAlternate} configured for gopls.
Please install it and reload this VS Code window.`
			);
			return;
		}
		// Check if the user has the deprecated "go-langserver" setting.
		// Suggest deleting it if the alternate tool is gopls.
		if (alternateTools['go-langserver']) {
			vscode.window.showErrorMessage(`Support for "go-langserver" has been deprecated.
The recommended language server is gopls. Delete the alternate tool setting for "go-langserver" to use gopls, or change "go-langserver" to "gopls" in your settings.json and reload the VS Code window.`);
			return;
		}
	}

	// Prompt the user to install gopls.
	promptForMissingTool('gopls');
}

function allFoldersHaveSameGopath(): boolean {
	if (!vscode.workspace.workspaceFolders || vscode.workspace.workspaceFolders.length <= 1) {
		return true;
	}
	const tempGopath = getCurrentGoPath(vscode.workspace.workspaceFolders[0].uri);
	return vscode.workspace.workspaceFolders.find((x) => tempGopath !== getCurrentGoPath(x.uri)) ? false : true;
}

export async function shouldUpdateLanguageServer(
	tool: Tool,
	cfg: LanguageServerConfig,
): Promise<semver.SemVer> {
	// Only support updating gopls for now.
	if (tool.name !== 'gopls' || cfg.checkForUpdates === 'off') {
		return null;
	}

	// First, run the "gopls version" command and parse its results.
	// TODO(rstambler): Confirm that the gopls binary's modtime matches the
	// modtime in the config. Update it if needed.
	const usersVersion = await getLocalGoplsVersion(cfg);

	// We might have a developer version. Don't make the user update.
	if (usersVersion === '(devel)') {
		return null;
	}

	// Get the latest gopls version. If it is for nightly, using the prereleased version is ok.
	let latestVersion = cfg.checkForUpdates === 'local' ? tool.latestVersion : await getLatestGoplsVersion(tool);

	// If we failed to get the gopls version, pick the one we know to be latest at the time of this extension's last update
	if (!latestVersion) {
		latestVersion = tool.latestVersion;
	}

	// If "gopls" is so old that it doesn't have the "gopls version" command,
	// or its version doesn't match our expectations, usersVersion will be empty or invalid.
	// Suggest the latestVersion.
	if (!usersVersion || !semver.valid(usersVersion)) {
		return latestVersion;
	}

	// The user may have downloaded golang.org/x/tools/gopls@master,
	// which means that they have a pseudoversion.
	const usersTime = parseTimestampFromPseudoversion(usersVersion);
	// If the user has a pseudoversion, get the timestamp for the latest gopls version and compare.
	if (usersTime) {
		let latestTime = cfg.checkForUpdates ?
			await getTimestampForVersion(tool, latestVersion) : tool.latestVersionTimestamp;
		if (!latestTime) {
			latestTime = tool.latestVersionTimestamp;
		}
		return usersTime.isBefore(latestTime) ? latestVersion : null;
	}

	// If the user's version does not contain a timestamp,
	// default to a semver comparison of the two versions.
	const usersVersionSemver = semver.parse(usersVersion, {
		includePrerelease: true,
		loose: true,
	});
	return semver.lt(usersVersionSemver, latestVersion) ? latestVersion : null;
}

/**
 * forceUpdateGopls will make sure the user is using the latest version of `gopls`,
 * when go.useLanguageServer is changed to true by default.
 *
 * @param tool	Object of type `Tool` for gopls tool.
 * @param cfg	Object of type `Language Server Config` for the users language server
 * 				configuration.
 * @returns		true if the tool was updated
 */
async function forceUpdateGopls(
	tool: Tool,
	cfg: LanguageServerConfig,
): Promise<boolean> {
	const forceUpdatedGoplsKey = 'forceUpdateForGoplsOnDefault';
	// forceUpdated is true when the process of updating has been succesfully completed.
	const forceUpdated = getFromGlobalState(forceUpdatedGoplsKey, false);
	// TODO: If we want to force update again, switch this to be a comparison for a newer version.
	if (!!forceUpdated) {
		return false;
	}
	// Update the state to the latest version to show the last version that was checked.
	await updateGlobalState(forceUpdatedGoplsKey, tool.latestVersion);

	const latestVersion = await shouldUpdateLanguageServer(tool, cfg);

	if (!latestVersion) {
		// The user is using a new enough version
		return false;
	}

	const toolVersion = { ...tool, version: latestVersion }; // ToolWithVersion
	const goVersion = await getGoVersion();
	const failures = await installTools([toolVersion], goVersion);

	// We successfully updated to the latest version.
	if (failures.length === 0) {
		return true;
	}

	// Failed to install the new version of gopls, warn the user.
	vscode.window.showWarningMessage(`'gopls' is now enabled by default and you are using an old version. Please [update 'gopls'](https://github.com/golang/tools/blob/master/gopls/doc/user.md#installation) and restart the language server for the best experience.`);
	return false;
}

// Copied from src/cmd/go/internal/modfetch.go.
const pseudoVersionRE = /^v[0-9]+\.(0\.0-|\d+\.\d+-([^+]*\.)?0\.)\d{14}-[A-Za-z0-9]+(\+incompatible)?$/;

// parseTimestampFromPseudoversion returns the timestamp for the given
// pseudoversion. The timestamp is the center component, and it has the
// format "YYYYMMDDHHmmss".
function parseTimestampFromPseudoversion(version: string): moment.Moment {
	const split = version.split('-');
	if (split.length < 2) {
		return null;
	}
	if (!semver.valid(version)) {
		return null;
	}
	if (!pseudoVersionRE.test(version)) {
		return null;
	}
	const sv = semver.coerce(version);
	if (!sv) {
		return null;
	}
	// Copied from src/cmd/go/internal/modfetch.go.
	const build = sv.build.join('.');
	const buildIndex = version.lastIndexOf(build);
	if (buildIndex >= 0) {
		version = version.substring(0, buildIndex);
	}
	const lastDashIndex = version.lastIndexOf('-');
	version = version.substring(0, lastDashIndex);
	const firstDashIndex = version.lastIndexOf('-');
	const dotIndex = version.lastIndexOf('.');
	let timestamp: string;
	if (dotIndex > firstDashIndex) {
		// "vX.Y.Z-pre.0" or "vX.Y.(Z+1)-0"
		timestamp = version.substring(dotIndex + 1);
	} else {
		// "vX.0.0"
		timestamp = version.substring(firstDashIndex + 1);
	}
	return moment.utc(timestamp, 'YYYYMMDDHHmmss');
}

export const getTimestampForVersion = async (tool: Tool, version: semver.SemVer) => {
	const data = await goProxyRequest(tool, `v${version.format()}.info`);
	if (!data) {
		return null;
	}
	const time = moment(data['Time']);
	return time;
};

const acceptGoplsPrerelease = isNightly();

export const getLatestGoplsVersion = async (tool: Tool) => {
	// If the user has a version of gopls that we understand,
	// ask the proxy for the latest version, and if the user's version is older,
	// prompt them to update.
	const data = await goProxyRequest(tool, 'list');
	if (!data) {
		return null;
	}
	// Coerce the versions into SemVers so that they can be sorted correctly.
	const versions = [];
	for (const version of data.trim().split('\n')) {
		const parsed = semver.parse(version, {
			includePrerelease: true,
			loose: true
		});
		if (parsed) {
			versions.push(parsed);
		}
	}
	if (versions.length === 0) {
		return null;
	}
	versions.sort(semver.rcompare);

	if (acceptGoplsPrerelease) {
		return versions[0]; // The first one (newest one).
	}
	// The first version in the sorted list without a prerelease tag.
	return versions.find((version) => !version.prerelease || !version.prerelease.length);
};

// getLocalGoplsVersion returns the version of gopls that is currently
// installed on the user's machine. This is determined by running the
// `gopls version` command.
//
// If this command has already been executed, it returns the saved result.
export const getLocalGoplsVersion = async (cfg: LanguageServerConfig) => {
	if (!cfg) {
		return null;
	}
	if (cfg.version !== '') {
		return cfg.version;
	}
	const execFile = util.promisify(cp.execFile);
	let output: any;
	try {
		const env = toolExecutionEnvironment();
		const cwd = getWorkspaceFolderPath();
		const { stdout } = await execFile(cfg.path, ['version'], { env, cwd });
		output = stdout;
	} catch (e) {
		// The "gopls version" command is not supported, or something else went wrong.
		// TODO: Should we propagate this error?
		return null;
	}

	const lines = <string>output.trim().split('\n');
	switch (lines.length) {
		case 0:
			// No results, should update.
			// Worth doing anything here?
			return null;
		case 1:
			// Built in $GOPATH mode. Should update.
			// TODO: Should we check the Go version here?
			// Do we even allow users to enable gopls if their Go version is too low?
			return null;
		case 2:
			// We might actually have a parseable version.
			break;
		default:
			return null;
	}

	// The second line should be the sum line.
	// It should look something like this:
	//
	//    golang.org/x/tools/gopls@v0.1.3 h1:CB5ECiPysqZrwxcyRjN+exyZpY0gODTZvNiqQi3lpeo=
	//
	// TODO(stamblerre): We should use a regex to match this, but for now, we split on the @ symbol.
	// The reasoning for this is that gopls still has a golang.org/x/tools/cmd/gopls binary,
	// so users may have a developer version that looks like "golang.org/x/tools@(devel)".
	const moduleVersion = lines[1].trim().split(' ')[0];

	// Get the relevant portion, that is:
	//
	//    golang.org/x/tools/gopls@v0.1.3
	//
	const split = moduleVersion.trim().split('@');
	if (split.length < 2) {
		return null;
	}
	// The version comes after the @ symbol:
	//
	//    v0.1.3
	//
	cfg.version = split[1];
	return cfg.version;
};

async function goProxyRequest(tool: Tool, endpoint: string): Promise<any> {
	// Get the user's value of GOPROXY.
	// If it is not set, we cannot make the request.
	const output: string = process.env['GOPROXY'];
	if (!output || !output.trim()) {
		return null;
	}
	// Try each URL set in the user's GOPROXY environment variable.
	// If none is set, don't make the request.
	const proxies = output.trim().split(/,|\|/);
	for (const proxy of proxies) {
		if (proxy === 'direct') {
			continue;
		}
		const url = `${proxy}/${tool.importPath}/@v/${endpoint}`;
		let data: string;
		try {
			data = await WebRequest.json<string>(url, {
				throwResponseError: true
			});
		} catch (e) {
			console.log(`Error sending request to ${proxy}: ${e}`);
			return null;
		}
		return data;
	}
	return null;
}

// SurveyConfig is the set of global properties used to determine if
// we should prompt a user to take the gopls survey.
export interface SurveyConfig {
	// prompt is true if the user can be prompted to take the survey.
	// It is false if the user has responded "Never" to the prompt.
	prompt?: boolean;

	// promptThisMonth is true if we have used a random number generator
	// to determine if the user should be prompted this month.
	// It is undefined if we have not yet made the determination.
	promptThisMonth?: boolean;

	// dateToPromptThisMonth is the date on which we should prompt the user
	// this month.
	dateToPromptThisMonth?: Date;

	// dateComputedPromptThisMonth is the date on which the values of
	// promptThisMonth and dateToPromptThisMonth were set.
	dateComputedPromptThisMonth?: Date;

	// lastDatePrompted is the most recent date that the user has been prompted.
	lastDatePrompted?: Date;

	// lastDateAccepted is the most recent date that the user responded "Yes"
	// to the survey prompt. The user need not have completed the survey.
	lastDateAccepted?: Date;
}

function maybePromptForGoplsSurvey() {
	const now = new Date();
	let cfg = shouldPromptForGoplsSurvey(now, getSurveyConfig());
	if (!cfg) {
		return;
	}
	flushSurveyConfig(cfg);
	if (!cfg.dateToPromptThisMonth) {
		return;
	}
	const callback = async () => {
		const currentTime = new Date();

		// Make sure the user has been idle for at least a minute.
		if (minutesBetween(lastUserAction, currentTime) < 1) {
			setTimeout(callback, 5 * timeMinute);
			return;
		}
		cfg = await promptForSurvey(cfg, now);
		if (cfg) {
			flushSurveyConfig(cfg);
		}
	};
	const ms = msBetween(now, cfg.dateToPromptThisMonth);
	setTimeout(callback, ms);
}

export function shouldPromptForGoplsSurvey(now: Date, cfg: SurveyConfig): SurveyConfig {
	// If the prompt value is not set, assume we haven't prompted the user
	// and should do so.
	if (cfg.prompt === undefined) {
		cfg.prompt = true;
	}
	if (!cfg.prompt) {
		return;
	}

	// Check if the user has taken the survey in the last year.
	// Don't prompt them if they have been.
	if (cfg.lastDateAccepted) {
		if (daysBetween(now, cfg.lastDateAccepted) < 365) {
			return;
		}
	}

	// Check if the user has been prompted for the survey in the last 90 days.
	// Don't prompt them if they have been.
	if (cfg.lastDatePrompted) {
		if (daysBetween(now, cfg.lastDatePrompted) < 90) {
			return;
		}
	}

	// Check if the extension has been activated this month.
	if (cfg.dateComputedPromptThisMonth) {
		// The extension has been activated this month, so we should have already
		// decided if the user should be prompted.
		if (daysBetween(now, cfg.dateComputedPromptThisMonth) < 30) {
			return cfg;
		}
	}
	// This is the first activation this month (or ever), so decide if we
	// should prompt the user. This is done by generating a random number in
	// the range [0, 1) and checking if it is < probability, which varies
	// depending on whether the default or the nightly is in use.
	// We then randomly pick a day in the rest of the month on which to prompt
	// the user.
	let probability = 0.01; // lower probability for the regular extension
	if (isNightly()) {
		probability = 0.0275;
	}
	cfg.promptThisMonth = Math.random() < probability;
	if (cfg.promptThisMonth) {
		// end is the last day of the month, day is the random day of the
		// month on which to prompt.
		const end = new Date(now.getFullYear(), now.getMonth() + 1, 0);
		const day = randomIntInRange(now.getUTCDate(), end.getUTCDate());
		cfg.dateToPromptThisMonth = new Date(now.getFullYear(), now.getMonth(), day);
	} else {
		cfg.dateToPromptThisMonth = undefined;
	}
	cfg.dateComputedPromptThisMonth = now;
	return cfg;
}

// isNightly returns true if the extension ID is the extension ID for the
// Nightly extension.
export function isNightly(): boolean {
	return extensionId === 'golang.go-nightly';
}

async function promptForSurvey(cfg: SurveyConfig, now: Date): Promise<SurveyConfig> {
	const selected = await vscode.window.showInformationMessage(`Looks like you're using gopls, the Go language server.
Would you be willing to fill out a quick survey about your experience with gopls?`, 'Yes', 'Not now', 'Never');

	// Update the time last asked.
	cfg.lastDatePrompted = now;

	switch (selected) {
		case 'Yes':
			cfg.lastDateAccepted = now;
			cfg.prompt = true;
			const usersGoplsVersion = await getLocalGoplsVersion(latestConfig);
			await vscode.env.openExternal(vscode.Uri.parse(`https://google.qualtrics.com/jfe/form/SV_ekAdHVcVcvKUojX?gopls=${usersGoplsVersion}&extid=${extensionId}`));
			break;
		case 'Not now':
			cfg.prompt = true;

			vscode.window.showInformationMessage(`No problem! We'll ask you again another time.`);
			break;
		case 'Never':
			cfg.prompt = false;

			vscode.window.showInformationMessage(`No problem! We won't ask again.`);
			break;
		default:
			// If the user closes the prompt without making a selection, treat it
			// like a "Not now" response.
			cfg.prompt = true;

			break;
	}
	return cfg;
}

export const goplsSurveyConfig = 'goplsSurveyConfig';

function getSurveyConfig(surveyConfigKey = goplsSurveyConfig): SurveyConfig {
	const saved = getFromGlobalState(surveyConfigKey);
	if (saved === undefined) {
		return {};
	}
	try {
		const cfg = JSON.parse(saved, (key: string, value: any) => {
			// Make sure values that should be dates are correctly converted.
			if (key.toLowerCase().includes('date') || key.toLowerCase().includes('timestamp')) {
				return new Date(value);
			}
			return value;
		});
		return cfg || {};
	} catch (err) {
		console.log(`Error parsing JSON from ${saved}: ${err}`);
		return {};
	}
}

export async function showSurveyConfig() {
	outputChannel.appendLine('Gopls Survey Configuration');
	outputChannel.appendLine(JSON.stringify(getSurveyConfig(), null, 2));
	outputChannel.show();

	const selected = await vscode.window.showInformationMessage(`Prompt for survey?`, 'Yes', 'Maybe', 'No');
	switch (selected) {
		case 'Yes':
			promptForSurvey(getSurveyConfig(), new Date());
			break;
		case 'Maybe':
			maybePromptForGoplsSurvey();
			break;
		default:
			break;
	}
}

export function resetSurveyConfig() {
	flushSurveyConfig(null);
}

function flushSurveyConfig(cfg: SurveyConfig) {
	if (cfg) {
		updateGlobalState(goplsSurveyConfig, JSON.stringify(cfg));
	} else {
		updateGlobalState(goplsSurveyConfig, null);  // reset
	}
}

// errorKind refers to the different possible kinds of gopls errors.
enum errorKind {
	initializationFailure,
	crash,
	manualRestart,
}

// suggestGoplsIssueReport prompts users to file an issue with gopls.
async function suggestGoplsIssueReport(msg: string, reason: errorKind) {
	// Don't prompt users who manually restart to file issues until gopls/v1.0.
	if (reason === errorKind.manualRestart) {
		return;
	}

	// The user may have an outdated version of gopls, in which case we should
	// just prompt them to update, not file an issue.
	const tool = getTool('gopls');
	if (tool) {
		const versionToUpdate = await shouldUpdateLanguageServer(tool, latestConfig);
		if (versionToUpdate) {
			promptForUpdatingTool(tool.name, versionToUpdate, true);
			return;
		}
	}

	// Show the user the output channel content to alert them to the issue.
	serverOutputChannel.show();

	if (latestConfig.serverName !== 'gopls') {
		return;
	}
	const promptForIssueOnGoplsRestartKey = `promptForIssueOnGoplsRestart`;
	let saved: any;
	try {
		saved = JSON.parse(getFromGlobalState(promptForIssueOnGoplsRestartKey, false));
	} catch (err) {
		console.log(`Failed to parse as JSON ${getFromGlobalState(promptForIssueOnGoplsRestartKey, true)}: ${err}`);
		return;
	}
	// If the user has already seen this prompt, they may have opted-out for
	// the future. Only prompt again if it's been more than a year since.
	if (saved) {
		const dateSaved = new Date(saved['date']);
		const prompt = <boolean>saved['prompt'];
		if (!prompt && daysBetween(new Date(), dateSaved) <= 365) {
			return;
		}
	}
	const selected = await vscode.window.showInformationMessage(`${msg} Would you like to report a gopls issue on GitHub?
You will be asked to provide additional information and logs, so PLEASE READ THE CONTENT IN YOUR BROWSER.`, 'Yes', 'Next time', 'Never');
	switch (selected) {
		case 'Yes':
			// Prefill an issue title and report.
			let errKind: string;
			switch (reason) {
				case errorKind.crash:
					errKind = 'crash';
					break;
				case errorKind.initializationFailure:
					errKind = 'initialization';
					break;
			}
			// Get the user's version in case the update prompt above failed.
			const usersGoplsVersion = await getLocalGoplsVersion(latestConfig);
			const extInfo = getExtensionInfo();
			const settings = latestConfig.flags.join(' ');
			const title = `gopls: automated issue report (${errKind})`;
			const { sanitizedLog, failureReason } = await collectGoplsLog();
			const goplsLog = (sanitizedLog) ?
				`<pre>${sanitizedLog}</pre>` :
				`Please attach the stack trace from the crash.
A window with the error message should have popped up in the lower half of your screen.
Please copy the stack trace and error messages from that window and paste it in this issue.

<PASTE STACK TRACE HERE>

Failed to auto-collect gopls trace: ${failureReason}.
`;

			const body = `
gopls version: ${usersGoplsVersion}
gopls flags: ${settings}
extension version: ${extInfo.version}
environment: ${extInfo.appName}

ATTENTION: PLEASE PROVIDE THE DETAILS REQUESTED BELOW.

Describe what you observed.

<ANSWER HERE>

${goplsLog}

OPTIONAL: If you would like to share more information, you can attach your complete gopls logs.

NOTE: THESE MAY CONTAIN SENSITIVE INFORMATION ABOUT YOUR CODEBASE.
DO NOT SHARE LOGS IF YOU ARE WORKING IN A PRIVATE REPOSITORY.

<OPTIONAL: ATTACH LOGS HERE>
`;
			const url = `https://github.com/golang/vscode-go/issues/new?title=${title}&labels=upstream-tools&body=${body}`;
			await vscode.env.openExternal(vscode.Uri.parse(url));
			break;
		case 'Next time':
			break;
		case 'Never':
			updateGlobalState(promptForIssueOnGoplsRestartKey, JSON.stringify({
				prompt: false,
				date: new Date(),
			}));
			break;
	}
}

// randomIntInRange returns a random integer between min and max, inclusive.
function randomIntInRange(min: number, max: number): number {
	const low = Math.ceil(min);
	const high = Math.floor(max);
	return Math.floor(Math.random() * (high - low + 1)) + low;
}

export const timeMinute = 1000 * 60;
const timeHour = timeMinute * 60;
const timeDay = timeHour * 24;

// daysBetween returns the number of days between a and b.
function daysBetween(a: Date, b: Date): number {
	return msBetween(a, b) / timeDay;
}

// minutesBetween returns the number of minutes between a and b.
function minutesBetween(a: Date, b: Date): number {
	return msBetween(a, b) / timeMinute;
}

function msBetween(a: Date, b: Date): number {
	return Math.abs(a.getTime() - b.getTime());
}

export function showServerOutputChannel() {
	if (!languageServerIsRunning) {
		vscode.window.showInformationMessage(`gopls is not running`);
		return;
	}
	// likely show() is asynchronous, despite the documentation
	serverOutputChannel.show();
	let found: vscode.TextDocument;
	for (const doc of vscode.workspace.textDocuments) {
		if (doc.fileName.indexOf('extension-output-') !== -1) {
			// despite show() above, this might not get the output we want, so check
			const contents = doc.getText();
			if (contents.indexOf('[Info  - ') === -1) {
				continue;
			}
			if (found !== undefined) {
				vscode.window.showInformationMessage('multiple docs named extension-output-...');
			}
			found = doc;
			// .log, as some decoration is better than none
			vscode.workspace.openTextDocument({ language: 'log', content: contents });
		}
	}
	if (found === undefined) {
		vscode.window.showErrorMessage('make sure "gopls (server)" output is showing');
	}
}

function sleep(ms: number) {
	return new Promise((resolve) => setTimeout(resolve, ms));
}

async function collectGoplsLog(): Promise<{ sanitizedLog?: string; failureReason?: string; }> {
	serverOutputChannel.show();
	// Find the logs in the output channel. There is no way to read
	// an output channel directly, but we can find the open text
	// document, since we just surfaced the output channel to the user.
	// See https://github.com/microsoft/vscode/issues/65108.
	let logs: string;
	for (let i = 0; i < 3; i++) {
		// try a couple of times until successfully finding the channel.
		for (const doc of vscode.workspace.textDocuments) {
			if (doc.languageId !== 'Log') {
				continue;
			}
			if (doc.isDirty || doc.isClosed) {
				continue;
			}
			// The document's name should look like 'extension-output-#X'.
			if (doc.fileName.indexOf('extension-output-') === -1) {
				continue;
			}
			logs = doc.getText();
			break;
		}
		if (!!logs) {
			break;
		}
		// sleep a bit before the next try. The choice of the sleep time is arbitrary.
		await sleep((i + 1) * 10);
	}

	return sanitizeGoplsTrace(logs);
}

// capture only panic stack trace and the initialization error message.
// exported for testing.
export function sanitizeGoplsTrace(logs?: string): { sanitizedLog?: string, failureReason?: string } {
	if (!logs) {
		return { failureReason: 'no gopls log' };
	}
	const panicMsgBegin = logs.lastIndexOf('panic: ');
	if (panicMsgBegin > -1) {  // panic message was found.
		const panicMsgEnd = logs.indexOf('Connection to server got closed.', panicMsgBegin);
		if (panicMsgEnd > -1) {
			const panicTrace = logs.substr(panicMsgBegin, panicMsgEnd - panicMsgBegin);
			const filePattern = /(\S+\.go):\d+/;
			const sanitized = panicTrace.split('\n').map(
				(line: string) => {
					// Even though this is a crash from gopls, the file path
					// can contain user names and user's filesystem directory structure.
					// We can still locate the corresponding file if the file base is
					// available because the full package path is part of the function
					// name. So, leave only the file base.
					const m = line.match(filePattern);
					if (!m) { return line; }
					const filePath = m[1];
					const fileBase = path.basename(filePath);
					return line.replace(filePath, '  ' + fileBase);
				}
			).join('\n');

			if (sanitized) {
				return { sanitizedLog: sanitized };
			}
			return { failureReason: 'empty panic trace' };
		}
		return { failureReason: 'incomplete panic trace' };
	}
	const initFailMsgBegin = logs.lastIndexOf('Starting client failed');
	if (initFailMsgBegin > -1) {  // client start failed. Capture up to the 'Code:' line.
		const initFailMsgEnd = logs.indexOf('Code: ', initFailMsgBegin);
		if (initFailMsgEnd > -1) {
			const lineEnd = logs.indexOf('\n', initFailMsgEnd);
			return { sanitizedLog: lineEnd > -1 ? logs.substr(initFailMsgBegin, lineEnd - initFailMsgBegin) : logs.substr(initFailMsgBegin) };
		}
	}
	if (logs.lastIndexOf('Usage: gopls') > -1) {
		return { failureReason: 'incorrect gopls command usage' };
	}
	return { failureReason: 'unrecognized crash pattern' };
}

export async function promptForLanguageServerDefaultChange(cfg: vscode.WorkspaceConfiguration) {
	const useLanguageServer = cfg.inspect<boolean>('useLanguageServer');
	if (!languageServerUsingDefault(cfg)) {
		if (!cfg['useLanguageServer']) {  // ask users who explicitly disabled.
			promptForLanguageServerOptOutSurvey();
		}
		return;  // user already explicitly set the field.
	}

	const promptedForLSDefaultChangeKey = `promptedForLSDefaultChange`;
	if (getFromGlobalState(promptedForLSDefaultChangeKey, false)) {
		return;
	}

	const selected = await vscode.window.showInformationMessage(
		`"go.useLanguageServer" is enabled by default. If you need to disable it, please configure in the settings.`,
		'Open Settings', 'OK');
	switch (selected) {
		case 'Open Settings':
			vscode.commands.executeCommand('workbench.action.openSettings', 'go.useLanguageServer');
		default:
	}
	updateGlobalState(promptedForLSDefaultChangeKey, true);
}

function languageServerUsingDefault(cfg: vscode.WorkspaceConfiguration): boolean {
	const useLanguageServer = cfg.inspect<boolean>('useLanguageServer');
	return useLanguageServer.globalValue === undefined && useLanguageServer.workspaceValue === undefined;
}

// Prompt users who disabled the language server and ask to file an issue.
async function promptForLanguageServerOptOutSurvey() {
	const promptedForLSOptOutSurveyKey = `promptedForLSOptOutSurvey`;
	const value = getSurveyConfig(promptedForLSOptOutSurveyKey);  // We use only 'prompt' and 'lastDatePrompted' fields.

	if (value?.prompt === false ||
		(value?.lastDatePrompted && daysBetween(value.lastDatePrompted, new Date()) < 90)) {
		return;
	}

	value.lastDatePrompted = new Date();

	const selected = await vscode.window.showInformationMessage(
		`Looks like you've disabled the language server. Would you be willing to file an issue and tell us why you had to disable it?`,
		'Yes', 'Not now', 'Never');
	switch (selected) {
		case 'Yes':
			const title = 'gopls: automated issue report (opt out)';
			const body = `
Please tell us why you had to disable the language server.

`;
			const url = `https://github.com/golang/vscode-go/issues/new?title=${title}&labels=upstream-tools&body=${body}`;
			await vscode.env.openExternal(vscode.Uri.parse(url));
			break;
		case 'Never':
			value.prompt = false;
			break;
		default:
	}
	updateGlobalState(promptedForLSOptOutSurveyKey, JSON.stringify(value));
}

interface ExtensionInfo {
	version: string;  // Extension version
	appName: string;  // The application name of the editor, like 'VS Code'
}

function getExtensionInfo(): ExtensionInfo {
	const version = vscode.extensions.getExtension(extensionId)?.packageJSON?.version;
	const appName = vscode.env.appName;
	return { version, appName };

}
