/* 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 { isAbsolute } from 'path';
import { CancellationToken, CodeLens, Range, TextDocument } from 'vscode';
import { getGoConfig } from './config';
import { GoBaseCodeLensProvider } from './goBaseCodelens';
import { GoDocumentSymbolProvider } from './goOutline';
import { GoReferenceProvider } from './goReferences';
import { getBinPath } from './util';
import vscode = require('vscode');

const methodRegex = /^func\s+\(\s*\w+\s+\*?\w+\s*\)\s+/;

class ReferencesCodeLens extends CodeLens {
	constructor(public document: TextDocument, range: Range) {
		super(range);
	}
}

export class GoReferencesCodeLensProvider extends GoBaseCodeLensProvider {
	public provideCodeLenses(document: TextDocument, token: CancellationToken): CodeLens[] | Thenable<CodeLens[]> {
		if (!this.enabled) {
			return [];
		}
		const codeLensConfig = getGoConfig(document.uri).get<{ [key: string]: any }>('enableCodeLens');
		const codelensEnabled = codeLensConfig ? codeLensConfig['references'] : false;
		if (!codelensEnabled) {
			return Promise.resolve([]);
		}

		const goGuru = getBinPath('guru');
		if (!isAbsolute(goGuru)) {
			return Promise.resolve([]);
		}

		return this.provideDocumentSymbols(document, token).then((symbols) => {
			return symbols.map((symbol) => {
				let position = symbol.range.start;

				// Add offset for functions as go-outline returns position at the keyword func instead of func name
				if (symbol.kind === vscode.SymbolKind.Function) {
					const funcDecl = document.lineAt(position.line).text.substr(position.character);
					const match = methodRegex.exec(funcDecl);
					position = position.translate(0, match ? match[0].length : 5);
				}
				return new ReferencesCodeLens(document, new vscode.Range(position, position));
			});
		});
	}

	public resolveCodeLens?(inputCodeLens: CodeLens, token: CancellationToken): CodeLens | Thenable<CodeLens> {
		const codeLens = inputCodeLens as ReferencesCodeLens;

		if (token.isCancellationRequested) {
			return Promise.resolve(codeLens);
		}

		const options = {
			includeDeclaration: false
		};
		const referenceProvider = new GoReferenceProvider();
		return referenceProvider.provideReferences(codeLens.document, codeLens.range.start, options, token).then(
			(references) => {
				codeLens.command = {
					title: references.length === 1 ? '1 reference' : references.length + ' references',
					command: 'editor.action.showReferences',
					arguments: [codeLens.document.uri, codeLens.range.start, references]
				};
				return codeLens;
			},
			(err) => {
				console.log(err);
				codeLens.command = {
					title: 'Error finding references',
					command: ''
				};
				return codeLens;
			}
		);
	}

	private async provideDocumentSymbols(
		document: TextDocument,
		token: CancellationToken
	): Promise<vscode.DocumentSymbol[]> {
		const symbolProvider = new GoDocumentSymbolProvider();
		const isTestFile = document.fileName.endsWith('_test.go');
		const symbols = await symbolProvider.provideDocumentSymbols(document, token);
		return symbols[0].children.filter((symbol) => {
			if (symbol.kind === vscode.SymbolKind.Interface) {
				return true;
			}
			if (symbol.kind === vscode.SymbolKind.Function) {
				if (
					isTestFile &&
					(symbol.name.startsWith('Test') ||
						symbol.name.startsWith('Example') ||
						symbol.name.startsWith('Benchmark'))
				) {
					return false;
				}
				return true;
			}
			return false;
		});
	}
}
