/*---------------------------------------------------------
 * Copyright (C) Microsoft Corporation. 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 { CommandFactory } from '../commands';
import { getGoConfig } from '../config';
import { toolExecutionEnvironment } from '../goEnv';
import { diagnosticsStatusBarItem, outputChannel } from '../goStatus';
import { inspectGoToolVersion } from '../goInstallTools';
import { getBinPath, getWorkspaceFolderPath, resolvePath } from '../util';
import { handleErrors, ICheckResult, runTool } from './diagnostics';

/**
 * Runs linter on the current file, package or workspace.
 */
export function lintCode(scope?: string): CommandFactory {
	return (ctx, goCtx) => () => {
		const editor = vscode.window.activeTextEditor;
		if (scope !== 'workspace') {
			if (!editor) {
				vscode.window.showInformationMessage('No editor is active, cannot find current package to lint');
				return;
			}
			if (editor.document.languageId !== 'go') {
				vscode.window.showInformationMessage(
					'File in the active editor is not a Go file, cannot find current package to lint'
				);
				return;
			}
		}

		const documentUri = editor ? editor.document.uri : undefined;
		const goConfig = getGoConfig(documentUri);

		outputChannel.info('Linting...');
		diagnosticsStatusBarItem.show();
		diagnosticsStatusBarItem.text = 'Linting...';

		goLint(documentUri, goConfig, scope)
			.then((warnings) => {
				handleErrors(goCtx, editor ? editor.document : undefined, warnings, goCtx.lintDiagnosticCollection);
				diagnosticsStatusBarItem.hide();
			})
			.catch((err) => {
				vscode.window.showInformationMessage('Error: ' + err);
				diagnosticsStatusBarItem.text = 'Linting Failed';
			});
	};
}

/**
 * Runs linter and presents the output in the 'Go' channel and in the diagnostic
 * collections.
 *
 * @param fileUri Document uri.
 * @param goConfig Configuration for the Go extension.
 * @param scope Scope in which to run the linter.
 */
export async function goLint(
	fileUri: vscode.Uri | undefined,
	goConfig: vscode.WorkspaceConfiguration,
	scope?: string
): Promise<ICheckResult[]> {
	const linter = goConfig.get<string>('lintTool');
	if (linter === undefined || linter === '') {
		// Yield the linter functionality to gopls by returning empty.
		return Promise.resolve([]);
	}

	epoch++;
	const closureEpoch = epoch;
	if (tokenSource) {
		if (running) {
			tokenSource.cancel();
		}
		tokenSource.dispose();
	}
	tokenSource = new vscode.CancellationTokenSource();

	const currentWorkspace = getWorkspaceFolderPath(fileUri);

	const cwd = scope === 'workspace' && currentWorkspace ? currentWorkspace : path.dirname(fileUri?.fsPath ?? '');

	if (!path.isAbsolute(cwd)) {
		return Promise.resolve([]);
	}

	const lintFlags = goConfig.get<string[]>('lintFlags') === undefined ? [] : goConfig.get<string[]>('lintFlags')!;
	const lintEnv = toolExecutionEnvironment();
	const args: string[] = [];

	lintFlags.forEach((flag) => {
		// --json is not a valid flag for golint and in gometalinter, it is used to print output in json which we dont want
		if (flag === '--json') {
			return;
		}
		if (flag.startsWith('--config=') || flag.startsWith('-config=')) {
			let configFilePath = flag.substring(flag.indexOf('=') + 1).trim();
			if (!configFilePath) {
				return;
			}
			configFilePath = resolvePath(configFilePath);
			args.push(`${flag.substring(0, flag.indexOf('=') + 1)}${configFilePath}`);
			return;
		}
		args.push(flag);
	});
	if (linter.startsWith('golangci-lint')) {
		let version: number;
		if (linter === 'golangci-lint-v2') {
			version = 2;
		} else {
			const { moduleVersion } = await inspectGoToolVersion(getBinPath(linter));
			// if moduleVersion is undefined, treat it as version=1
			// if moduleVersion is higher than v1 (v2, v3...), treat it as version=2
			version = !moduleVersion || moduleVersion.startsWith('v1') ? 1 : 2;
		}

		// append common flags
		if (args.indexOf('run') === -1) {
			args.unshift('run');
		}
		if (args.indexOf('--issues-exit-code=0') === -1) {
			// adds an explicit no-error-code return argument, to avoid npm error
			// message detection logic. See golang/vscode-go/issues/411
			args.push('--issues-exit-code=0');
		}
		switch (version) {
			case 1: // append golangci-lint v1 flags
				if (args.indexOf('--print-issued-lines=false') === -1) {
					// print only file:number:column
					args.push('--print-issued-lines=false');
				}
				if (args.indexOf('--out-format=line-number') === -1) {
					// print file:number:column.
					// Explicit override in case .golangci.yml calls for a format we don't understand
					args.push('--out-format=line-number');
				}
				break;

			case 2: // append golangci-lint v2 flags
				if (args.indexOf('--output.text.print-issued-lines=false') === -1) {
					// print only file:number:column
					args.push('--output.text.print-issued-lines=false');
				}
				if (args.indexOf('--show-stats=false') === -1) {
					// print only file:number:column
					args.push('--show-stats=false');
				}
				if (args.indexOf('--output.text.path=stdout') === -1) {
					// print file:number:column.
					// Explicit override in case .golangci.yml calls for a format we don't understand
					args.push('--output.text.path=stdout');
				}
				if (!args.some((v) => v.startsWith('--path-mode='))) {
					// print file name as absolute path
					args.push('--path-mode=abs');
				}
				break;
		}
	}

	if (scope === 'workspace' && currentWorkspace) {
		args.push('./...');
		outputChannel.info(`Starting linting the current workspace at ${currentWorkspace}`);
	} else if (scope === 'file') {
		args.push(fileUri?.fsPath ?? '');
		outputChannel.info(`Starting linting the current file at ${fileUri?.fsPath}`);
	} else {
		outputChannel.info(`Starting linting the current package at ${cwd}`);
	}

	running = true;
	const lintPromise = runTool(args, cwd, 'warning', false, linter, lintEnv, false, tokenSource.token).then(
		(result) => {
			if (closureEpoch === epoch) {
				running = false;
			}
			return result;
		}
	);

	return lintPromise;
}

let epoch = 0;
let tokenSource: vscode.CancellationTokenSource;
let running = false;
