/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/no-explicit-any */
/*---------------------------------------------------------
 * Copyright (C) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See LICENSE in the project root for license information.
 *--------------------------------------------------------*/

'use strict';

import vscode = require('vscode');
import { CancellationToken, CodeLens, TextDocument } from 'vscode';
import { getGoConfig } from './config';
import { GoBaseCodeLensProvider } from './goBaseCodelens';
import { GoDocumentSymbolProvider } from './goDocumentSymbols';
import { getBenchmarkFunctions, getTestFunctions } from './testUtils';
import { GoExtensionContext } from './context';
import { GO_MODE } from './goMode';

export class GoRunTestCodeLensProvider extends GoBaseCodeLensProvider {
	static activate(ctx: vscode.ExtensionContext, goCtx: GoExtensionContext) {
		const testCodeLensProvider = new this(goCtx);
		ctx.subscriptions.push(vscode.languages.registerCodeLensProvider(GO_MODE, testCodeLensProvider));
		ctx.subscriptions.push(
			vscode.workspace.onDidChangeConfiguration(async (e: vscode.ConfigurationChangeEvent) => {
				if (!e.affectsConfiguration('go')) {
					return;
				}
				const updatedGoConfig = getGoConfig();
				if (updatedGoConfig['enableCodeLens']) {
					testCodeLensProvider.setEnabled(updatedGoConfig['enableCodeLens']['runtest']);
				}
			})
		);
	}

	constructor(private readonly goCtx: GoExtensionContext) {
		super();
	}

	private readonly benchmarkRegex = /^Benchmark.+/;

	public async provideCodeLenses(document: TextDocument, token: CancellationToken): Promise<CodeLens[]> {
		if (!this.enabled) {
			return [];
		}
		const config = getGoConfig(document.uri);
		const codeLensConfig = config.get<{ [key: string]: any }>('enableCodeLens');
		const codelensEnabled = codeLensConfig ? codeLensConfig['runtest'] : false;
		if (!codelensEnabled || !document.fileName.endsWith('_test.go')) {
			return [];
		}

		const codelenses = await Promise.all([
			this.getCodeLensForPackage(document, token),
			this.getCodeLensForFunctions(document, token)
		]);
		return ([] as CodeLens[]).concat(...codelenses);
	}

	private async getCodeLensForPackage(document: TextDocument, token: CancellationToken): Promise<CodeLens[]> {
		const documentSymbolProvider = GoDocumentSymbolProvider(this.goCtx);
		const symbols = await documentSymbolProvider.provideDocumentSymbols(document);
		if (!symbols || symbols.length === 0) {
			return [];
		}
		const pkg = symbols[0];
		if (!pkg) {
			return [];
		}
		const range = pkg.range;
		const packageCodeLens = [
			new CodeLens(range, {
				title: 'run package tests',
				command: 'go.test.package'
			}),
			new CodeLens(range, {
				title: 'run file tests',
				command: 'go.test.file'
			})
		];
		if (pkg.children.some((sym) => sym.kind === vscode.SymbolKind.Function && this.benchmarkRegex.test(sym.name))) {
			packageCodeLens.push(
				new CodeLens(range, {
					title: 'run package benchmarks',
					command: 'go.benchmark.package'
				}),
				new CodeLens(range, {
					title: 'run file benchmarks',
					command: 'go.benchmark.file'
				})
			);
		}
		return packageCodeLens;
	}

	private async getCodeLensForFunctions(document: TextDocument, token: CancellationToken): Promise<CodeLens[]> {
		const testPromise = async (): Promise<CodeLens[]> => {
			const codelens: CodeLens[] = [];

			const testFunctions = await getTestFunctions(this.goCtx, document, token);
			if (!testFunctions) {
				return codelens;
			}

			const simpleRunRegex = /t.Run\("([^"]+)",/;

			for (const f of testFunctions) {
				const functionName = f.name;

				codelens.push(
					new CodeLens(f.range, {
						title: 'run test',
						command: 'go.test.cursor',
						arguments: [{ functionName }]
					}),
					new CodeLens(f.range, {
						title: 'debug test',
						command: 'go.debug.cursor',
						arguments: [{ functionName }]
					})
				);

				for (let i = f.range.start.line; i < f.range.end.line; i++) {
					const line = document.lineAt(i);
					const simpleMatch = line.text.match(simpleRunRegex);

					// BUG: this does not handle nested subtests. This should
					// be solved once codelens is handled by gopls and not by
					// vscode.
					if (simpleMatch) {
						const subTestName = simpleMatch[1];

						codelens.push(
							new CodeLens(line.range, {
								title: 'run test',
								command: 'go.subtest.cursor',
								arguments: [{ functionName, subTestName }]
							}),
							new CodeLens(line.range, {
								title: 'debug test',
								command: 'go.debug.subtest.cursor',
								arguments: [{ functionName, subTestName }]
							})
						);
					}
				}
			}

			return codelens;
		};

		const benchmarkPromise = async (): Promise<CodeLens[]> => {
			const benchmarkFunctions = await getBenchmarkFunctions(this.goCtx, document, token);
			if (!benchmarkFunctions) {
				return [];
			}
			const codelens: CodeLens[] = [];
			for (const f of benchmarkFunctions) {
				codelens.push(
					new CodeLens(f.range, {
						title: 'run benchmark',
						command: 'go.benchmark.cursor',
						arguments: [{ functionName: f.name }]
					})
				);
				codelens.push(
					new CodeLens(f.range, {
						title: 'debug benchmark',
						command: 'go.debug.cursor',
						arguments: [{ functionName: f.name }]
					})
				);
			}
			return codelens;
		};

		const codelenses = await Promise.all([testPromise(), benchmarkPromise()]);
		return ([] as CodeLens[]).concat(...codelenses);
	}
}
