/*---------------------------------------------------------
 * Copyright (C) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See LICENSE in the project root for license information.
 *--------------------------------------------------------*/
import * as assert from 'assert';
import cp = require('child_process');
import * as fs from 'fs-extra';
import * as path from 'path';
import * as vscode from 'vscode';
import { extensionId } from '../../src/const';

// Env is a collection of test related variables
// that define the test environment such as vscode workspace.
class Env {

	// Currently gopls requires a workspace and does not work in a single-file mode.
	// Code in test environment does not support dynamically adding folders.
	// tslint:disable-next-line:max-line-length
	// https://github.com/microsoft/vscode/blob/890f62dfd9f3e70198931f788c5c332b3e8b7ad7/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts#L281
	//
	// So, when we start the gopls tests, we start the test extension host with a
	// dummy workspace, ${projectDir}/test/gopls/testfixtures/src/workspace
	// (see test/runTest.ts and launch.json).
	// Then copy necessary files to the workspace using Env.reset() from the
	// fixturesRoot directory.
	public workspaceDir: string;
	public fixturesRoot: string;

	public extension: vscode.Extension<any>;

	constructor(projectDir: string) {
		if (!projectDir) {
			assert.fail('project directory cannot be determined');
		}
		this.workspaceDir = path.resolve(projectDir, 'test/gopls/testfixtures/src/workspace');
		this.fixturesRoot = path.resolve(projectDir, 'test/fixtures');
		this.extension = vscode.extensions.getExtension(extensionId);

		// Ensure the vscode extension host is configured as expected.
		const workspaceFolder = path.resolve(vscode.workspace.workspaceFolders[0].uri.fsPath);
		if (this.workspaceDir !== workspaceFolder) {
			assert.fail(`specified workspaceDir: ${this.workspaceDir} does not match the workspace folder: ${workspaceFolder}`);
		}
	}

	public async setup() {
		await this.reset();
		await this.extension.activate();
		await sleep(2000);  // allow extension host + gopls to start.
	}

	public async reset(fixtureDirName?: string) {  // name of the fixtures subdirectory to use.
		try {
			// clean everything except the .gitignore file
			// needed to keep the empty directory in vcs.
			await fs.readdir(this.workspaceDir).then((files) => {
				return Promise.all(
					files.filter((filename) => filename !== '.gitignore' && filename !== '.vscode').map((file) => {
						fs.remove(path.resolve(this.workspaceDir, file));
					}));
			});

			if (!fixtureDirName) {
				return;
			}
			const src = path.resolve(this.fixturesRoot, fixtureDirName);
			const dst = this.workspaceDir;
			await fs.copy(src, dst, { recursive: true });
		} catch (err) {
			assert.fail(err);
		}
	}

	// openDoc opens the file in the workspace with the given path (paths
	// are the path elements of a file).
	public async openDoc(...paths: string[]) {
		const uri = vscode.Uri.file(path.resolve(this.workspaceDir, ...paths));
		const doc = await vscode.workspace.openTextDocument(uri);
		return { uri, doc };
	}
}

async function sleep(ms: number) {
	return new Promise((resolve) => setTimeout(resolve, ms));
}

suite('Go Extension Tests With Gopls', function () {
	this.timeout(300000);
	const projectDir = path.join(__dirname, '..', '..', '..');
	const env = new Env(projectDir);

	suiteSetup(async () => { await env.setup(); });
	suiteTeardown(async () => { await env.reset(); });

	test('HoverProvider', async () => {
		await env.reset('gogetdocTestData');
		const { uri, doc } = await env.openDoc('test.go');

		// TODO(hyangah): find a way to wait for the language server to complete processing.

		const testCases: [string, vscode.Position, string | null, string | null][] = [
			// [new vscode.Position(3,3), '/usr/local/go/src/fmt'],
			['keyword', new vscode.Position(0, 3), null, null], // keyword
			['inside a string', new vscode.Position(23, 14), null, null], // inside a string
			['just a }', new vscode.Position(20, 0), null, null], // just a }
			['inside a number', new vscode.Position(28, 16), null, null], // inside a number
			['func main()', new vscode.Position(22, 5), 'func main()', null],
			['import "math"', new vscode.Position(40, 23), 'package math', '`math` on'],
			['func Println()', new vscode.Position(19, 6), 'func fmt.Println(a ...interface{}) (n int, err error)', 'Println formats '],
			['func print()', new vscode.Position(23, 4), 'func print(txt string)', 'This is an unexported function ']
		];

		const promises = testCases.map(async ([name, position, expectedSignature, expectedDoc]) => {
			const hovers = await vscode.commands.executeCommand(
				'vscode.executeHoverProvider', uri, position) as vscode.Hover[];

			if (expectedSignature === null && expectedDoc === null) {
				assert.equal(hovers.length, 0, `check hovers over ${name} failed: unexpected non-empty hover message.`);
				return;
			}

			const hover = hovers[0];
			assert.equal(hover.contents.length, 1, `check hovers over ${name} failed: unexpected number of hover messages.`);
			const gotMessage = (<vscode.MarkdownString>hover.contents[0]).value;
			assert.ok(
				gotMessage.includes('```go\n' + expectedSignature + '\n```')
				&& (!expectedDoc || gotMessage.includes(expectedDoc)),
				`check hovers over ${name} failed: got ${gotMessage}`);
		});
		return Promise.all(promises);
	});

	test('Completion middleware', async () => {
		await env.reset('gogetdocTestData');
		const { uri } = await env.openDoc('test.go');
		const testCases: [string, vscode.Position, string][] = [
			['fmt.<>', new vscode.Position(19, 5), 'Formatter'],
		];
		for (const [name, position, wantFilterText] of testCases) {
			const list = await vscode.commands.executeCommand(
				'vscode.executeCompletionItemProvider', uri, position) as vscode.CompletionList;

			// Confirm that the hardcoded filter text hack has been applied.
			if (!list.isIncomplete) {
				assert.fail(`gopls should provide an incomplete list by default`);
			}
			// TODO(rstambler): For some reason, the filter text gets deleted
			// from the first item. I can't reproduce this outside of the test
			// suite.
			for (let i = 1; i < list.items.length; i++) {
				const item = list.items[i];
				assert.equal(item.filterText, wantFilterText, `${uri}:${name} failed, unexpected filter text (got ${item.filterText}, want ${wantFilterText})`);
			}
			for (const item of list.items) {
				if (item.kind === vscode.CompletionItemKind.Method || item.kind === vscode.CompletionItemKind.Function) {
					assert.ok(item.command, `${uri}:${name}: expected command associated with ${item.label}, found none`);
				}
			}
		}

	});
});
