/*---------------------------------------------------------
 * Copyright 2021 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 * as vscode from 'vscode';
import { getMementoKeys, getWorkspaceState, resetItemsState, setWorkspaceState, updateWorkspaceState } from '../../src/stateUtils';
import { MockMemento } from '../mocks/MockMemento';

suite('Workspace State Modification Tests', () => {
	let defaultMemento: vscode.Memento;

	setup(async () => {
		defaultMemento = getWorkspaceState();
	});

	teardown(async () => {
		setWorkspaceState(defaultMemento);
	});

	test('test getMementoKeys', () => {
		interface TestCase {
			keys: string[];
			values: any[];
			want: string[];
		}
		const testCases: TestCase[] = [
			{keys: [], values: [], want: []},
			{keys: ['hello'], values: [false], want: ['hello']},
			{keys: ['hello', 'goodbye'], values: [false, 25], want: ['hello', 'goodbye']},
		];

		testCases.forEach((tc) => {
			setWorkspaceState(new MockMemento());

			const keys = tc.keys;
			const values = tc.values;
			assert.strictEqual(keys.length, values.length, 'List of keys and values does not have same length');

			for (let i = 0; i < keys.length; i ++) {
				updateWorkspaceState(keys[i], values[i]);
			}

			const got = getMementoKeys(getWorkspaceState());
			const want = tc.want;

			assert.strictEqual(got.length, tc.want.length);
			got.forEach((key) => {
				assert.ok(want.includes(key));
			});
		});
	});

	test('test resetItemsState', () => {
		interface TestCase {
			keys: string[];
			values: any[];
			items: string[];
			want: string[];
		}
		const testCases: TestCase[] = [
			{keys: [], values: [], items: undefined, want: []},
			{keys: ['hello'], values: [false], items: undefined, want: ['hello']},
			{keys: ['hello', 'goodbye'], values: [false, 25], items: undefined, want: ['hello', 'goodbye']},

			{keys: [], values: [], items: [], want: []},
			{keys: ['hello'], values: [false], items: [], want: ['hello']},
			{keys: ['hello', 'goodbye'], values: [false, 25], items: [], want: ['hello', 'goodbye']},

			{keys: ['hello'], values: [false], items: ['hello'], want: []},
			{keys: ['hello', 'goodbye'], values: [false, 25], items: ['hello'], want: ['goodbye']},

			{keys: ['hello'], values: [false], items: ['hello'], want: []},
			{keys: ['hello', 'goodbye'], values: [false, 25], items: ['hello', 'goodbye'], want: []},
		];

		testCases.forEach((tc) => {
			setWorkspaceState(new MockMemento());

			const keys = tc.keys;
			const values = tc.values;
			assert.strictEqual(keys.length, values.length, 'List of keys and values does not have same length');

			for (let i = 0; i < keys.length; i ++) {
				updateWorkspaceState(keys[i], values[i]);
			}

			resetItemsState(tc.items, updateWorkspaceState);
			const got = getMementoKeys(getWorkspaceState());
			const want = tc.want;

			assert.strictEqual(got.length, want.length);
			got.forEach((key) => {
				assert.ok(want.includes(key));
			});
		});
	});

});
