/*---------------------------------------------------------
 * Copyright 2022 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 vscodeUri = require('vscode-uri');
import os = require('os');
import path = require('path');
import { getGoConfig, getGoplsConfig } from './config';
import { getBinPath, getGoVersion } from './util';
import { getConfiguredTools } from './goTools';
import { inspectGoToolVersion } from './goInstallTools';
import { runGoEnv } from './goModules';

/**
 * GoExplorerProvider provides data for the Go tree view in the Explorer
 * Tree View Container.
 */
export class GoExplorerProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
	private goEnvCache = new Cache((uri) => GoEnv.get(uri ? vscode.Uri.parse(uri) : undefined), Time.MINUTE);
	private toolDetailCache = new Cache((name) => getToolDetail(name), Time.HOUR);
	private activeFolder?: vscode.WorkspaceFolder;
	private activeDocument?: vscode.TextDocument;

	static setup({ subscriptions }: vscode.ExtensionContext) {
		const provider = new this();
		const {
			window: { registerTreeDataProvider },
			commands: { registerCommand, executeCommand }
		} = vscode;
		subscriptions.push(registerTreeDataProvider('go.explorer', provider));
		subscriptions.push(registerCommand('go.explorer.refresh', () => provider.update(true)));
		subscriptions.push(registerCommand('go.explorer.open', (item) => provider.open(item)));
		subscriptions.push(registerCommand('go.workspace.editEnv', (item) => provider.editEnv(item)));
		subscriptions.push(registerCommand('go.workspace.resetEnv', (item) => provider.resetEnv(item)));
		executeCommand('setContext', 'go.showExplorer', true);
		return provider;
	}

	private _onDidChangeTreeData = new vscode.EventEmitter<vscode.TreeItem | void>();
	readonly onDidChangeTreeData = this._onDidChangeTreeData.event;

	constructor() {
		this.update();
		vscode.window.onDidChangeActiveTextEditor(() => this.update());
		vscode.workspace.onDidChangeWorkspaceFolders(() => this.update());
		vscode.workspace.onDidChangeConfiguration(() => this.update(true));
		vscode.workspace.onDidCloseTextDocument((doc) => {
			if (!this.activeFolder) {
				this.goEnvCache.delete(vscodeUri.Utils.dirname(doc.uri).toString());
			}
		});
	}

	getTreeItem(element: vscode.TreeItem) {
		return element;
	}

	getChildren(element?: vscode.TreeItem) {
		if (!element) {
			return [this.envTree(), this.toolTree()];
		}
		if (isEnvTree(element)) {
			return this.envTreeItems(element.workspace);
		}
		if (isToolTree(element)) {
			return this.toolTreeItems();
		}
		if (isToolTreeItem(element)) {
			return element.children;
		}
	}

	private update(clearCache = false) {
		if (clearCache) {
			this.goEnvCache.clear();
			this.toolDetailCache.clear();
		}
		const { activeTextEditor } = vscode.window;
		const { getWorkspaceFolder, workspaceFolders } = vscode.workspace;
		this.activeDocument = activeTextEditor?.document;
		this.activeFolder = activeTextEditor?.document
			? getWorkspaceFolder(activeTextEditor.document.uri) || workspaceFolders?.[0]
			: workspaceFolders?.[0];
		this._onDidChangeTreeData.fire();
	}

	private async open(item: EnvTreeItem) {
		if (typeof item.file === 'undefined') return;
		const edit = new vscode.WorkspaceEdit();
		edit.createFile(item.file, { ignoreIfExists: true });
		await vscode.workspace.applyEdit(edit);
		const doc = await vscode.workspace.openTextDocument(item.file);
		await vscode.window.showTextDocument(doc);
	}

	private async editEnv(item?: EnvTreeItem) {
		const uri = this.activeFolder?.uri;
		if (!uri) {
			return;
		}
		let pick: { label?: string; description?: string } | undefined;
		if (isEnvTreeItem(item)) {
			pick = { label: item.key, description: item.value };
		} else {
			const items = Object.entries<string>(await runGoEnv(uri))
				.filter(([label]) => !GoEnv.readonlyVars.has(label))
				.map(([label, description]) => ({
					label,
					description
				}));
			pick = await vscode.window.showQuickPick(items, { title: 'Go: Edit Workspace Env' });
		}
		if (!pick) return;
		const { label, description } = pick;
		const value = await vscode.window.showInputBox({ title: label, value: description });
		if (label && typeof value !== 'undefined') {
			await GoEnv.edit({ [label]: value });
		}
	}

	private async resetEnv(item?: EnvTreeItem) {
		if (item?.key) {
			await GoEnv.reset([item.key]);
			return;
		}
		await GoEnv.reset();
	}

	private envTree() {
		if (this.activeFolder) {
			const { name, uri } = this.activeFolder;
			return new EnvTree(name, uri);
		}
		if (this.activeDocument) {
			const { fileName, uri } = this.activeDocument;
			return new EnvTree(path.basename(fileName), vscodeUri.Utils.dirname(uri));
		}
		return new EnvTree();
	}

	private async envTreeItems(uri?: vscode.Uri) {
		const env = await this.goEnvCache.get(uri?.toString() ?? '');
		const items = [];
		for (const [k, v] of Object.entries(env)) {
			if (v !== '') {
				items.push(new EnvTreeItem(k, v));
			}
		}
		return items;
	}

	private toolTree() {
		return new ToolTree();
	}

	private async toolTreeItems() {
		const goVersion = await getGoVersion();
		const allTools = getConfiguredTools(goVersion, getGoConfig(), getGoplsConfig());
		const toolsInfo = await Promise.all(allTools.map((tool) => this.toolDetailCache.get(tool.name)));
		const items = [];
		for (const t of toolsInfo) {
			items.push(new ToolTreeItem(t));
		}
		return items;
	}
}

class EnvTree implements vscode.TreeItem {
	label = 'env';
	contextValue = 'go:explorer:envtree';
	collapsibleState = vscode.TreeItemCollapsibleState.Expanded;
	iconPath = new vscode.ThemeIcon('symbol-folder');
	constructor(public description = '', public workspace?: vscode.Uri) {}
}

function isEnvTree(item?: vscode.TreeItem): item is EnvTree {
	return item?.contextValue === 'go:explorer:envtree';
}

class EnvTreeItem implements vscode.TreeItem {
	file?: vscode.Uri;
	label: string;
	contextValue?: string;
	tooltip?: string;
	constructor(public key: string, public value: string) {
		this.label = `${key}=${replaceHome(value)}`;
		this.contextValue = 'go:explorer:envitem';
		if (GoEnv.fileVars.has(key)) {
			this.contextValue = 'go:explorer:envfile';
			this.file = vscode.Uri.file(value);
		}
		this.tooltip = `${key}=${value}`;
	}
}

function isEnvTreeItem(item?: vscode.TreeItem): item is EnvTreeItem {
	return item?.contextValue === 'go:explorer:envitem';
}

class GoEnv {
	/**
	 * get returns a subset of go env vars, the union of this.vars and values
	 * set with toolsEnvVars in the go workspace config.
	 * @param uri the directory from which to run go env.
	 * @returns the output of running go env -json VAR1 VAR2...
	 */
	static async get(uri?: vscode.Uri) {
		const toolsEnv = await getGoConfig(uri)['toolsEnvVars'];
		const output = await runGoEnv(uri, [...this.vars, ...Object.keys(toolsEnv)]);
		return output as Record<string, string>;
	}

	/**
	 * update writes to toolsEnvVars in the go workspace config.
	 * @param vars a record of env vars to update.
	 */
	static async edit(vars: Record<string, string>) {
		const config = getGoConfig();
		await config.update('toolsEnvVars', { ...config['toolsEnvVars'], ...vars });
	}

	/**
	 * reset removes entries from toolsEnvVars in the go workspace config.
	 * @param vars env vars to reset.
	 */
	static async reset(vars?: string[]) {
		const config = getGoConfig();
		let env: Record<string, string> = {};
		if (vars) {
			env = { ...config['toolsEnvVars'] };
			for (const v of vars) {
				delete env[v];
			}
		}
		await config.update('toolsEnvVars', env);
	}

	/** Vars that point to files. */
	static fileVars = new Set(['GOMOD', 'GOWORK', 'GOENV']);

	/** Vars available from 'go env' but not read from the environment */
	static readonlyVars = new Set([
		'GOEXE',
		'GOGCCFLAGS',
		'GOHOSTARCH',
		'GOHOSTOS',
		'GOMOD',
		'GOTOOLDIR',
		'GOVERSION',
		'GOWORK'
	]);

	/** Vars that should always be visible if they contain a value. */
	private static vars = ['GOPRIVATE', 'GOMOD', 'GOWORK', 'GOENV'];
}

class ToolTree implements vscode.TreeItem {
	label = 'tools';
	contextValue = 'go:explorer:tools';
	collapsibleState = vscode.TreeItemCollapsibleState.Collapsed;
	iconPath = new vscode.ThemeIcon('tools');
}

function isToolTree(item?: vscode.TreeItem): item is ToolTree {
	return item?.contextValue === 'go:explorer:tools';
}

class ToolTreeItem implements vscode.TreeItem {
	contextValue = 'go:explorer:toolitem';
	description = 'not installed';
	label: string;
	children?: vscode.TreeItem[];
	collapsibleState?: vscode.TreeItemCollapsibleState;
	tooltip?: string;
	constructor({ name, version, goVersion, binPath, error }: ToolDetail) {
		this.label = name;
		if (binPath) {
			this.label = `${name}@${version}`;
			this.description = `${replaceHome(binPath)} ${goVersion}`;
			this.tooltip = `${this.label} ${this.description}`;
		}
		if (error) {
			const msg = `go version -m failed: ${error}`;
			this.description = msg;
			this.tooltip = msg;
		}
	}
}

function isToolTreeItem(item?: vscode.TreeItem): item is ToolTreeItem {
	return item?.contextValue === 'go:explorer:toolitem';
}

interface ToolDetail {
	name: string;
	goVersion?: string;
	version?: string;
	binPath?: string;
	error?: Error;
}

async function getToolDetail(name: string): Promise<ToolDetail> {
	const toolPath = getBinPath(name);
	if (!path.isAbsolute(toolPath)) {
		return { name: name };
	}
	try {
		const { goVersion, moduleVersion } = await inspectGoToolVersion(toolPath);
		return {
			name: name,
			binPath: toolPath,
			goVersion: goVersion,
			version: moduleVersion
		};
	} catch (e) {
		return { name: name, error: e as Error };
	}
}

const enum Time {
	SECOND = 1000,
	MINUTE = SECOND * 60,
	HOUR = MINUTE * 60
}

interface CacheEntry<T> {
	entry: T;
	updatedAt: number;
}

class Cache<T> {
	private cache = new Map<string, CacheEntry<T>>();

	constructor(private fn: (key: string) => Promise<T>, private ttl: number) {}

	async get(key: string, ttl = this.ttl) {
		const cache = this.cache.get(key);
		const useCache = cache && Date.now() - cache.updatedAt < ttl;
		if (useCache) {
			return cache.entry;
		}
		const entry = await this.fn(key);
		this.cache.set(key, { entry, updatedAt: Date.now() });
		return entry;
	}

	clear() {
		return this.cache.clear();
	}

	delete(key: string) {
		return this.cache.delete(key);
	}
}

/**
 * replaceHome replaces the home directory prefix of a string with `~`.
 * @param maybePath a string that might be a file system path.
 * @returns the string with os.homedir() replaced by `~`.
 */
function replaceHome(maybePath: string) {
	return maybePath.replace(new RegExp(`^${os.homedir()}`), '~');
}
