/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See LICENSE in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

import {
	CancellationToken,
	ParameterInformation,
	Position,
	SignatureHelp,
	SignatureHelpProvider,
	SignatureInformation,
	TextDocument,
	WorkspaceConfiguration
} from 'vscode';
import { definitionLocation } from './goDeclaration';
import { getGoConfig, getParametersAndReturnType, isPositionInComment, isPositionInString } from './util';

export class GoSignatureHelpProvider implements SignatureHelpProvider {
	constructor(private goConfig?: WorkspaceConfiguration) {}

	public async provideSignatureHelp(
		document: TextDocument,
		position: Position,
		token: CancellationToken
	): Promise<SignatureHelp> {
		let goConfig = this.goConfig || getGoConfig(document.uri);

		const theCall = this.walkBackwardsToBeginningOfCall(document, position);
		if (theCall == null) {
			return Promise.resolve(null);
		}
		const callerPos = this.previousTokenPosition(document, theCall.openParen);
		// Temporary fix to fall back to godoc if guru is the set docsTool
		if (goConfig['docsTool'] === 'guru') {
			goConfig = Object.assign({}, goConfig, { docsTool: 'godoc' });
		}
		try {
			const res = await definitionLocation(document, callerPos, goConfig, true, token);
			if (!res) {
				// The definition was not found
				return null;
			}
			if (res.line === callerPos.line) {
				// This must be a function definition
				return null;
			}
			let declarationText: string = (res.declarationlines || []).join(' ').trim();
			if (!declarationText) {
				return null;
			}
			const result = new SignatureHelp();
			let sig: string;
			let si: SignatureInformation;
			if (res.toolUsed === 'godef') {
				// declaration is of the form "Add func(a int, b int) int"
				const nameEnd = declarationText.indexOf(' ');
				const sigStart = nameEnd + 5; // ' func'
				const funcName = declarationText.substring(0, nameEnd);
				sig = declarationText.substring(sigStart);
				si = new SignatureInformation(funcName + sig, res.doc);
			} else if (res.toolUsed === 'gogetdoc') {
				// declaration is of the form "func Add(a int, b int) int"
				declarationText = declarationText.substring(5);
				const funcNameStart = declarationText.indexOf(res.name + '('); // Find 'functionname(' to remove anything before it
				if (funcNameStart > 0) {
					declarationText = declarationText.substring(funcNameStart);
				}
				si = new SignatureInformation(declarationText, res.doc);
				sig = declarationText.substring(res.name.length);
			}
			si.parameters = getParametersAndReturnType(sig).params.map(
				(paramText) => new ParameterInformation(paramText)
			);
			result.signatures = [si];
			result.activeSignature = 0;
			result.activeParameter = Math.min(theCall.commas.length, si.parameters.length - 1);
			return result;
		} catch (e) {
			return null;
		}
	}

	private previousTokenPosition(document: TextDocument, position: Position): Position {
		while (position.character > 0) {
			const word = document.getWordRangeAtPosition(position);
			if (word) {
				return word.start;
			}
			position = position.translate(0, -1);
		}
		return null;
	}

	/**
	 * Goes through the function params' lines and gets the number of commas and the start position of the call.
	 */
	private walkBackwardsToBeginningOfCall(
		document: TextDocument,
		position: Position
	): { openParen: Position; commas: Position[] } | null {
		let parenBalance = 0;
		let maxLookupLines = 30;
		const commas = [];

		for (let lineNr = position.line; lineNr >= 0 && maxLookupLines >= 0; lineNr--, maxLookupLines--) {
			const line = document.lineAt(lineNr);

			// Stop processing if we're inside a comment
			if (isPositionInComment(document, position)) {
				return null;
			}

			// if its current line, get the text until the position given, otherwise get the full line.
			const [currentLine, characterPosition] =
				lineNr === position.line
					? [line.text.substring(0, position.character), position.character]
					: [line.text, line.text.length - 1];

			for (let char = characterPosition; char >= 0; char--) {
				switch (currentLine[char]) {
					case '(':
						parenBalance--;
						if (parenBalance < 0) {
							return {
								openParen: new Position(lineNr, char),
								commas
							};
						}
						break;
					case ')':
						parenBalance++;
						break;
					case ',':
						const commaPos = new Position(lineNr, char);
						if (parenBalance === 0 && !isPositionInString(document, commaPos)) {
							commas.push(commaPos);
						}
						break;
				}
			}
		}
		return null;
	}
}
