/* eslint-disable prettier/prettier */
/* eslint-disable @typescript-eslint/no-unused-vars */
/*---------------------------------------------------------
 * 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 * as vscode from 'vscode';
import {
	GoVersion,
	guessPackageNameFromFile,

	removeDuplicateDiagnostics,
	substituteEnv
} from '../../src/util';
import path = require('path');

suite('utils Tests', () => {
	test('substituteEnv: default', () => {
		// prepare test
		const env = Object.assign({}, process.env);
		process.env['test1'] = 'abcd';
		process.env['test2'] = 'defg';

		const actual = substituteEnv(' ${env:test1} \r\n ${env:test2}\r\n${env:test1}');
		const expected = ' abcd \r\n defg\r\nabcd';

		assert.equal(actual, expected);

		// test completed
		process.env = env;
	});

	test('build GoVersion', () => {
		// [input, wantFormat, wantFormatIncludePrerelease, wantIsValid]
		const testCases: [string | undefined, string, string, boolean][] = [
			[
				'go version devel +a295d59d Fri Jun 26 19:00:25 2020 +0000 darwin/amd64',
				'devel +a295d59d',
				'devel +a295d59d',
				true
			],
			['go version go1.14 darwin/amd64', '1.14.0', '1.14', true],
			['go version go1.14.1 linux/amd64', '1.14.1', '1.14.1', true],
			['go version go1.15rc1 darwin/amd64', '1.15.0', '1.15rc1', true],
			['go version go1.15.1rc2 windows/amd64', '1.15.1', '1.15.1rc2', true],
			['go version go1.15.3-beta.1 darwin/amd64', '1.15.3', '1.15.3-beta.1', true],
			['go version go1.15.3-beta.1.2.3 foobar/amd64', '1.15.3', '1.15.3-beta.1.2.3', true],
			['go version go10.0.1 js/amd64', 'unknown', 'unknown', false],
			[undefined, 'unknown', 'unknown', false],
			['something wrong', 'unknown', 'unknown', false]
		];
		for (const [input, wantFormat, wantFormatIncludePrerelease, wantIsValid] of testCases) {
			const go = new GoVersion('/path/to/go', input);

			assert.equal(go.isValid(), wantIsValid, `GoVersion(${input}) = ${JSON.stringify(go)}`);
			assert.equal(go.format(), wantFormat, `GoVersion(${input}) = ${JSON.stringify(go)}`);
			assert.equal(go.format(true), wantFormatIncludePrerelease, `GoVersion(${input}) = ${JSON.stringify(go)}`);
		}
	});
});

suite('GuessPackageNameFromFile Tests', () => {
	test('package name from main file', (done) => {
		const expectedPackageName = 'main';
		const filename = 'main.go';

		guessPackageNameFromFile(filename)
			.then((result) => {
				assert.equal(result, expectedPackageName);
			})
			.then(() => done(), done);
	});

	test('package name from dirpath', (done) => {
		const expectedPackageName = 'package';
		const fileDir = 'path/package/file.go';

		guessPackageNameFromFile(fileDir)
			.then(([result]) => {
				assert.equal(result, expectedPackageName);
			})
			.then(() => done(), done);
	});

	test('package name from test file', (done) => {
		const expectedPackageName = 'file';
		const expectedPackageTestName = 'file_test';
		const fileDir = 'file_test.go';

		guessPackageNameFromFile(fileDir)
			.then(([packageNameResult, packageTestNameResult]) => {
				assert.equal(packageNameResult, expectedPackageName);
				assert.equal(packageTestNameResult, expectedPackageTestName);
			})
			.then(() => done(), done);
	});
});

suite('Duplicate Diagnostics Tests', () => {
	test('remove duplicate diagnostics', async () => {
		const fixturePath = path.join(__dirname, '..', '..', '..', 'test', 'testdata');
		const uri1 = vscode.Uri.file(path.join(fixturePath, 'linterTest', 'linter_1.go'));
		const uri2 = vscode.Uri.file(path.join(fixturePath, 'linterTest', 'linter_2.go'));

		const diagnosticCollection = vscode.languages.createDiagnosticCollection('linttest');

		// Populate the diagnostic collection
		const diag1 = [
			new vscode.Diagnostic(
				new vscode.Range(1, 2, 1, 3),
				'first line diagnostic',
				vscode.DiagnosticSeverity.Warning
			),
			new vscode.Diagnostic(
				new vscode.Range(2, 0, 2, 3),
				'second line diagnostic',
				vscode.DiagnosticSeverity.Warning
			),
			new vscode.Diagnostic(new vscode.Range(2, 3, 2, 5), 'second line error', vscode.DiagnosticSeverity.Error),
			new vscode.Diagnostic(
				new vscode.Range(4, 0, 4, 3),
				'fourth line diagnostic',
				vscode.DiagnosticSeverity.Warning
			)
		];
		const diag2 = [
			new vscode.Diagnostic(
				new vscode.Range(1, 2, 1, 3),
				'first line diagnostic',
				vscode.DiagnosticSeverity.Warning
			),
			new vscode.Diagnostic(
				new vscode.Range(2, 0, 2, 3),
				'second line diagnostic',
				vscode.DiagnosticSeverity.Warning
			),
			new vscode.Diagnostic(new vscode.Range(2, 3, 2, 5), 'second line error', vscode.DiagnosticSeverity.Error),
			new vscode.Diagnostic(
				new vscode.Range(4, 0, 4, 3),
				'fourth line diagnostic',
				vscode.DiagnosticSeverity.Warning
			)
		];
		diagnosticCollection.set(uri1, diag1);
		diagnosticCollection.set(uri2, diag2);

		// After removing diagnostics from uri1, there should only be one diagnostic remaining, and
		// the diagnostics for uri2 should not be changed.
		const want1 = [diag1[3]];
		const want2: vscode.Diagnostic[] = [];
		diag2.forEach((diag) => {
			want2.push(diag);
		});

		const newDiagnostics: vscode.Diagnostic[] = [
			new vscode.Diagnostic(
				new vscode.Range(1, 2, 1, 3),
				'first line diagnostic',
				vscode.DiagnosticSeverity.Warning
			),
			new vscode.Diagnostic(new vscode.Range(2, 3, 2, 5), 'second line error', vscode.DiagnosticSeverity.Error)
		];

		removeDuplicateDiagnostics(diagnosticCollection, uri1, newDiagnostics);

		assert.strictEqual(diagnosticCollection.get(uri1).length, want1.length);
		for (let i = 0; i < want1.length; i++) {
			assert.strictEqual(diagnosticCollection.get(uri1)[i], want1[i]);
		}

		assert.strictEqual(diagnosticCollection.get(uri2).length, want2.length);
		for (let i = 0; i < want2.length; i++) {
			assert.strictEqual(diagnosticCollection.get(uri2)[i], want2[i]);
		}
	});
});
