import assert = require('assert');
import {CompletionItemProvider, CompletionItem, CompletionItemKind, CancellationToken, TextDocument, Range, Position, Uri, workspace, window} from 'vscode';
import PHPCompletionItemProvider from '../features/completionItemProvider';
import HoverProvider from '../features/hoverProvider';
import SignatureHelpProvider from '../features/signatureHelpProvider';


var phpCompletionProvider = new PHPCompletionItemProvider();

var testSuggestionsFor = function(value:string, stringBefore:string):Thenable<CompletionItem[]> {
	return workspace.openTextDocument(Uri.parse("untitled:/foo/new.js")).then(document => {
		return window.showTextDocument(document).then(textEditor => {
			return textEditor.edit(editBuilder => {
				var lastLineLength = document.lineAt(document.lineCount - 1).text.length;
				editBuilder.replace(new vscode.Range(new vscode.Position(0, 0), new vscode.Position(textEditor.document.lineCount - 1, lastLineLength)), value);
			}).then(() => {
				var idx = stringBefore ? value.indexOf(stringBefore) + stringBefore.length : 0;
				var position = new Position(0, idx);
				return phpCompletionProvider.provideCompletionItems(document, position, null);
			})
		})
	});
};

var assertSuggestion= function(completions:CompletionItem[], label:string, kind: CompletionItemKind) {
	var entries = completions.filter(suggestion => {
		return suggestion.label === label;
	});
	assert.equal(entries.length, 1);
	assert.equal(entries[0].kind, kind);
};

suite("PHP", () => {

	test("Intellisense", (testDone:(err?:any) => void) => {
		Promise.all([
			testSuggestionsFor('<?php ', 'php ').then(completions => {
				assertSuggestion(completions, '__CLASS__', CompletionItemKind.Field);
				assertSuggestion(completions, 'mysql_thread_id', CompletionItemKind.Function);
				assertSuggestion(completions, '$argc', CompletionItemKind.Variable);
			}),
			testSuggestionsFor('<?php mysql_', 'mysql_').then(completions => {
				assertSuggestion(completions, 'mysql_db_name', CompletionItemKind.Function);
				assertSuggestion(completions, 'mysql_list_tables', CompletionItemKind.Function);
			})
		]).then(() => testDone(), (errors:any[]) => {
			testDone(errors.reduce((e1, e2) => e1 || e2));
		});

	});
});
// /*---------------------------------------------------------
//  * Copyright (C) Microsoft Corporation. All rights reserved.
//  *--------------------------------------------------------*/
// 'use strict';

// import assert = require('assert');
// import {CompletionItemProvider, CompletionItem, CompletionItemKind, CancellationToken, TextDocument, Range, Position} from 'vscode';



// var mockPHPWorkerEnv = function (url:Network.URL, content: string) : { worker: phpWorker.PHPWorker; model: mm.MirrorModel } {
// 	var resourceService = new ResourceService.ResourceService();
// 	var model = mm.createMirrorModelFromString(null, 0, content, modesUtil.createMockMode('mock.mode.id', /(-?\d*\.\d\w*)|(\$[\w-]*)|([\w-]+)/g), url);
// 	resourceService.insert(url, model);

// 	let services = servicesUtil2.createMockEditorWorkerServices({
// 		resourceService: resourceService,
// 	});

// 	var worker = new phpWorker.PHPWorker(modesUtil.createMockMode('mock.mode.id'), [],
// 		services.resourceService, services.markerService);

// 	return { worker: worker, model: model };
// };

// var testComputeInfo = function(value:string, stringBefore:string):WinJS.TPromise<Modes.IComputeExtraInfoResult> {
// 	var url = new Network.URL('test://1');
// 	var env = mockPHPWorkerEnv(url, value);
// 	var idx = stringBefore ? value.indexOf(stringBefore) : value.length;
// 	var position = env.model.getPositionFromOffset(idx);
// 	return env.worker.computeInfo(url, position);
// };

// var testSuggestionsFor = function(value:string, stringBefore:string):WinJS.TPromise<Modes.ISuggestions> {
// 	var url = new Network.URL('test://1');
// 	var env = mockPHPWorkerEnv(url, value);
// 	var idx = stringBefore ? value.indexOf(stringBefore) + stringBefore.length : 0;
// 	var position = env.model.getPositionFromOffset(idx);
// 	return env.worker.suggest(url, position).then(result => result[0]);
// };

// var testParameterHintsFor = function(value:string, stringBefore:string):WinJS.TPromise<Modes.IParameterHints> {
// 	var url = new Network.URL('test://1');
// 	var env = mockPHPWorkerEnv(url, value);
// 	var idx = stringBefore ? value.indexOf(stringBefore) + stringBefore.length : value.length;
// 	var position = env.model.getPositionFromOffset(idx);
// 	return env.worker.getParameterHints(url, position);
// };

// var assertSuggestion= function(completion:Modes.ISuggestions, label:string, type: string) {
// 	var entries = completion.suggestions.filter(function(suggestion: Modes.ISuggestion) {
// 		return suggestion.label === label;
// 	});
// 	assert.equal(entries.length, 1);
// 	assert.equal(entries[0].type, type);
// };

// var assertParameterHints= function(hints:Modes.IParameterHints, paramNames: string[], currentParameter: number) {
// 	assert.equal(hints.signatures.length, 1);
// 	assert.equal(hints.signatures[0].parameters.length, paramNames.length);
// 	var i= 0;
// 	var label = hints.signatures[0].label;
// 	hints.signatures[0].parameters.forEach(function(param) {
// 		assert.equal(param.label, paramNames[i++]);
// 		assert.equal(param.label, label.substring(param.signatureLabelOffset, param.signatureLabelEnd));
// 	});
// 	assert.equal(hints.currentParameter, currentParameter);
// };


// suite('PHP - Intellisense', () => {

// 	test('Globals', function(testDone):any {
// 		Promise.join([
// 			testSuggestionsFor('<?php ', 'php ').then(function(completion:Modes.ISuggestions):void {
// 				assert.equal(completion.currentWord, '');
// 				assertSuggestion(completion, '__CLASS__', 'field');
// 				assertSuggestion(completion, 'mysql_thread_id', 'function');
// 				assertSuggestion(completion, '$argc', 'variable');
// 			}),
// 			testSuggestionsFor('<?php mysql_', 'mysql_').then(function(completion:Modes.ISuggestions):void {
// 				assert.equal(completion.currentWord, 'mysql_');
// 				assertSuggestion(completion, 'mysql_db_name', 'function');
// 				assertSuggestion(completion, 'mysql_list_tables', 'function');
// 			})
// 		]).done(() => testDone(), (errors:any[]) => {
// 			testDone(errors.reduce((e1, e2) => e1 || e2));
// 		});
// 	});

// 	test('Variables', function(testDone):any {
// 		WinJS.Promise.join([
// 			testSuggestionsFor('<?php $a = 1; $', '$a = 1; $').then(function(completion:Modes.ISuggestions):void {
// 				assert.equal(completion.currentWord, '$');
// 				assertSuggestion(completion, '$a', 'variable');
// 			})
// 		]).done(() => testDone(), (errors:any[]) => {
// 			testDone(errors.reduce((e1, e2) => e1 || e2));
// 		});
// 	});
// });

// suite('PHP - Parameter hints', () => {

// 	test('Globals', function(testDone): any {
// 		WinJS.Promise.join([
// 			testParameterHintsFor('<?php mysql_data_seek(', null).then(function(hints: Modes.IParameterHints): void {
// 				assertParameterHints(hints, ['$result', '$row_number'], 0);
// 			}),

// 			testParameterHintsFor('<?php password_hash(', null).then(function(hints: Modes.IParameterHints): void {
// 				assertParameterHints(hints, ['$password', '$algo', '$options'], 0);
// 			}),
// 			testParameterHintsFor('<?php localtime(', null).then(function(hints: Modes.IParameterHints): void {
// 				assertParameterHints(hints, ['$timestamp', '$is_associative'], 0);
// 			}),
// 			testParameterHintsFor('<?php is_callable(', null).then(function(hints: Modes.IParameterHints): void {
// 				assertParameterHints(hints, ['$name', '$syntax_only', '&$callable_name'], 0);
// 			}),
// 			testParameterHintsFor('<?php array_unshift(', null).then(function(hints: Modes.IParameterHints): void {
// 				assertParameterHints(hints, ['&$array', '$var', '$...'], 0);
// 			})
// 		]).done(() => testDone(), (errors:any[]) => {
// 			testDone(errors.reduce((e1, e2) => e1 || e2));
// 		});
// 	});

// 	test('With arguments', function(testDone): any {
// 		WinJS.Promise.join([
// 			testParameterHintsFor('<?php array_unshift(foo', null).then(function(hints:Modes.IParameterHints):void {
// 				assertParameterHints(hints, ['&$array', '$var', '$...'], 0);
// 			}),
// 			testParameterHintsFor('<?php array_unshift(foo, ', null).then(function(hints:Modes.IParameterHints):void {
// 				assertParameterHints(hints, ['&$array', '$var', '$...'], 1);
// 			}),
// 			testParameterHintsFor('<?php array_unshift(foo, f[]', null).then(function(hints:Modes.IParameterHints):void {
// 				assertParameterHints(hints, ['&$array', '$var', '$...'], 1);
// 			}),
// 			testParameterHintsFor('<?php array_unshift(foo, [a, 2]', null).then(function(hints:Modes.IParameterHints):void {
// 				assertParameterHints(hints, ['&$array', '$var', '$...'], 1);
// 			}),
// 			testParameterHintsFor('<?php array_unshift(foo, [a, 2], x', null).then(function(hints:Modes.IParameterHints):void {
// 				assertParameterHints(hints, ['&$array', '$var', '$...'], 2);
// 			}),
// 			testParameterHintsFor('<?php array_unshift(foo, [a, 2], x, y', null).then(function(hints:Modes.IParameterHints):void {
// 				assertParameterHints(hints, ['&$array', '$var', '$...'], 2);
// 			}),
// 			testParameterHintsFor('<?php array_unshift(foo, f(a, 2), x, y', null).then(function(hints:Modes.IParameterHints):void {
// 				assertParameterHints(hints, ['&$array', '$var', '$...'], 2);
// 			}),
// 			testParameterHintsFor('<?php array_unshift(foo, "f(a, 2"', null).then(function(hints:Modes.IParameterHints):void {
// 				assertParameterHints(hints, ['&$array', '$var', '$...'], 1);
// 			}),
// 			testParameterHintsFor('<?php array_unshift(foo, \'f(a, 2\'', null).then(function(hints:Modes.IParameterHints):void {
// 				assertParameterHints(hints, ['&$array', '$var', '$...'], 1);
// 			})
// 		]).done(() => testDone(), (errors:any[]) => {
// 			testDone(errors.reduce((e1, e2) => e1 || e2));
// 		});
// 	});

// 	test('all function', function(testDone):any {

// 		var testFunc = function(hints:Modes.IParameterHints):void {
// 			assert.ok(hints !== null);
// 			assert.equal(1, hints.signatures.length, name);

// 			var res= hints.signatures[0].parameters.map(function(param) { return param.label; } ).join(',');
// 			assert.ok(hints.signatures[0].parameters.length > 0, 'parameters for ' + hints.signatures[0].label + ': ' + res);
// 		};
// 		var promises : WinJS.Promise[] = []
// 		for (var name in phpGlobals.globalfunctions) {
// 			if (phpGlobals.globalfunctions.hasOwnProperty(name)) {
// 				var entry = phpGlobals.globalfunctions[name];
// 				if (entry.signature) {
// 					promises.push(testParameterHintsFor('<?php ' + name + '(', null).then(testFunc));
// 				}
// 			}
// 		}
// 		WinJS.Promise.join(promises).done(() => testDone(), (errors) => {
// 			testDone(errors[0]);
// 		});

// 	});
// });

// suite('PHP - compute info', () => {
// 	test('Globals', function(testDone):any {
// 		WinJS.Promise.join([
// 			testComputeInfo('<?php $file=fopen("welcome.txt","r"); ?>', 'fopen').then((hints:Modes.IComputeExtraInfoResult) => {
// 				assert.ok(!!(hints.value || hints.htmlContent));
// 			}),
// 			testComputeInfo('<?php $file=fopen("welcome.txt","r"); ?>', 'welcome').then((hints:Modes.IComputeExtraInfoResult) => {
// 				assert.ok(hints === null);
// 			})
// 		]).done(() => testDone(), (errors:any[]) => {
// 			testDone(errors.reduce((e1, e2) => e1 || e2));
// 		});
// 	});
// });
