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

'use strict';

import cp = require('child_process');
import path = require('path');
import vscode = require('vscode');
import { toolExecutionEnvironment } from './goEnv';
import { promptForMissingTool } from './goInstallTools';
import {
	byteOffsetAt,
	canonicalizeGOPATHPrefix,
	getBinPath,
	getFileArchive,
	getGoConfig
} from './util';
import {killProcessTree} from './utils/processUtils';

export class GoReferenceProvider implements vscode.ReferenceProvider {
	public provideReferences(
		document: vscode.TextDocument,
		position: vscode.Position,
		options: { includeDeclaration: boolean },
		token: vscode.CancellationToken
	): Thenable<vscode.Location[]> {
		return this.doFindReferences(document, position, options, token);
	}

	private doFindReferences(
		document: vscode.TextDocument,
		position: vscode.Position,
		options: { includeDeclaration: boolean },
		token: vscode.CancellationToken
	): Thenable<vscode.Location[]> {
		return new Promise<vscode.Location[]>((resolve, reject) => {
			// get current word
			const wordRange = document.getWordRangeAtPosition(position);
			if (!wordRange) {
				return resolve([]);
			}

			const goGuru = getBinPath('guru');
			if (!path.isAbsolute(goGuru)) {
				promptForMissingTool('guru');
				return reject('Cannot find tool "guru" to find references.');
			}

			const filename = canonicalizeGOPATHPrefix(document.fileName);
			const cwd = path.dirname(filename);
			const offset = byteOffsetAt(document, wordRange.start);
			const env = toolExecutionEnvironment();
			const buildTags = getGoConfig(document.uri)['buildTags'];
			const args = buildTags ? ['-tags', buildTags] : [];
			args.push('-modified', 'referrers', `${filename}:#${offset.toString()}`);

			const process = cp.execFile(goGuru, args, { env }, (err, stdout, stderr) => {
				try {
					if (err && (<any>err).code === 'ENOENT') {
						promptForMissingTool('guru');
						return reject('Cannot find tool "guru" to find references.');
					}

					if (err && (<any>err).killed !== true) {
						return reject(`Error running guru: ${err.message || stderr}`);
					}

					const lines = stdout.toString().split('\n');
					const results: vscode.Location[] = [];
					for (const line of lines) {
						const match = /^(.*):(\d+)\.(\d+)-(\d+)\.(\d+):/.exec(line);
						if (!match) {
							continue;
						}
						const [_, file, lineStartStr, colStartStr, lineEndStr, colEndStr] = match;
						const referenceResource = vscode.Uri.file(path.resolve(cwd, file));

						if (!options.includeDeclaration) {
							if (
								document.uri.fsPath === referenceResource.fsPath &&
								position.line === Number(lineStartStr) - 1
							) {
								continue;
							}
						}

						const range = new vscode.Range(
							+lineStartStr - 1,
							+colStartStr - 1,
							+lineEndStr - 1,
							+colEndStr
						);
						results.push(new vscode.Location(referenceResource, range));
					}
					resolve(results);
				} catch (e) {
					reject(e);
				}
			});
			if (process.pid) {
				process.stdin.end(getFileArchive(document));
			}
			token.onCancellationRequested(() => killProcessTree(process));
		});
	}
}
