/*---------------------------------------------------------
 * Copyright 2022 The Go Authors. All rights reserved.
 * Licensed under the MIT License. See LICENSE in the project root for license information.
 *--------------------------------------------------------*/

import path from 'path';
import fs from 'fs';
import * as vscode from 'vscode';
import { GoExtensionContext } from './context';
import { getBinPath } from './util';
import * as cp from 'child_process';
import { toolExecutionEnvironment } from './goEnv';
import { killProcessTree } from './utils/processUtils';
import * as readline from 'readline';
import { URI } from 'vscode-uri';
import { promisify } from 'util';
import { runGoEnv } from './goModules';
import { ExecuteCommandParams, ExecuteCommandRequest } from 'vscode-languageserver-protocol';

export class VulncheckResultViewProvider implements vscode.CustomTextEditorProvider {
	public static readonly viewType = 'vulncheck.view';

	public static register(
		{ extensionUri, subscriptions }: vscode.ExtensionContext,
		goCtx: GoExtensionContext
	): VulncheckResultViewProvider {
		const provider = new VulncheckResultViewProvider(extensionUri, goCtx);
		subscriptions.push(vscode.window.registerCustomEditorProvider(VulncheckResultViewProvider.viewType, provider));
		return provider;
	}

	constructor(private readonly extensionUri: vscode.Uri, private readonly goCtx: GoExtensionContext) {}

	/**
	 * Called when our custom editor is opened.
	 */
	public async resolveCustomTextEditor(
		document: vscode.TextDocument,
		webviewPanel: vscode.WebviewPanel,
		_: vscode.CancellationToken // eslint-disable-line @typescript-eslint/no-unused-vars
	): Promise<void> {
		// Setup initial content for the webview
		webviewPanel.webview.options = { enableScripts: true };
		webviewPanel.webview.html = this.getHtmlForWebview(webviewPanel.webview);

		// Receive message from the webview.
		webviewPanel.webview.onDidReceiveMessage(this.handleMessage, this);

		function updateWebview() {
			webviewPanel.webview.postMessage({ type: 'update', text: document.getText() });
		}

		// Hook up event handlers so that we can synchronize the webview with the text document.
		//
		// The text document acts as our model, so we have to sync change in the document to our
		// editor and sync changes in the editor back to the document.
		//
		// Remember that a single text document can also be shared between multiple custom
		// editors (this happens for example when you split a custom editor)
		const changeDocumentSubscription = vscode.workspace.onDidChangeTextDocument((e) => {
			if (e.document.uri.toString() === document.uri.toString()) {
				updateWebview();
			}
		});

		// Make sure we get rid of the listener when our editor is closed.
		webviewPanel.onDidDispose(() => {
			changeDocumentSubscription.dispose();
		});

		updateWebview();
	}

	/**
	 * Get the static html used for the editor webviews.
	 */
	private getHtmlForWebview(webview: vscode.Webview): string {
		const mediaUri = vscode.Uri.joinPath(this.extensionUri, 'media');
		// Local path to script and css for the webview
		const scriptUri = webview.asWebviewUri(vscode.Uri.joinPath(mediaUri, 'vulncheckView.js'));
		const styleResetUri = webview.asWebviewUri(vscode.Uri.joinPath(mediaUri, 'reset.css'));
		const styleVSCodeUri = webview.asWebviewUri(vscode.Uri.joinPath(mediaUri, 'vscode.css'));
		const styleMainUri = webview.asWebviewUri(vscode.Uri.joinPath(mediaUri, 'vulncheckView.css'));

		// Use a nonce to whitelist which scripts can be run
		const nonce = getNonce();

		return /* html */ `
			<!DOCTYPE html>
			<html lang="en">
			<head>
				<meta charset="UTF-8">
				<!--
				Use a content security policy to only allow loading images from https or from our extension directory,
				and only allow scripts that have a specific nonce.
				-->
				<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src ${webview.cspSource}; style-src ${webview.cspSource}; script-src 'nonce-${nonce}';">
				<meta name="viewport" content="width=device-width, initial-scale=1.0">
				<link href="${styleResetUri}" rel="stylesheet" />
				<link href="${styleVSCodeUri}" rel="stylesheet" />
				<link href="${styleMainUri}" rel="stylesheet" />
				<title>Vulnerability Report - govulncheck</title>
			</head>
			<body>
				<div class="log"></div>
				<div class="vulns"></div>
				<div class="unaffecting"></div>
				<script nonce="${nonce}" src="${scriptUri}"></script>
			</body>
			</html>`;
	}

	private async handleMessage(e: { type: string; target?: string; dir?: string }): Promise<void> {
		switch (e.type) {
			case 'open':
				{
					if (!e.target) return;
					const uri = safeURIParse(e.target);
					if (!uri || !uri.scheme) return;
					if (uri.scheme === 'https') {
						vscode.env.openExternal(uri);
					} else if (uri.scheme === 'file') {
						const line = uri.query ? Number(uri.query.split(':')[0]) : undefined;
						const range = line ? new vscode.Range(line, 0, line, 0) : undefined;
						vscode.window.showTextDocument(
							vscode.Uri.from({ scheme: uri.scheme, path: uri.path }),
							// prefer the first column to present the source.
							{ viewColumn: vscode.ViewColumn.One, selection: range }
						);
					}
				}
				return;
			case 'fix':
				{
					if (!e.target || !e.dir) return;
					const modFile = await getGoModFile(vscode.Uri.file(e.dir));
					if (modFile) {
						await goplsUpgradeDependency(this.goCtx, vscode.Uri.file(modFile), [e.target], false);
						// TODO: run go mod tidy?
					}
				}
				return;
			case 'snapshot-result':
				// response for `snapshot-request`.
				return;
			default:
				console.log(`unrecognized type message: ${e.type}`);
		}
	}
}

const GOPLS_UPGRADE_DEPENDENCY = 'gopls.upgrade_dependency';
async function goplsUpgradeDependency(
	goCtx: GoExtensionContext,
	goModFileUri: vscode.Uri,
	goCmdArgs: string[],
	addRequire: boolean
): Promise<void> {
	const { languageClient } = goCtx;
	const uri = languageClient?.code2ProtocolConverter.asUri(goModFileUri);
	const params: ExecuteCommandParams = {
		command: GOPLS_UPGRADE_DEPENDENCY,
		arguments: [
			{
				URI: uri,
				GoCmdArgs: goCmdArgs,
				AddRequire: addRequire
			}
		]
	};
	return await languageClient?.sendRequest(ExecuteCommandRequest.type, params);
}

async function getGoModFile(dir: vscode.Uri): Promise<string | undefined> {
	try {
		const p = await runGoEnv(dir, ['GOMOD']);
		return p['GOMOD'] === '/dev/null' || p['GOMOD'] === 'NUL' ? '' : p['GOMOD'];
	} catch (e) {
		vscode.window.showErrorMessage(`Failed to find 'go.mod' for ${dir}: ${e}`);
	}
	return;
}

export class VulncheckProvider {
	static scheme = 'govulncheck';
	static setup({ subscriptions }: vscode.ExtensionContext, goCtx: GoExtensionContext) {
		const channel = vscode.window.createOutputChannel('govulncheck');
		const instance = new this(channel);
		subscriptions.push(
			vscode.commands.registerCommand('go.vulncheck.run', async () => {
				instance.run(goCtx);
			})
		);
		return instance;
	}

	constructor(private channel: vscode.OutputChannel) {}

	private running = false;

	async run(goCtx: GoExtensionContext) {
		if (this.running) {
			vscode.window.showWarningMessage('another vulncheck is in progress');
			return;
		}
		try {
			this.running = true;
			await this.runInternal(goCtx);
		} finally {
			this.running = false;
		}
	}

	private async runInternal(goCtx: GoExtensionContext) {
		const pick = await vscode.window.showQuickPick(['Current Package', 'Workspace']);
		let dir, pattern: string;
		const document = vscode.window.activeTextEditor?.document;
		switch (pick) {
			case 'Current Package':
				if (!document) {
					vscode.window.showErrorMessage('vulncheck error: no current package');
					return;
				}
				if (document.languageId !== 'go') {
					vscode.window.showErrorMessage(
						'File in the active editor is not a Go file, cannot find current package to check.'
					);
					return;
				}
				dir = path.dirname(document.fileName);
				pattern = '.';
				break;
			case 'Workspace':
				dir = await this.activeDir();
				pattern = './...';
				break;
			default:
				return;
		}
		if (!dir) {
			return;
		}

		this.channel.clear();
		this.channel.appendLine(`cd ${dir}; gopls vulncheck ${pattern}`);

		try {
			const start = new Date();
			const vuln = await vulncheck(goCtx, dir, pattern, this.channel);

			if (vuln?.Vuln?.length) {
				fillAffectedPkgs(vuln.Vuln);

				// record run info.
				vuln.Start = start;
				vuln.Duration = Date.now() - start.getTime();
				vuln.Dir = dir;
				vuln.Pattern = pattern;

				// write to file and visualize it!
				const fname = path.join(dir, `vulncheck-${Date.now()}.vulncheck.json`);
				const writeFile = promisify(fs.writeFile);
				await writeFile(fname, JSON.stringify(vuln));
				const uri = URI.file(fname);
				const viewColumn = vscode.ViewColumn.Beside;
				vscode.commands.executeCommand(
					'vscode.openWith',
					uri,
					VulncheckResultViewProvider.viewType,
					viewColumn
				);
				this.channel.appendLine(`Vulncheck - result written in ${fname}`);
			} else {
				this.channel.appendLine('Vulncheck - found no vulnerability');
			}
		} catch (e) {
			vscode.window.showErrorMessage(`error running vulncheck: ${e}`);
			this.channel.appendLine(`Vulncheck failed: ${e}`);
		}
		this.channel.show();
	}

	private async activeDir() {
		const folders = vscode.workspace.workspaceFolders;
		if (!folders || folders.length === 0) return;
		let dir: string | undefined = '';
		if (folders.length === 1) {
			dir = folders[0].uri.path;
		} else {
			const pick = await vscode.window.showQuickPick(
				folders.map((f) => ({ label: f.name, description: f.uri.path }))
			);
			dir = pick?.description;
		}
		return dir;
	}
}

// run `gopls vulncheck`.
export async function vulncheck(
	goCtx: GoExtensionContext,
	dir: string,
	pattern = './...',
	channel: { appendLine: (msg: string) => void }
): Promise<VulncheckReport> {
	const { languageClient, serverInfo } = goCtx;
	const COMMAND = 'gopls.run_vulncheck_exp';
	if (!languageClient || !serverInfo?.Commands?.includes(COMMAND)) {
		throw Promise.reject('this feature requires gopls v0.8.4 or newer');
	}
	// TODO: read back the actual package configuration from gopls.
	const gopls = getBinPath('gopls');
	const options: vscode.ProgressOptions = {
		cancellable: true,
		title: 'Run govulncheck',
		location: vscode.ProgressLocation.Notification
	};
	const task = vscode.window.withProgress<VulncheckReport>(options, (progress, token) => {
		const p = cp.spawn(gopls, ['vulncheck', pattern], {
			cwd: dir,
			env: toolExecutionEnvironment(vscode.Uri.file(dir))
		});

		progress.report({ message: `starting command ${gopls} from ${dir}  (pid; ${p.pid})` });

		const d = token.onCancellationRequested(() => {
			channel.appendLine(`gopls vulncheck (pid: ${p.pid}) is cancelled`);
			killProcessTree(p);
			d.dispose();
		});

		const promise = new Promise<VulncheckReport>((resolve, reject) => {
			const rl = readline.createInterface({ input: p.stderr });
			rl.on('line', (line) => {
				channel.appendLine(line);
				const msg = line.match(/^\d+\/\d+\/\d+\s+\d+:\d+:\d+\s+(.*)/);
				if (msg && msg[1]) {
					progress.report({ message: msg[1] });
				}
			});

			let buf = '';
			p.stdout.on('data', (chunk) => {
				buf += chunk;
			});
			p.stdout.on('close', () => {
				try {
					const res: VulncheckReport = JSON.parse(buf);
					resolve(res);
				} catch (e) {
					if (token.isCancellationRequested) {
						reject('analysis cancelled');
					} else {
						channel.appendLine(buf);
						reject(`result in unexpected format: ${e}`);
					}
				}
			});
		});
		return promise;
	});
	return await task;
}

interface VulncheckReport {
	// Vulns populated by gopls vulncheck run.
	Vuln?: Vuln[];

	// analysis run information.
	Pattern?: string;
	Dir?: string;

	Start?: Date;
	Duration?: number; // milliseconds
}

interface Vuln {
	ID: string;
	Details: string;
	Aliases: string[];
	Symbol: string;
	PkgPath: string;
	ModPath: string;
	URL: string;
	CurrentVersion: string;
	FixedVersion: string;
	CallStacks?: CallStack[][];
	CallStacksSummary?: string[];

	// Derived from call stacks.
	// TODO(hyangah): add to gopls vulncheck.
	AffectedPkgs?: string[];
}

interface CallStack {
	Name: string;
	URI: string;
	Pos: {
		line: number;
		character: number;
	};
}

function getNonce() {
	let text = '';
	const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
	for (let i = 0; i < 32; i++) {
		text += possible.charAt(Math.floor(Math.random() * possible.length));
	}
	return text;
}

function safeURIParse(s: string): URI | undefined {
	try {
		return URI.parse(s);
	} catch (_) {
		return undefined;
	}
}

// Computes the AffectedPkgs attribute if it's not present.
// Exported for testing.
// TODO(hyangah): move this logic to gopls vulncheck or govulncheck.
export function fillAffectedPkgs(vulns: Vuln[] | undefined): Vuln[] {
	if (!vulns) return [];

	const re = new RegExp(/^(\S+)\/([^/\s]+)$/);
	vulns.forEach((vuln) => {
		// If it's already set by gopls vulncheck, great!
		if (vuln.AffectedPkgs) return;

		const affected = new Set<string>();
		vuln.CallStacks?.forEach((cs) => {
			if (!cs || cs.length === 0) {
				return;
			}
			const name = cs[0].Name || '';
			const m = name.match(re);
			if (!m) {
				name && affected.add(name);
			} else {
				const pkg = m[2] && m[2].split('.')[0];
				affected.add(`${m[1]}/${pkg}`);
			}
		});
		vuln.AffectedPkgs = Array.from(affected);
	});
	return vulns;
}
