/* eslint-disable @typescript-eslint/no-explicit-any */
/*---------------------------------------------------------
 * Copyright 2021 The Go Authors. All rights reserved.
 * Licensed under the MIT License. See LICENSE in the project root for license information.
 *--------------------------------------------------------*/

import 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));
			});
		});
	});
});
