/* 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 vscode = require('vscode');
import { getFromWorkspaceState, updateWorkspaceState } from './stateUtils';

const WORKSPACE_IS_TRUSTED_KEY = 'WORKSPACE_IS_TRUSTED_KEY';
const SECURITY_SENSITIVE_CONFIG: string[] = [
	'alternateTools',
	'gopath',
	'goroot',
	'inferGopath',
	'toolsGopath',
	'toolsEnvVars'
];

// Set true only if the vscode is the recent version that has the workspace trust API AND
// if the security.workspace.trust is enabled. Change of this configuration requires restart
// of VSCode, so we don't need to set up the configuration change listener.
// TODO(hyangah): remove this and Configuration & WrappedConfiguration when we update
// our extension to require 2021 June VSCode engine.
const isVscodeWorkspaceTrustAPIAvailable =
	'boolean' === typeof (vscode.workspace as any).isTrusted &&
	vscode.workspace.getConfiguration('security.workspace.trust')?.get('enabled') === true;

// Initialize the singleton defaultConfig and register related commands.
// Prompt if workspace configuration was found but had to be ignored until
// the user has to explicitly opt in to trust the workspace.
export async function initConfig(ctx: vscode.ExtensionContext) {
	ctx.subscriptions.push(vscode.commands.registerCommand('go.workspace.isTrusted.toggle', toggleWorkspaceIsTrusted));

	if (isVscodeWorkspaceTrustAPIAvailable) {
		return; // let vscode handle configuration management.
	}

	const isTrusted = getFromWorkspaceState(WORKSPACE_IS_TRUSTED_KEY, false);
	if (isTrusted !== defaultConfig.workspaceIsTrusted()) {
		defaultConfig.toggleWorkspaceIsTrusted();
	}

	if (isTrusted) {
		return;
	}
	const ignored = ignoredWorkspaceConfig(vscode.workspace.getConfiguration('go'), SECURITY_SENSITIVE_CONFIG);
	if (ignored.length === 0) {
		return;
	}
	const ignoredSettings = ignored.map((x) => `"go.${x}"`).join(',');
	const val = await vscode.window.showWarningMessage(
		`Some workspace/folder-level settings (${ignoredSettings}) from the untrusted workspace are disabled ` +
			'by default. If this workspace is trusted, explicitly enable the workspace/folder-level settings ' +
			'by running the "Go: Toggle Workspace Trust Flag" command.',
		'OK',
		'Trust This Workspace',
		'More Info'
	);
	switch (val) {
		case 'Trust This Workspace':
			await toggleWorkspaceIsTrusted();
			break;
		case 'More Info':
			vscode.env.openExternal(
				vscode.Uri.parse('https://github.com/golang/vscode-go/blob/master/docs/settings.md#security')
			);
			break;
		default:
			break;
	}
}

function ignoredWorkspaceConfig(cfg: vscode.WorkspaceConfiguration, keys: string[]) {
	return keys.filter((key) => {
		const inspect = cfg.inspect(key);
		return inspect.workspaceValue !== undefined || inspect.workspaceFolderValue !== undefined;
	});
}

async function toggleWorkspaceIsTrusted() {
	if (isVscodeWorkspaceTrustAPIAvailable) {
		vscode.commands.executeCommand('workbench.action.manageTrust');
		return;
	}
	const v = defaultConfig.toggleWorkspaceIsTrusted();
	await updateWorkspaceState(WORKSPACE_IS_TRUSTED_KEY, v);
}

// Go extension configuration for a workspace.
export class Configuration {
	constructor(private _workspaceIsTrusted = false, private getConfiguration = vscode.workspace.getConfiguration) {}

	public toggleWorkspaceIsTrusted() {
		this._workspaceIsTrusted = !this._workspaceIsTrusted;
		return this._workspaceIsTrusted;
	}

	// returns a Proxied vscode.WorkspaceConfiguration, which prevents
	// from using the workspace configuration if the workspace is untrusted.
	public get(section: string, uri?: vscode.Uri): vscode.WorkspaceConfiguration {
		const cfg = this.getConfiguration(section, uri);
		if (section !== 'go' || this._workspaceIsTrusted) {
			return cfg;
		}
		return new WrappedConfiguration(cfg);
	}

	public workspaceIsTrusted(): boolean {
		return this._workspaceIsTrusted;
	}
}

class vscodeConfiguration {
	public toggleWorkspaceIsTrusted() {
		/* no-op */
	}
	public get(section: string, uri?: vscode.Uri): vscode.WorkspaceConfiguration {
		return vscode.workspace.getConfiguration(section, uri);
	}
	public workspaceIsTrusted(): boolean {
		return !!(vscode.workspace as any).isTrusted;
	}
}

const defaultConfig = isVscodeWorkspaceTrustAPIAvailable ? new vscodeConfiguration() : new Configuration();

// Returns the workspace Configuration used by the extension.
export function DefaultConfig() {
	return defaultConfig;
}

// wrappedConfiguration wraps vscode.WorkspaceConfiguration.
class WrappedConfiguration implements vscode.WorkspaceConfiguration {
	constructor(private readonly _wrapped: vscode.WorkspaceConfiguration) {
		// set getters for direct setting access (e.g. cfg.gopath), but don't overwrite _wrapped.
		const desc = Object.getOwnPropertyDescriptors(_wrapped);
		for (const prop in desc) {
			// TODO(hyangah): find a better way to exclude WrappedConfiguration's members.
			// These methods are defined by WrappedConfiguration.
			if (typeof prop === 'string' && !['get', 'has', 'inspect', 'update', '_wrapped'].includes(prop)) {
				const d = desc[prop];
				if (SECURITY_SENSITIVE_CONFIG.includes(prop)) {
					const inspect = this._wrapped.inspect(prop);
					d.value = inspect.globalValue ?? inspect.defaultValue;
				}
				Object.defineProperty(this, prop, desc[prop]);
			}
		}
	}

	public get(section: any, defaultValue?: any) {
		if (SECURITY_SENSITIVE_CONFIG.includes(section)) {
			const inspect = this._wrapped.inspect(section);
			return inspect.globalValue ?? defaultValue ?? inspect.defaultValue;
		}
		return this._wrapped.get(section, defaultValue);
	}
	public has(section: string) {
		return this._wrapped.has(section);
	}
	public inspect<T>(section: string) {
		return this._wrapped.inspect<T>(section);
	}
	public update(
		section: string,
		value: any,
		configurationTarget?: boolean | vscode.ConfigurationTarget,
		overrideInLanguage?: boolean
	): Thenable<void> {
		return this._wrapped.update(section, value, configurationTarget, overrideInLanguage);
	}
}

// getGoConfig is declared as an exported const rather than a function, so it can be stubbbed in testing.
export const getGoConfig = (uri?: vscode.Uri) => {
	return getConfig('go', uri);
};

// getGoplsConfig returns the user's gopls configuration.
export function getGoplsConfig(uri?: vscode.Uri) {
	return getConfig('gopls', uri);
}

function getConfig(section: string, uri?: vscode.Uri) {
	if (!uri) {
		if (vscode.window.activeTextEditor) {
			uri = vscode.window.activeTextEditor.document.uri;
		} else {
			uri = null;
		}
	}
	return defaultConfig.get(section, uri);
}

// True if the extension is running in known cloud-based IDEs.
export const IsInCloudIDE = process.env.CLOUD_SHELL === 'true' || process.env.CODESPACES === 'true';
