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

import assert from 'assert';
import * as lsp from '../../src/language/goLanguageServer';
import * as goInstallTools from '../../src/goInstallTools';
import { getTool, Tool } from '../../src/goTools';
import moment = require('moment');
import semver = require('semver');
import sinon = require('sinon');

suite('gopls okForStagedRollout', () => {
	const tool: Tool = getTool('gopls')!;
	const sandbox = sinon.createSandbox();
	teardown(() => {
		sandbox.restore();
	});

	function daysAgo(d: number): Date {
		const day = new Date();
		day.setDate(day.getDate() - d);
		return day;
	}

	async function testOkForStagedRollout(ver: string, published: Date | null, machineIDHash: number, want: boolean) {
		const version = semver.parse(ver);

		assert(version);
		sandbox.stub(lsp, 'getTimestampForVersion').returns(Promise.resolve(published ? moment(published) : null));
		const got = await lsp.okForStagedRollout(tool, version, () => machineIDHash);
		assert.strictEqual(got, want);
	}
	test('published today, machine id hash % 100 < 10, want update', async () =>
		await testOkForStagedRollout('v0.11.0', daysAgo(0), 9, true));
	test('published today, machine id hash % 100 >= 10, delay update', async () =>
		await testOkForStagedRollout('v0.11.0', daysAgo(0), 11, false));
	test('published 2d ago, machine id hash % 100 < 30, want update', async () =>
		await testOkForStagedRollout('v0.11.0', daysAgo(2), 29, true));
	test('published 2d ago, machine id hash % 100 >= 30, delay update', async () =>
		await testOkForStagedRollout('v0.11.0', daysAgo(2), 30, false));
	test('published 5d ago, want update', async () => await testOkForStagedRollout('v0.11.0', daysAgo(5), 99, true));
	test('publish date unknown, want update', async () => await testOkForStagedRollout('0.11.0', null, 99, true));
	test('prerelease, want update', async () => await testOkForStagedRollout('v0.11.0-pre.1', daysAgo(0), 99, true));
	test('patch version, want update', async () => await testOkForStagedRollout('0.11.1', daysAgo(0), 99, true));
});

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

		const toSemver = (v: string) => semver.parse(v, { 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 | null][] = [
			['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],
			['developer version dirty', 'v0.0.0-20200521000000-2212a7e161a5+dirty', false, null],
			['developer version dirty (pre-release)', 'v0.0.0-20200521000000-2212a7e161a5+dirty', 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 { version: usersVersion };
			});
			sinon.replace(goInstallTools, 'latestModuleVersion', 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;
				}
				return null;
			});
			const got = await lsp.shouldUpdateLanguageServer(tool, {
				enabled: true,
				path: 'bad/path/to/gopls',
				version: undefined,
				checkForUpdates: 'proxy',
				env: {},
				features: {},
				flags: [],
				modtime: new Date(),
				serverName: 'gopls'
			});
			assert.deepEqual(got, want, `${name}: failed (got: '${got}' ${typeof got} want: '${want}' ${typeof want})`);
			sinon.restore();
		}
	});
});

suite('version comparison', () => {
	const tool: Tool = getTool('dlv')!;
	const latestVersion = tool.latestVersion;

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

	async function testShouldUpdateTool(expected: boolean, moduleVersion?: string) {
		sinon.stub(goInstallTools, 'inspectGoToolVersion').returns(Promise.resolve({ moduleVersion }));
		const got = await goInstallTools.shouldUpdateTool(tool, '/bin/path/to/dlv');
		assert.strictEqual(
			expected,
			got,
			`hard-coded minimum: ${tool.latestVersion?.toString()} vs localVersion: ${moduleVersion}`
		);
	}

	test('local delve is old', async () => {
		await testShouldUpdateTool(true, 'v1.6.0');
	});

	test('local delve is the minimum required version', async () => {
		await testShouldUpdateTool(false, 'v' + latestVersion?.toString());
	});

	test('local delve is newer', async () => {
		await testShouldUpdateTool(false, `v${latestVersion?.major}.${(latestVersion?.minor ?? 0) + 1}.0`);
	});

	test('local delve is slightly older', async () => {
		await testShouldUpdateTool(
			true,
			`v${latestVersion?.major}.${latestVersion?.minor}.${latestVersion?.patch}-0.20201231000000-5360c6286949`
		);
	});

	test('local delve is slightly newer', async () => {
		await testShouldUpdateTool(
			false,
			`v{$latestVersion.major}.${latestVersion?.minor}.${latestVersion?.patch}-0.30211231000000-5360c6286949`
		);
	});

	test('local delve version is unknown', async () => {
		// maybe a wrapper shellscript?
		await testShouldUpdateTool(false, undefined);
	});

	test('local delve version is non-sense', async () => {
		// maybe a wrapper shellscript?
		await testShouldUpdateTool(false, 'hello');
	});

	test('local delve version is non-sense again', async () => {
		// maybe a wrapper shellscript?
		await testShouldUpdateTool(false, '');
	});
});
