/*---------------------------------------------------------
 * 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(ctx: vscode.ExtensionContext) {
		const provider = new this(ctx);
		const {
			window: { registerTreeDataProvider },
			commands: { registerCommand, executeCommand }
		} = vscode;
		ctx.subscriptions.push(
			registerTreeDataProvider('go.explorer', provider),
			registerCommand('go.explorer.refresh', () => provider.update(true)),
			registerCommand('go.explorer.open', (item) => provider.open(item)),
			registerCommand('go.workspace.editEnv', (item) => provider.editEnv(item)),
			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(ctx: vscode.ExtensionContext) {
		this.update();
		ctx.subscriptions.push(
			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()}`), '~');
}
