/* eslint-disable prettier/prettier */
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable node/no-unpublished-import */
/*---------------------------------------------------------
 * Copyright 2020 The Go Authors. All rights reserved.
 * Licensed under the MIT License. See LICENSE in the project root for license information.
 *--------------------------------------------------------*/

import * as assert from 'assert';
import { describe, it } from 'mocha';
import * as sinon from 'sinon';
import * as vscode from 'vscode';
import { getLatestGoVersions, GoEnvironmentOption, latestGoVersionKey } from '../../src/goEnvironmentStatus';
import { getGlobalState, setGlobalState, updateGlobalState } from '../../src/stateUtils';
import { MockMemento } from '../mocks/MockMemento';

import moment = require('moment');
import semver = require('semver');
import WebRequest = require('web-request');

describe('#getLatestGoVersion()', function () {
	this.timeout(40000);
	let sandbox: sinon.SinonSandbox | undefined;
	let defaultMemento: vscode.Memento;
	const webrequest = sinon.mock(WebRequest);
	const mmnt = sinon.mock(moment);

	const now = 100000000;
	const oneday = 60 * 60 * 24 * 1000; // 24 hours in milliseconds

	this.beforeAll(async () => {
		defaultMemento = getGlobalState();
	});
	this.afterAll(async () => {
		setGlobalState(defaultMemento);
	});

	this.beforeEach(() => {
		sandbox = sinon.createSandbox();
		setGlobalState(new MockMemento());

		webrequest
			.expects('json')
			.withArgs('https://golang.org/dl/?mode=json')
			.returns([
				{
					version: 'go1.15.1',
					stable: true
				},
				{
					version: 'go1.14.2',
					stable: true
				}
			]);

		mmnt.expects('now').returns(now);
	});

	this.afterEach(async () => {
		sandbox.restore();
	});

	it('should get latest go versions from golang.org/dl with empty cache', async () => {
		const results = await getLatestGoVersions();
		const want = [
			{ label: 'Go 1.15.1', binpath: 'go get golang.org/dl/go1.15.1' },
			{ label: 'Go 1.14.2', binpath: 'go get golang.org/dl/go1.14.2' }
		];

		assert(results.length === want.length);
		for (let i = 0; i < results.length; i++) {
			assert(results[i].label === want[i].label);
			assert(results[i].binpath === want[i].binpath);
		}
	});

	const cacheVersions = [
		new GoEnvironmentOption('go get golang.org/dl/go1.14.7', 'Go 1.14.7'),
		new GoEnvironmentOption('go get golang.org/dl/go1.13.2', 'Go 1.13.2')
	];

	it('should get latest go versions from golang.org/dl with timed out cache', async () => {
		// add a timed out cache entry
		await updateGlobalState(latestGoVersionKey, {
			timestamp: now - (oneday + 1), // more than one day ago
			goVersions: cacheVersions
		});

		// run test
		const results = await getLatestGoVersions();
		const want = [
			{ label: 'Go 1.15.1', binpath: 'go get golang.org/dl/go1.15.1' },
			{ label: 'Go 1.14.2', binpath: 'go get golang.org/dl/go1.14.2' }
		];

		// check results
		assert(results.length === want.length);
		for (let i = 0; i < results.length; i++) {
			assert(results[i].label === want[i].label);
			assert(results[i].binpath === want[i].binpath);
		}
	});

	it('should get latest go versions from cache', async () => {
		// add a valid cache entry
		await updateGlobalState(latestGoVersionKey, {
			timestamp: now - (oneday - 100), // less than one day ago
			goVersions: cacheVersions
		});

		// run test
		const results = await getLatestGoVersions();
		const want = [
			{ label: 'Go 1.14.7', binpath: 'go get golang.org/dl/go1.14.7' },
			{ label: 'Go 1.13.2', binpath: 'go get golang.org/dl/go1.13.2' }
		];

		// check results
		assert(results.length === want.length);
		for (let i = 0; i < results.length; i++) {
			assert(results[i].label === want[i].label);
			assert(results[i].binpath === want[i].binpath);
		}
	});
});
