/*---------------------------------------------------------
 * Copyright (C) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------*/

'use strict';

import cp = require('child_process');
import fs = require('fs');
import path = require('path');
import vscode = require('vscode');
import { getLanguageServerToolPath } from './goLanguageServer';
import { envPath, getToolFromToolPath } from './goPath';
import { hideGoStatus, outputChannel, showGoStatus } from './goStatus';
import {
	containsString,
	containsTool,
	disableModulesForWildcard,
	getConfiguredTools,
	getImportPath,
	getTool,
	hasModSuffix,
	isGocode,
	Tool
} from './goTools';
import {
	getBinPath,
	getCurrentGoPath,
	getGoConfig,
	getGoVersion,
	getTempFilePath,
	getToolsGopath,
	GoVersion,
	resolvePath
} from './util';

// declinedUpdates tracks the tools that the user has declined to update.
const declinedUpdates: Tool[] = [];

// declinedUpdates tracks the tools that the user has declined to install.
const declinedInstalls: Tool[] = [];

export async function installAllTools(updateExistingToolsOnly: boolean = false) {
	const goVersion = await getGoVersion();
	let allTools = getConfiguredTools(goVersion);

	// exclude tools replaced by alternateTools.
	const alternateTools: { [key: string]: string } = getGoConfig().get('alternateTools');
	allTools = allTools.filter((tool) => {
		return !alternateTools[tool.name];
	});

	// Update existing tools by finding all tools the user has already installed.
	if (updateExistingToolsOnly) {
		installTools(
			allTools.filter((tool) => {
				const toolPath = getBinPath(tool.name);
				return toolPath && path.isAbsolute(toolPath);
			}),
			goVersion
		);
		return;
	}

	// Otherwise, allow the user to select which tools to install or update.
	vscode.window
		.showQuickPick(
			allTools.map((x) => {
				const item: vscode.QuickPickItem = {
					label: x.name,
					description: x.description
				};
				return item;
			}),
			{
				canPickMany: true,
				placeHolder: 'Select the tools to install/update.'
			}
		)
		.then((selectedTools) => {
			if (!selectedTools) {
				return;
			}
			installTools(
				selectedTools.map((x) => getTool(x.label)),
				goVersion
			);
		});
}

/**
 * Installs given array of missing tools. If no input is given, the all tools are installed
 *
 * @param string[] array of tool names to be installed
 */
export function installTools(missing: Tool[], goVersion: GoVersion): Promise<void> {
	const goRuntimePath = getBinPath('go');
	if (!goRuntimePath) {
		vscode.window.showErrorMessage(
			`Failed to run "go get" to install the packages as the "go" binary cannot be found in either GOROOT(${process.env['GOROOT']}) or PATH(${envPath})`
		);
		return;
	}
	if (!missing) {
		return;
	}

	// http.proxy setting takes precedence over environment variables
	const httpProxy = vscode.workspace.getConfiguration('http', null).get('proxy');
	let envForTools = Object.assign({}, process.env);
	if (httpProxy) {
		envForTools = Object.assign({}, process.env, {
			http_proxy: httpProxy,
			HTTP_PROXY: httpProxy,
			https_proxy: httpProxy,
			HTTPS_PROXY: httpProxy
		});
	}

	outputChannel.show();
	outputChannel.clear();

	// If the go.toolsGopath is set, use its value as the GOPATH for the "go get" child process.
	// Else use the Current Gopath
	let toolsGopath = getToolsGopath();
	if (toolsGopath) {
		// User has explicitly chosen to use toolsGopath, so ignore GOBIN
		envForTools['GOBIN'] = '';
		outputChannel.appendLine(`Using the value ${toolsGopath} from the go.toolsGopath setting.`);
	} else {
		toolsGopath = getCurrentGoPath();
		outputChannel.appendLine(`go.toolsGopath setting is not set. Using GOPATH ${toolsGopath}`);
	}
	if (toolsGopath) {
		const paths = toolsGopath.split(path.delimiter);
		toolsGopath = paths[0];
		envForTools['GOPATH'] = toolsGopath;
	} else {
		const msg = 'Cannot install Go tools. Set either go.gopath or go.toolsGopath in settings.';
		vscode.window.showInformationMessage(msg, 'Open User Settings', 'Open Workspace Settings').then((selected) => {
			switch (selected) {
				case 'Open User Settings':
					vscode.commands.executeCommand('workbench.action.openGlobalSettings');
					break;
				case 'Open Workspace Settings':
					vscode.commands.executeCommand('workbench.action.openWorkspaceSettings');
					break;
			}
		});
		return;
	}

	let installingMsg = `Installing ${missing.length} ${missing.length > 1 ? 'tools' : 'tool'} at `;
	if (envForTools['GOBIN']) {
		installingMsg += `the configured GOBIN: ${envForTools['GOBIN']}`;
	} else {
		installingMsg += toolsGopath + path.sep + 'bin';
	}

	// If the user is on Go >= 1.11, tools should be installed with modules enabled.
	// This ensures that users get the latest tagged version, rather than master,
	// which may be unstable.
	let modulesOff = false;
	if (goVersion.lt('1.11')) {
		modulesOff = true;
	} else {
		installingMsg += ' in module mode.';
	}

	outputChannel.appendLine(installingMsg);
	missing.forEach((missingTool) => {
		outputChannel.appendLine('  ' + missingTool.name);
	});

	outputChannel.appendLine(''); // Blank line for spacing.

	// Install tools in a temporary directory, to avoid altering go.mod files.
	const toolsTmpDir = fs.mkdtempSync(getTempFilePath('go-tools-'));

	return missing
		.reduce((res: Promise<string[]>, tool: Tool) => {
			return res.then(
				(sofar) =>
					new Promise<string[]>((resolve, reject) => {
						// Disable modules for tools which are installed with the "..." wildcard.
						// TODO: ... will be supported in Go 1.13, so enable these tools to use modules then.
						const modulesOffForTool = modulesOff || disableModulesForWildcard(tool, goVersion);
						let tmpGoModFile: string;
						if (modulesOffForTool) {
							envForTools['GO111MODULE'] = 'off';
						} else {
							envForTools['GO111MODULE'] = 'on';
							// Write a temporary go.mod file to avoid version conflicts.
							tmpGoModFile = path.join(toolsTmpDir, 'go.mod');
							fs.writeFileSync(tmpGoModFile, 'module tools');
						}

						const opts = {
							env: envForTools,
							cwd: toolsTmpDir
						};

						const callback = (err: Error, stdout: string, stderr: string) => {
							// Make sure to delete the temporary go.mod file, if it exists.
							if (tmpGoModFile && fs.existsSync(tmpGoModFile)) {
								fs.unlinkSync(tmpGoModFile);
							}
							if (err) {
								outputChannel.appendLine('Installing ' + getImportPath(tool, goVersion) + ' FAILED');
								const failureReason = tool.name + ';;' + err + stdout.toString() + stderr.toString();
								resolve([...sofar, failureReason]);
							} else {
								outputChannel.appendLine('Installing ' + getImportPath(tool, goVersion) + ' SUCCEEDED');
								resolve([...sofar, null]);
							}
						};

						let closeToolPromise = Promise.resolve(true);
						const toolBinPath = getBinPath(tool.name);
						if (path.isAbsolute(toolBinPath) && isGocode(tool)) {
							closeToolPromise = new Promise<boolean>((innerResolve) => {
								cp.execFile(toolBinPath, ['close'], {}, (err, stdout, stderr) => {
									if (stderr && stderr.indexOf(`rpc: can't find service Server.`) > -1) {
										outputChannel.appendLine(
											'Installing gocode aborted as existing process cannot be closed. Please kill the running process for gocode and try again.'
										);
										return innerResolve(false);
									}
									innerResolve(true);
								});
							});
						}

						closeToolPromise.then((success) => {
							if (!success) {
								resolve([...sofar, null]);
								return;
							}
							const args = ['get', '-v'];
							// Only get tools at master if we are not using modules.
							if (modulesOffForTool) {
								args.push('-u');
							}
							// Tools with a "mod" suffix should not be installed,
							// instead we run "go build -o" to rename them.
							if (hasModSuffix(tool)) {
								args.push('-d');
							}
							args.push(getImportPath(tool, goVersion));
							cp.execFile(goRuntimePath, args, opts, (err, stdout, stderr) => {
								if (stderr.indexOf('unexpected directory layout:') > -1) {
									outputChannel.appendLine(
										`Installing ${tool.name} failed with error "unexpected directory layout". Retrying...`
									);
									cp.execFile(goRuntimePath, args, opts, callback);
								} else if (!err && hasModSuffix(tool)) {
									const outputFile = path.join(
										toolsGopath,
										'bin',
										process.platform === 'win32' ? `${tool.name}.exe` : tool.name
									);
									cp.execFile(
										goRuntimePath,
										['build', '-o', outputFile, getImportPath(tool, goVersion)],
										opts,
										callback
									);
								} else {
									callback(err, stdout, stderr);
								}
							});
						});
					})
			);
		}, Promise.resolve([]))
		.then((res) => {
			outputChannel.appendLine(''); // Blank line for spacing
			const failures = res.filter((x) => x != null);
			if (failures.length === 0) {
				if (containsString(missing, 'go-langserver') || containsString(missing, 'gopls')) {
					outputChannel.appendLine('Reload VS Code window to use the Go language server');
				}
				outputChannel.appendLine('All tools successfully installed. You are ready to Go :).');
				return;
			}

			outputChannel.appendLine(failures.length + ' tools failed to install.\n');
			failures.forEach((failure) => {
				const reason = failure.split(';;');
				outputChannel.appendLine(reason[0] + ':');
				outputChannel.appendLine(reason[1]);
			});
		});
}

export async function promptForMissingTool(toolName: string) {
	const tool = getTool(toolName);

	// If user has declined to install this tool, don't prompt for it.
	if (containsTool(declinedInstalls, tool)) {
		return;
	}

	const goVersion = await getGoVersion();
	// Show error messages for outdated tools.
	if (goVersion.lt('1.9')) {
		let outdatedErrorMsg;
		switch (tool.name) {
			case 'golint':
				outdatedErrorMsg =
					'golint no longer supports go1.8 or below, update your settings to use golangci-lint as go.lintTool and install golangci-lint';
				break;
			case 'gotests':
				outdatedErrorMsg =
					'Generate unit tests feature is not supported as gotests tool needs go1.9 or higher.';
				break;
		}
		if (outdatedErrorMsg) {
			vscode.window.showInformationMessage(outdatedErrorMsg);
			return;
		}
	}

	const installOptions = ['Install'];
	let missing = await getMissingTools(goVersion);
	if (!containsTool(missing, tool)) {
		return;
	}
	missing = missing.filter((x) => x === tool || tool.isImportant);
	if (missing.length > 1) {
		// Offer the option to install all tools.
		installOptions.push('Install All');
	}
	const msg = `The "${tool.name}" command is not available. Run "go get -v ${getImportPath(
		tool,
		goVersion
	)}" to install.`;
	vscode.window.showInformationMessage(msg, ...installOptions).then((selected) => {
		switch (selected) {
			case 'Install':
				installTools([tool], goVersion);
				break;
			case 'Install All':
				installTools(missing, goVersion);
				hideGoStatus();
				break;
			default:
				// The user has declined to install this tool.
				declinedInstalls.push(tool);
				break;
		}
	});
}

export async function promptForUpdatingTool(toolName: string) {
	const tool = getTool(toolName);

	// If user has declined to update, then don't prompt.
	if (containsTool(declinedUpdates, tool)) {
		return;
	}
	const goVersion = await getGoVersion();
	const updateMsg = `Your version of ${tool.name} appears to be out of date. Please update for an improved experience.`;
	const choices: string[] = ['Update'];
	if (toolName === `gopls`) {
		choices.push('Release Notes'); // TODO(hyangah): pass more info such as version, release note location.
	}
	vscode.window.showInformationMessage(updateMsg, ...choices).then((selected) => {
		switch (selected) {
			case 'Update':
				installTools([tool], goVersion);
				break;
			case 'Release Notes':
				vscode.commands.executeCommand(
					'vscode.open',
					vscode.Uri.parse('https://github.com/golang/go/issues/33030#issuecomment-510151934')
				);
				break;
			default:
				declinedUpdates.push(tool);
				break;
		}
	});
}

export function updateGoPathGoRootFromConfig(): Promise<void> {
	const goroot = getGoConfig()['goroot'];
	if (goroot) {
		process.env['GOROOT'] = resolvePath(goroot);
	}

	if (process.env['GOPATH'] && process.env['GOROOT'] && process.env['GOPROXY']) {
		return Promise.resolve();
	}

	// If GOPATH is still not set, then use the one from `go env`
	const goRuntimePath = getBinPath('go');
	if (!goRuntimePath) {
		vscode.window.showErrorMessage(
			`Failed to run "go env" to find GOPATH as the "go" binary cannot be found in either GOROOT(${process.env['GOROOT']}) or PATH(${envPath})`
		);
		return;
	}
	const goRuntimeBasePath = path.dirname(goRuntimePath);

	// cgo and a few other Go tools expect Go binary to be in the path
	let pathEnvVar: string;
	if (process.env.hasOwnProperty('PATH')) {
		pathEnvVar = 'PATH';
	} else if (process.platform === 'win32' && process.env.hasOwnProperty('Path')) {
		pathEnvVar = 'Path';
	}
	if (
		goRuntimeBasePath &&
		pathEnvVar &&
		process.env[pathEnvVar] &&
		(<string>process.env[pathEnvVar]).split(path.delimiter).indexOf(goRuntimeBasePath) === -1
	) {
		process.env[pathEnvVar] += path.delimiter + goRuntimeBasePath;
	}

	return new Promise<void>((resolve, reject) => {
		cp.execFile(goRuntimePath, ['env', 'GOPATH', 'GOROOT', 'GOPROXY'], (err, stdout, stderr) => {
			if (err) {
				return reject();
			}
			const envOutput = stdout.split('\n');
			if (!process.env['GOPATH'] && envOutput[0].trim()) {
				process.env['GOPATH'] = envOutput[0].trim();
			}
			if (!process.env['GOROOT'] && envOutput[1] && envOutput[1].trim()) {
				process.env['GOROOT'] = envOutput[1].trim();
			}
			if (!process.env['GOPROXY'] && envOutput[2] && envOutput[2].trim()) {
				process.env['GOPROXY'] = envOutput[2].trim();
			}
			return resolve();
		});
	});
}

let alreadyOfferedToInstallTools = false;

export async function offerToInstallTools() {
	if (alreadyOfferedToInstallTools) {
		return;
	}
	alreadyOfferedToInstallTools = true;

	const goVersion = await getGoVersion();
	let missing = await getMissingTools(goVersion);
	missing = missing.filter((x) => x.isImportant);
	if (missing.length > 0) {
		showGoStatus('Analysis Tools Missing', 'go.promptforinstall', 'Not all Go tools are available on the GOPATH');
		vscode.commands.registerCommand('go.promptforinstall', () => {
			const installItem = {
				title: 'Install',
				command() {
					hideGoStatus();
					installTools(missing, goVersion);
				}
			};
			const showItem = {
				title: 'Show',
				command() {
					outputChannel.clear();
					outputChannel.appendLine('Below tools are needed for the basic features of the Go extension.');
					missing.forEach((x) => outputChannel.appendLine(x.name));
				}
			};
			vscode.window
				.showInformationMessage(
					'Failed to find some of the Go analysis tools. Would you like to install them?',
					installItem,
					showItem
				)
				.then((selection) => {
					if (selection) {
						selection.command();
					} else {
						hideGoStatus();
					}
				});
		});
	}

	const usingSourceGraph = getToolFromToolPath(getLanguageServerToolPath()) === 'go-langserver';
	if (usingSourceGraph && goVersion.gt('1.10')) {
		const promptMsg =
			'The language server from Sourcegraph is no longer under active development and it does not support Go modules as well. Please install and use the language server from Google or disable the use of language servers altogether.';
		const disableLabel = 'Disable language server';
		const installLabel = 'Install';
		vscode.window.showInformationMessage(promptMsg, installLabel, disableLabel).then((selected) => {
			if (selected === installLabel) {
				installTools([getTool('gopls')], goVersion).then(() => {
					vscode.window.showInformationMessage(
						'Reload VS Code window to enable the use of Go language server'
					);
				});
			} else if (selected === disableLabel) {
				const goConfig = getGoConfig();
				const inspectLanguageServerSetting = goConfig.inspect('useLanguageServer');
				if (inspectLanguageServerSetting.globalValue === true) {
					goConfig.update('useLanguageServer', false, vscode.ConfigurationTarget.Global);
				} else if (inspectLanguageServerSetting.workspaceFolderValue === true) {
					goConfig.update('useLanguageServer', false, vscode.ConfigurationTarget.WorkspaceFolder);
				}
			}
		});
	}
}

function getMissingTools(goVersion: GoVersion): Promise<Tool[]> {
	const keys = getConfiguredTools(goVersion);
	return Promise.all<Tool>(
		keys.map(
			(tool) =>
				new Promise<Tool>((resolve, reject) => {
					const toolPath = getBinPath(tool.name);
					fs.exists(toolPath, (exists) => {
						resolve(exists ? null : tool);
					});
				})
		)
	).then((res) => {
		return res.filter((x) => x != null);
	});
}
