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

import * as assert from 'assert';
import { defaultCipherList } from 'constants';
import moment = require('moment');
import semver = require('semver');
import sinon = require('sinon');
import * as vscode from 'vscode';
import * as lsp from '../../src/goLanguageServer';
import { getTool, Tool } from '../../src/goTools';
import { getCheckForToolsUpdatesConfig as getCheckForToolUpdatesConfig, getGoConfig } from '../../src/util';

suite('getCheckForToolUpdatesConfig tests', () => {
	const CHECK_FOR_UPDATES = 'toolsManagement.checkForUpdates';
	const LEGACY_CHECK_FOR_UPDATES = 'useGoProxyToCheckForToolUpdates';
	const defaultConfigInspector = getGoConfig().inspect(CHECK_FOR_UPDATES);

	test('default is as expected', () => {
		const {key, defaultValue, globalValue, workspaceValue} = defaultConfigInspector;
		assert.deepStrictEqual(
			{ key, defaultValue, globalValue, workspaceValue },
			{ key: `go.${CHECK_FOR_UPDATES}`, defaultValue : 'proxy', globalValue: undefined, workspaceValue: undefined},
			CHECK_FOR_UPDATES);
		assert.strictEqual(getGoConfig().get(LEGACY_CHECK_FOR_UPDATES), true, LEGACY_CHECK_FOR_UPDATES);
	});

	// wrapper class of vscode.WorkspaceConfiguration - the object returned by
	// vscode.getConfiguration is read-only, and doesn't allow property modification
	// so working with sinon directly doesn't seem possible.
	class TestWorkspaceConfiguration implements vscode.WorkspaceConfiguration {
		constructor(private _wrapped: vscode.WorkspaceConfiguration) {}
		public get<T>(params: string) { return this._wrapped.get<T>(params); }
		public has(params: string) { return this._wrapped.has(params); }
		public inspect<T>(params: string) { return this._wrapped.inspect<T>(params); }
		public update<T>(
			section: string, value: any,
			configurationTarget?: vscode.ConfigurationTarget | boolean, overrideInLanguage?: boolean) {
				return this._wrapped.update(section, value, configurationTarget, overrideInLanguage);
		}
		[key: string]: any;
	}

	teardown(() => { sinon.restore(); });

	test('default checkForUpdates returns proxy', () => {
		const gocfg = getGoConfig();
		assert.strictEqual(getCheckForToolUpdatesConfig(gocfg), 'proxy');
	});
	test('local when new config is not set and legacy config is set to false', () => {
		const gocfg = new TestWorkspaceConfiguration(getGoConfig());
		sinon.stub(gocfg, 'get')
			.withArgs(LEGACY_CHECK_FOR_UPDATES).returns(false);

		assert.strictEqual(getCheckForToolUpdatesConfig(gocfg), 'local');
	});
	test('proxy when new config is "proxy" and legacy config is set to false', () => {
		const gocfg = new TestWorkspaceConfiguration(getGoConfig());
		sinon.stub(gocfg, 'get')
			.withArgs(LEGACY_CHECK_FOR_UPDATES).returns(false)
			.withArgs(CHECK_FOR_UPDATES).returns('proxy');
		sinon.stub(gocfg, 'inspect').withArgs(CHECK_FOR_UPDATES).returns(
			Object.assign({}, defaultConfigInspector, {	globalValue: 'proxy' }));

		assert.strictEqual(getCheckForToolUpdatesConfig(gocfg), 'proxy');
	});
	test('off when new config (workspace) is "off" and legacy config is set to false', () => {
		const gocfg = new TestWorkspaceConfiguration(getGoConfig());
		sinon.stub(gocfg, 'get')
			.withArgs(LEGACY_CHECK_FOR_UPDATES).returns(false)
			.withArgs(CHECK_FOR_UPDATES).returns('off');
		sinon.stub(gocfg, 'inspect').withArgs(CHECK_FOR_UPDATES).returns(
			Object.assign({}, defaultConfigInspector, {	workspaceValue: 'off' }));
		assert.strictEqual(getCheckForToolUpdatesConfig(gocfg), 'off');
	});
});

suite('gopls update tests', () => {
	test('prompt for update', async () => {
		const tool = getTool('gopls');

		const toSemver = (v: string) => semver.parse(v, { includePrerelease: true, loose: true });

		// Fake data stubbed functions will serve.
		const latestVersion = toSemver('0.4.1');
		const latestVersionTimestamp = moment('2020-05-13', 'YYYY-MM-DD');
		const latestPrereleaseVersion = toSemver('0.4.2-pre1');
		const latestPrereleaseVersionTimestamp = moment('2020-05-20', 'YYYY-MM-DD');

		// name, usersVersion, acceptPrerelease, want
		const testCases: [string, string, boolean, semver.SemVer][] = [
			['outdated, tagged', 'v0.3.1', false, latestVersion],
			['outdated, tagged (pre-release)', '0.3.1', true, latestPrereleaseVersion],
			['up-to-date, tagged', latestVersion.format(), false, null],
			['up-to-date tagged (pre-release)', 'v0.4.0', true, latestPrereleaseVersion],
			['developer version', '(devel)', false, null],
			['developer version (pre-release)', '(devel)', true, null],
			['nonsense version', 'nosuchversion', false, latestVersion],
			['nonsense version (pre-release)', 'nosuchversion', true, latestPrereleaseVersion],
			[
				'latest pre-release',
				'v0.4.2-pre1',
				false, null,
			],
			[
				'latest pre-release (pre-release)',
				'v0.4.2-pre1',
				true, null,
			],
			[
				'outdated pre-release version',
				'v0.3.1-pre1',
				false, latestVersion,
			],
			[
				'outdated pre-release version (pre-release)',
				'v0.3.1-pre1',
				true, latestPrereleaseVersion,
			],
			[
				'recent pseudoversion after pre-release, 2020-05-20',
				'v0.0.0-20200521000000-2212a7e161a5',
				false, null,
			],
			[
				'recent pseudoversion before pre-release, 2020-05-20',
				'v0.0.0-20200515000000-2212a7e161a5',
				false, null,
			],
			[
				'recent pseudoversion after pre-release (pre-release)',
				'v0.0.0-20200521000000-2212a7e161a5',
				true, null,
			],
			[
				'recent pseudoversion before pre-release (pre-release)',
				'v0.0.0-20200515000000-2212a7e161a5',
				true, latestPrereleaseVersion,
			],
			[
				'outdated pseudoversion',
				'v0.0.0-20200309030707-2212a7e161a5',
				false, latestVersion,
			],
			[
				'outdated pseudoversion (pre-release)',
				'v0.0.0-20200309030707-2212a7e161a5',
				true, latestPrereleaseVersion,
			],
		];
		for (const [name, usersVersion, acceptPrerelease, want] of testCases) {
			sinon.replace(lsp, 'getLocalGoplsVersion', async () => {
				return usersVersion;
			});
			sinon.replace(lsp, 'getLatestGoplsVersion', async () => {
				if (acceptPrerelease) {
					return latestPrereleaseVersion;
				}
				return latestVersion;
			});
			sinon.replace(lsp, 'getTimestampForVersion', async (_: Tool, version: semver.SemVer) => {
				if (version === latestVersion) {
					return latestVersionTimestamp;
				}
				if (version === latestPrereleaseVersion) {
					return latestPrereleaseVersionTimestamp;
				}
			});
			const got = await lsp.shouldUpdateLanguageServer(tool, {
				enabled: true,
				path: 'bad/path/to/gopls',
				version: '',
				checkForUpdates: 'proxy',
				env: {},
				features: {
					diagnostics: true,
					documentLink: true,
				},
				flags: [],
				modtime: new Date(),
				serverName: 'gopls',
			});
			assert.deepEqual(got, want, `${name}: failed (got: '${got}' ${typeof got} want: '${want}' ${typeof want})`);
			sinon.restore();
		}
	});
});
