/*---------------------------------------------------------
 * Copyright 2022 The Go Authors. All rights reserved.
 * Licensed under the MIT License. See LICENSE in the project root for license information.
 *--------------------------------------------------------*/
import path = require('path');
import vscode = require('vscode');
import { URI } from 'vscode-uri';
import { getGoConfig } from './config';

function moduleVersion(mod: string, ver: string | undefined) {
	if (!ver) {
		return 'N/A';
	}
	if (mod === 'stdlib') {
		return `go${ver.replace(/^(v|go)/, '')}`;
	}
	return `${mod}@${ver}`;
}

// writeVulns generates human-readable vulnerability report from the VulncheckReport
// and write to the outputChannel.
export function writeVulns(
	res: VulncheckReport | undefined | null,
	outputChannel: { appendLine(value: string): void }
) {
	outputChannel.appendLine('');

	if (!res) {
		outputChannel.appendLine('Error - invalid vulncheck result.'); // TODO(hyangah): ask to open an issue.
		return;
	}
	if (!res.Vulns || res.Vulns.length === 0) {
		outputChannel.appendLine('No vulnerability found.');
		return;
	}

	const affecting = res.Vulns.filter((v) => {
		return v.Modules?.some((m) => {
			return m.Packages?.some((p) => {
				return p.CallStacks?.some((cs) => {
					return cs.Frames && cs.Frames.length > 0;
				});
			});
		});
	});
	const unaffecting = res.Vulns.filter((v) => !affecting.includes(v));

	switch (affecting.length) {
		case 0:
			outputChannel.appendLine('No vulnerability found.');
			break;
		case 1:
			outputChannel.appendLine(`Found ${affecting.length} affecting vulnerability.`);
			outputChannel.appendLine('-'.repeat(80));
			break;
		default:
			outputChannel.appendLine(`Found ${affecting.length} affecting vulnerabilities.`);
			outputChannel.appendLine('-'.repeat(80));
			break;
	}

	affecting.forEach((vuln) => {
		outputChannel.appendLine(`⚠ ${vuln.OSV.id} (https://pkg.go.dev/vuln/${vuln.OSV.id})`);
		const desc = (vuln.OSV.details || '').trimRight();
		const aliases = vuln.OSV.aliases?.length ? ` (${vuln.OSV.aliases.join(', ')})` : '';
		outputChannel.appendLine(`\n${desc}${aliases}\n`);
		vuln.Modules?.forEach((mod) => {
			outputChannel.appendLine(`Found Version: ${moduleVersion(mod.Path, mod.FoundVersion)}`);
			outputChannel.appendLine(`Fixed Version: ${moduleVersion(mod.Path, mod.FixedVersion)}`);
			mod.Packages?.forEach((pkg) => {
				outputChannel.appendLine('\nCall stacks in your code:');
				pkg.CallStacks?.forEach((cs, index) => {
					// TODO: the position info embedded in the cs.Summary is relative to
					// the directory gopls ran the vulnchek.
					// Instead replace with workspace-relative paths.
					outputChannel.appendLine(`- ${cs.Summary}`);
					// Print the first trace (index === 0) as an example.
					// TODO(hyangah): allow users to see example traces for all detected vulnerable symbols.
					if (index === 0 && cs.Frames) {
						const last = cs.Frames.length - 1;
						cs.Frames?.forEach((f, index) => {
							// Skip the last frame that just carries the vulnerable symbol.
							// This info is already included in cs.Summary.
							if (last === index) return;
							const line = f.Position?.Line || 1;
							// TODO: shorten f.Position.Filename (e.g. workspace relative path, and home directory ~ relative path)
							const pos = f.Position?.Filename ? `${f.Position.Filename}:${line}` : ' - ';
							const name = f.RecvType ? `${f.RecvType}.${f.FuncName}` : `${f.PkgPath}.${f.FuncName}`;
							outputChannel.appendLine(`\t${name}\n\t\t(${pos})`);
						});
					}
				});
			});
		});
		outputChannel.appendLine('-'.repeat(80));
	});

	if (unaffecting.length) {
		outputChannel.appendLine(`
# The vulnerabilities below are in packages that you import, but your code does
# not appear to call any vulnerable functions. You may not need to take any
# action. See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck for details.
`);

		switch (unaffecting.length) {
			case 1:
				outputChannel.appendLine(`Found ${unaffecting.length} unused vulnerability.`);
				break;
			default:
				outputChannel.appendLine(`Found ${unaffecting.length} unused vulnerabilities.`);
				break;
		}
		outputChannel.appendLine('-'.repeat(80));
	}

	unaffecting.forEach((vuln) => {
		outputChannel.appendLine(`ⓘ ${vuln.OSV.id} (https://pkg.go.dev/vuln/${vuln.OSV.id})`);
		const desc = (vuln.OSV.details || '').trimRight();
		const aliases = vuln.OSV.aliases?.length ? ` (${vuln.OSV.aliases.join(', ')})` : '';
		outputChannel.appendLine(`\n${desc}${aliases}\n`);
		vuln.Modules?.forEach((mod) => {
			outputChannel.appendLine(`Found Version: ${moduleVersion(mod.Path, mod.FoundVersion)}`);
			outputChannel.appendLine(`Fixed Version: ${moduleVersion(mod.Path, mod.FixedVersion)}`);
			mod.Packages?.forEach((pkg) => {
				outputChannel.appendLine(`Package: ${pkg.Path}`);
			});
		});
		outputChannel.appendLine('-'.repeat(80));
	});
}

// VulncheckReport is the JSON data type of gopls's vulncheck result.
export interface VulncheckReport {
	// Vulns populated by gopls vulncheck run.
	Vulns?: Vuln[];

	Mode?: 'govulncheck' | 'imports';
}

// Vuln represents a single OSV entry.
interface Vuln {
	// OSV contains all data from the OSV entry for this vulnerability.
	OSV: OSVEntry;

	// Modules contains all of the modules in the OSV entry where a
	// vulnerable package is imported by the target source code or binary.
	//
	// For example, a module M with two packages M/p1 and M/p2, where only p1
	// is vulnerable, will appear in this list if and only if p1 is imported by
	// the target source code or binary.
	Modules: Module[];

	AffectedPackages?: string[];
}

interface OSVEntry {
	id: string;
	published?: string;
	aliases?: string[];
	details?: string;
	affected?: Affected[];
}

interface Affected {
	package: Package;
	ecosystem_specific?: EcosystemSpecific;
}

interface EcosystemSpecificImport {
	path: string;
	goos?: string[];
	goarch?: string[];
	symbols?: string[];
}

interface EcosystemSpecific {
	imports?: EcosystemSpecificImport[];
}

interface Package {
	name: string;
}

interface Module {
	// Path is the module path of the module containing the vulnerability.
	//
	// Importable packages in the standard library will have the path "stdlib".
	Path: string;

	// FoundVersion is the module version where the vulnerability was found.
	FoundVersion?: string;

	// FixedVersion is the module version where the vulnerability was
	// fixed. If there are multiple fixed versions in the OSV report, this will
	// be the latest fixed version.
	//
	// This is empty if a fix is not available.
	FixedVersion?: string;

	// Packages contains all the vulnerable packages in OSV entry that are
	// imported by the target source code or binary.
	//
	// For example, given a module M with two packages M/p1 and M/p2, where
	// both p1 and p2 are vulnerable, p1 and p2 will each only appear in this
	// list they are individually imported by the target source code or binary.
	Packages?: Package[];
}

interface Package {
	// Path is the import path of the package containing the vulnerability.
	Path: string;

	// CallStacks contains a representative call stack for each
	// vulnerable symbol that is called.
	//
	// For vulnerabilities found from binary analysis, only CallStack.Symbol
	// will be provided.
	//
	// For non-affecting vulnerabilities reported from the source mode
	// analysis, this will be empty.
	CallStacks?: CallStack[];
}

interface CallStack {
	// Symbol is the name of the detected vulnerable function
	// or method.
	//
	// This follows the naming convention in the OSV report.
	Symbol?: string;

	// Summary is a one-line description of the callstack, used by the
	// default govulncheck mode.
	//
	// Example: module3.main calls github.com/shiyanhui/dht.DHT.Run
	Summary?: string;

	// Frames contains an entry for each stack in the call stack.
	//
	// Frames are sorted starting from the entry point to the
	// imported vulnerable symbol. The last frame in Frames should match
	// Symbol.
	Frames?: StackFrame[];
}

interface StackFrame {
	// PackagePath is the import path.
	PkgPath: string;

	// FuncName is the function name.
	FuncName?: string;

	// RecvType is the fully qualified receiver type,
	// if the called symbol is a method.
	//
	// The client can create the final symbol name by
	// prepending RecvType to FuncName.
	RecvType?: string;

	// Position describes an arbitrary source position
	// including the file, line, and column location.
	// A Position is valid if the line number is > 0.
	Position?: Position;
}

interface Position {
	Filename?: string; // filename, if any
	Offset?: number; // offset, starting at 0
	Line?: number; // line number, starting at 1
	Column?: number; // column number, starting at 1 (byte count)
}

// VulncheckOutputLinkProvider linkifies govulncheck output.
export class VulncheckOutputLinkProvider implements vscode.DocumentLinkProvider {
	static activate(ctx: Pick<vscode.ExtensionContext, 'subscriptions'>) {
		ctx.subscriptions.push(
			vscode.languages.registerDocumentLinkProvider(
				{ language: 'govulncheck' },
				new VulncheckOutputLinkProvider()
			)
		);
	}

	provideDocumentLinks(
		document: vscode.TextDocument,
		// eslint-disable-next-line @typescript-eslint/no-unused-vars
		_token: vscode.CancellationToken
	): vscode.ProviderResult<vscode.DocumentLink[]> {
		try {
			return this.unsafeProvideDocumentLinks(document);
		} catch (e) {
			console.log(`failed to linkify govulncheck output result: ${e}`);
		}
		return [];
	}

	unsafeProvideDocumentLinks(document: vscode.TextDocument): vscode.ProviderResult<vscode.DocumentLink[]> {
		const ret = [] as vscode.DocumentLink[];
		let cwd = '';
		for (let i = 0; i < document.lineCount; i++) {
			const readLine = document.lineAt(i);

			// govulncheck ./... for file:///foo/go.mod.
			const cmdPattern = readLine.text.match(/^govulncheck\s+\S+\s+for\s+(file:.*\.mod)/);
			if (cmdPattern && cmdPattern[1]) {
				cwd = path.dirname(vscode.Uri.parse(cmdPattern[1]).fsPath);
				continue;
			}

			// Found Version: and Fixed Version:
			const foundOrFixedVersionPattern = readLine.text.match(/^(?:Found|Fixed) Version:\s+(\S+@\S+)$/);
			if (foundOrFixedVersionPattern && foundOrFixedVersionPattern[1]) {
				const modVersion = foundOrFixedVersionPattern[1];
				const start = readLine.text.indexOf(modVersion);
				const end = start + modVersion.length;
				const link = new vscode.DocumentLink(
					new vscode.Range(i, start, i, end),
					vscode.Uri.parse(`https://pkg.go.dev/${modVersion}`)
				);
				link.tooltip = `https://pkg.go.dev/${modVersion}`;
				ret.push(link);
				continue;
			}

			// Position at file (e.g. file.go:1:2)
			const filePosPattern = readLine.text.match(/(?:-\s+|\s+\()(\S+\.go):(\d+)(?::(\d+)){0,1}/);
			if (filePosPattern && filePosPattern[1]) {
				let fname = filePosPattern[1];
				if (!path.isAbsolute(fname)) {
					fname = path.join(cwd, fname);
				}
				if (path.isAbsolute(fname)) {
					const line = filePosPattern[2];
					const col = filePosPattern[3];
					const fragment = col ? { fragment: `L${line},${col}` } : { fragment: `L${line}` };
					const uri = URI.file(fname).with(fragment);
					const start = readLine.text.indexOf(filePosPattern[1]);
					const end = readLine.text.indexOf(filePosPattern[0]) + filePosPattern[0].length;
					const link = new vscode.DocumentLink(new vscode.Range(i, start, i, end), uri);
					ret.push(link);
				}
				continue;
			}
		}
		return ret;
	}
}

export const toggleVulncheckCommandFactory = () => () => {
	const editor = vscode.window.activeTextEditor;
	const documentUri = editor?.document.uri;
	toggleVulncheckCommand(documentUri);
};

function toggleVulncheckCommand(uri?: URI) {
	const goCfgName = 'diagnostic.vulncheck';
	const cfg = getGoConfig(uri);
	const { globalValue, workspaceValue, workspaceFolderValue } = cfg.inspect(goCfgName) || {};
	if (workspaceFolderValue) {
		const newValue = workspaceFolderValue === 'Imports' ? 'Off' : 'Imports';
		cfg.update(goCfgName, newValue);
		return;
	}
	if (workspaceValue) {
		const newValue = workspaceValue === 'Imports' ? 'Off' : 'Imports';
		cfg.update(goCfgName, newValue, false);
		return;
	}
	if (globalValue) {
		const newValue = globalValue === 'Imports' ? 'Off' : 'Imports';
		cfg.update(goCfgName, newValue, true);
		return;
	}
	cfg.update(goCfgName, 'Imports');
}
