/*---------------------------------------------------------
 * 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[] = [
	'goroot', 'gopath', 'toolsGopath', 'alternateTools', 'inferGopath'
];

let defaultConfig: Configuration = null;

// 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) {
	const isTrusted = getFromWorkspaceState(WORKSPACE_IS_TRUSTED_KEY, false);
	defaultConfig = new Configuration(isTrusted, vscode.workspace.getConfiguration);
	ctx.subscriptions.push(
		vscode.commands.registerCommand('go.workspace.isTrusted.toggle', 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() {
	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<T>(section: string, uri?: vscode.Uri): vscode.WorkspaceConfiguration {
		const cfg = this.getConfiguration(section, uri);
		if (section !== 'go' || this.workspaceIsTrusted) {
			return cfg;
		}

		return new WrappedConfiguration(cfg);
	}
}

// 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) {
			if (typeof prop === 'string' && prop !== '_wrapped') {
				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 ? defaultConfig.get(section, uri) : new Configuration().get(section, uri);
}
