/*---------------------------------------------------------
 * Copyright 2020 The Go Authors. All rights reserved.
 * Licensed under the MIT License. See LICENSE in the project root for license information.
 *--------------------------------------------------------*/

// NOTE: This debug adapter is experimental, in-development code. If you
// actually need to debug Go code, please use the default adapter.

import { ChildProcess, spawn } from 'child_process';
import * as fs from 'fs';
import net = require('net');
import * as os from 'os';
import * as path from 'path';

import {
	logger,
	Logger,
	LoggingDebugSession,
	OutputEvent,
	TerminatedEvent
} from 'vscode-debugadapter';
import { DebugProtocol } from 'vscode-debugprotocol';

import {
	envPath,
	getBinPathWithPreferredGopathGoroot,
	parseEnvFile
} from '../utils/goPath';

import { killProcessTree } from '../utils/processUtils';

import { DAPClient } from './dapClient';

interface LoadConfig {
	// FollowPointers requests pointers to be automatically dereferenced.
	followPointers: boolean;
	// MaxVariableRecurse is how far to recurse when evaluating nested types.
	maxVariableRecurse: number;
	// MaxStringLen is the maximum number of bytes read from a string
	maxStringLen: number;
	// MaxArrayValues is the maximum number of elements read from an array, a slice or a map.
	maxArrayValues: number;
	// MaxStructFields is the maximum number of fields read from a struct, -1 will read all fields.
	maxStructFields: number;
}

// This interface should always match the schema found in `package.json`.
interface LaunchRequestArguments extends DebugProtocol.LaunchRequestArguments {
	request: 'launch';
	[key: string]: any;
	program: string;
	stopOnEntry?: boolean;
	args?: string[];
	showLog?: boolean;
	logOutput?: string;
	cwd?: string;
	env?: { [key: string]: string };
	mode?: 'auto' | 'debug' | 'remote' | 'test' | 'exec';
	remotePath?: string;
	port?: number;
	host?: string;
	buildFlags?: string;
	init?: string;
	trace?: 'verbose' | 'log' | 'error';
	/** Optional path to .env file. */
	envFile?: string | string[];
	backend?: string;
	output?: string;
	/** Delve LoadConfig parameters */
	dlvLoadConfig?: LoadConfig;
	dlvToolPath: string;
	/** Delve Version */
	apiVersion: number;
	/** Delve maximum stack trace depth */
	stackTraceDepth: number;

	showGlobalVariables?: boolean;
	packagePathToGoModPathMap: { [key: string]: string };
}

interface AttachRequestArguments extends DebugProtocol.AttachRequestArguments {
	request: 'attach';
	processId?: number;
	stopOnEntry?: boolean;
	showLog?: boolean;
	logOutput?: string;
	cwd?: string;
	mode?: 'local' | 'remote';
	remotePath?: string;
	port?: number;
	host?: string;
	trace?: 'verbose' | 'log' | 'error';
	backend?: string;
	/** Delve LoadConfig parameters */
	dlvLoadConfig?: LoadConfig;
	dlvToolPath: string;
	/** Delve Version */
	apiVersion: number;
	/** Delve maximum stack trace depth */
	stackTraceDepth: number;

	showGlobalVariables?: boolean;
}

function logArgsToString(args: any[]): string {
	return args
		.map((arg) => {
			return typeof arg === 'string' ? arg : JSON.stringify(arg);
		})
		.join(' ');
}

function log(...args: any[]) {
	logger.warn(logArgsToString(args));
}

function logError(...args: any[]) {
	logger.error(logArgsToString(args));
}

// GoDlvDapDebugSession implements a DAP debug adapter to talk to the editor.
//
// This adapter serves as a DAP proxy between the editor and the DAP server
// inside Delve. It relies on functionality inherited from DebugSession to
// implement the server side interfacing the editor, and on DapClient to
// implement the client side interfacing Delve:
//
//      Editor                GoDlvDapDebugSession                 Delve
//  +------------+        +--------------+-----------+         +------------+
//  | DAP Client | <====> | DebugSession | DAPClient |  <====> | DAP Server |
//  +------------+        +--------------+-----------+         +------------+
export class GoDlvDapDebugSession extends LoggingDebugSession {
	private readonly DEFAULT_DELVE_HOST = '127.0.0.1';
	private readonly DEFAULT_DELVE_PORT = 42042;

	private logLevel: Logger.LogLevel = Logger.LogLevel.Error;

	private dlvClient: DelveClient = null;

	// Child process used to track debugee launched without debugging (noDebug
	// mode). Either debugProcess or dlvClient are null.
	private debugProcess: ChildProcess = null;

	public constructor() {
		super();

		// Invoke logger.init here because we want logging to work in 'inline'
		// DA mode. It's typically called in the start() method of our parent
		// class, but this method isn't called in 'inline' mode.
		logger.init((e) => this.sendEvent(e));

		// this debugger uses zero-based lines and columns
		this.setDebuggerLinesStartAt1(false);
		this.setDebuggerColumnsStartAt1(false);
	}

	protected initializeRequest(
		response: DebugProtocol.InitializeResponse,
		args: DebugProtocol.InitializeRequestArguments,
		request?: DebugProtocol.Request
	): void {
		log('InitializeRequest');
		response.body.supportsConfigurationDoneRequest = true;

		// We respond to InitializeRequest here, because Delve hasn't been
		// launched yet. Delve will start responding to DAP requests after
		// LaunchRequest is received, which tell us how to start it.

		// TODO: we could send an InitializeRequest to Delve when
		// it launches, wait for its response and sanity check the capabilities
		// it reports. Once DAP support in Delve is complete, this can be part
		// of making sure that the "dlv" binary we find is sufficiently
		// up-to-date to talk DAP with us.
		this.sendResponse(response);
		log('InitializeResponse');
	}

	protected launchRequest(
		response: DebugProtocol.LaunchResponse,
		args: LaunchRequestArguments,
		request: DebugProtocol.Request
	): void {
		// Setup logger now that we have the 'trace' level passed in from
		// LaunchRequestArguments.
		this.logLevel =
			args.trace === 'verbose'
				? Logger.LogLevel.Verbose
				: args.trace === 'log'
					? Logger.LogLevel.Log
					: Logger.LogLevel.Error;
		const logPath =
			this.logLevel !== Logger.LogLevel.Error ? path.join(os.tmpdir(), 'vscode-godlvdapdebug.txt') : undefined;
		logger.setup(this.logLevel, logPath);
		log('launchRequest');

		// In noDebug mode with the 'debug' launch mode, we don't launch Delve
		// but run the debugee directly.
		// For other launch modes we currently still defer to Delve, for
		// compatibility with the old debugAdapter.
		// See https://github.com/golang/vscode-go/issues/336
		if (args.noDebug && args.mode === 'debug') {
			try {
				this.launchNoDebug(args);
			} catch (e) {
				logError(`launchNoDebug failed: "${e}"`);
				// TODO: define error constants
				// https://github.com/golang/vscode-go/issues/305
				this.sendErrorResponse(
					response,
					3000,
					`Failed to launch "${e}"`);
			}
			return;
		}

		if (!args.port) {
			args.port = this.DEFAULT_DELVE_PORT;
		}
		if (!args.host) {
			args.host = this.DEFAULT_DELVE_HOST;
		}

		this.dlvClient = new DelveClient(args);

		this.dlvClient.on('stdout', (str) => {
			log('dlv stdout:', str);
		});

		this.dlvClient.on('stderr', (str) => {
			log('dlv stderr:', str);
		});

		this.dlvClient.on('connected', () => {
			// Once the client is connected to Delve, forward it the launch
			// request to begin the actual debugging session.
			this.dlvClient.send(request);
		});

		this.dlvClient.on('close', (rc) => {
			if (rc !== 0) {
				// TODO: define error constants
				// https://github.com/golang/vscode-go/issues/305
				this.sendErrorResponse(
					response,
					3000,
					'Failed to continue: Check the debug console for details.');
			}
			log('Sending TerminatedEvent as delve is closed');
			this.sendEvent(new TerminatedEvent());
		});

		// Relay events and responses back to vscode. In the future we will
		// add middleware here to intercept specific kinds of responses/events
		// for special handling.
		this.dlvClient.on('event', (event) => {
			this.sendEvent(event);
		});

		this.dlvClient.on('response', (resp) => {
			this.sendResponse(resp);
		});
	}

	protected attachRequest(
		response: DebugProtocol.AttachResponse,
		args: AttachRequestArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected disconnectRequest(
		response: DebugProtocol.DisconnectResponse,
		args: DebugProtocol.DisconnectArguments,
		request?: DebugProtocol.Request
	): void {
		log('DisconnectRequest');
		// How we handle DisconnectRequest depends on whether Delve was launched
		// at all.
		// * In noDebug node, the Go program was spawned directly without
		//   debugging: this.debugProcess will be non-null, and this.dlvClient
		//   will be null.
		// * Otherwise, Delve was spawned: this.debugProcess will be null, and
		//   this.dlvClient will be non-null.
		if (this.debugProcess !== null) {
			log(`killing debugee (pid: ${this.debugProcess.pid})...`);

			// Kill the debugee and notify the client when the killing is
			// completed, to ensure a clean shutdown sequence.
			killProcessTree(this.debugProcess, log).then(() => {
				super.disconnectRequest(response, args);
				log('DisconnectResponse');
			});
		} else if (this.dlvClient !== null) {
			// Forward this DisconnectRequest to Delve.
			this.dlvClient.send(request);
		} else {
			logError(`both debug process and dlv client are null`);
			// TODO: define all error codes as constants
			// https://github.com/golang/vscode-go/issues/305
			this.sendErrorResponse(
				response,
				3000,
				'Failed to disconnect: Check the debug console for details.');
		}
	}

	protected terminateRequest(
		response: DebugProtocol.TerminateResponse,
		args: DebugProtocol.TerminateArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected restartRequest(
		response: DebugProtocol.RestartResponse,
		args: DebugProtocol.RestartArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected setBreakPointsRequest(
		response: DebugProtocol.SetBreakpointsResponse,
		args: DebugProtocol.SetBreakpointsArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected setFunctionBreakPointsRequest(
		response: DebugProtocol.SetFunctionBreakpointsResponse,
		args: DebugProtocol.SetFunctionBreakpointsArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected setExceptionBreakPointsRequest(
		response: DebugProtocol.SetExceptionBreakpointsResponse,
		args: DebugProtocol.SetExceptionBreakpointsArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected configurationDoneRequest(
		response: DebugProtocol.ConfigurationDoneResponse,
		args: DebugProtocol.ConfigurationDoneArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected continueRequest(
		response: DebugProtocol.ContinueResponse,
		args: DebugProtocol.ContinueArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected nextRequest(
		response: DebugProtocol.NextResponse,
		args: DebugProtocol.NextArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected stepInRequest(
		response: DebugProtocol.StepInResponse,
		args: DebugProtocol.StepInArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected stepOutRequest(
		response: DebugProtocol.StepOutResponse,
		args: DebugProtocol.StepOutArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected stepBackRequest(
		response: DebugProtocol.StepBackResponse,
		args: DebugProtocol.StepBackArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected reverseContinueRequest(
		response: DebugProtocol.ReverseContinueResponse,
		args: DebugProtocol.ReverseContinueArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected restartFrameRequest(
		response: DebugProtocol.RestartFrameResponse,
		args: DebugProtocol.RestartFrameArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected gotoRequest(
		response: DebugProtocol.GotoResponse,
		args: DebugProtocol.GotoArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected pauseRequest(
		response: DebugProtocol.PauseResponse,
		args: DebugProtocol.PauseArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected sourceRequest(
		response: DebugProtocol.SourceResponse,
		args: DebugProtocol.SourceArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected threadsRequest(
		response: DebugProtocol.ThreadsResponse,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected terminateThreadsRequest(
		response: DebugProtocol.TerminateThreadsResponse,
		args: DebugProtocol.TerminateThreadsArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected stackTraceRequest(
		response: DebugProtocol.StackTraceResponse,
		args: DebugProtocol.StackTraceArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected scopesRequest(
		response: DebugProtocol.ScopesResponse,
		args: DebugProtocol.ScopesArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected variablesRequest(
		response: DebugProtocol.VariablesResponse,
		args: DebugProtocol.VariablesArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected setVariableRequest(
		response: DebugProtocol.SetVariableResponse,
		args: DebugProtocol.SetVariableArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected setExpressionRequest(
		response: DebugProtocol.SetExpressionResponse,
		args: DebugProtocol.SetExpressionArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected evaluateRequest(
		response: DebugProtocol.EvaluateResponse,
		args: DebugProtocol.EvaluateArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected stepInTargetsRequest(
		response: DebugProtocol.StepInTargetsResponse,
		args: DebugProtocol.StepInTargetsArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected gotoTargetsRequest(
		response: DebugProtocol.GotoTargetsResponse,
		args: DebugProtocol.GotoTargetsArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected completionsRequest(
		response: DebugProtocol.CompletionsResponse,
		args: DebugProtocol.CompletionsArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected exceptionInfoRequest(
		response: DebugProtocol.ExceptionInfoResponse,
		args: DebugProtocol.ExceptionInfoArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected loadedSourcesRequest(
		response: DebugProtocol.LoadedSourcesResponse,
		args: DebugProtocol.LoadedSourcesArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected dataBreakpointInfoRequest(
		response: DebugProtocol.DataBreakpointInfoResponse,
		args: DebugProtocol.DataBreakpointInfoArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected setDataBreakpointsRequest(
		response: DebugProtocol.SetDataBreakpointsResponse,
		args: DebugProtocol.SetDataBreakpointsArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected readMemoryRequest(
		response: DebugProtocol.ReadMemoryResponse,
		args: DebugProtocol.ReadMemoryArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected disassembleRequest(
		response: DebugProtocol.DisassembleResponse,
		args: DebugProtocol.DisassembleArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected cancelRequest(
		response: DebugProtocol.CancelResponse,
		args: DebugProtocol.CancelArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected breakpointLocationsRequest(
		response: DebugProtocol.BreakpointLocationsResponse,
		args: DebugProtocol.BreakpointLocationsArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	protected setInstructionBreakpointsRequest(
		response: DebugProtocol.SetInstructionBreakpointsResponse,
		args: DebugProtocol.SetInstructionBreakpointsArguments,
		request?: DebugProtocol.Request
	): void {
		this.dlvClient.send(request);
	}

	// Launch the debugee process without starting a debugger.
	// This implements the `Run > Run Without Debugger` functionality in vscode.
	// Note: this method currently assumes launchArgs.mode === 'debug'.
	private launchNoDebug(launchArgs: LaunchRequestArguments): void {
		if (launchArgs.mode !== 'debug') {
			throw new Error('launchNoDebug requires "debug" mode');
		}
		const {program, dirname, programIsDirectory} = parseProgramArgSync(launchArgs);
		const goRunArgs = ['run'];
		if (launchArgs.buildFlags) {
			goRunArgs.push(launchArgs.buildFlags);
		}

		if (programIsDirectory) {
			goRunArgs.push('.');
		} else {
			goRunArgs.push(program);
		}

		if (launchArgs.args) {
			goRunArgs.push(...launchArgs.args);
		}

		// Read env from disk and merge into env variables.
		const fileEnvs = [];
		if (typeof launchArgs.envFile === 'string') {
			fileEnvs.push(parseEnvFile(launchArgs.envFile));
		}
		if (Array.isArray(launchArgs.envFile)) {
			launchArgs.envFile.forEach((envFile) => {
				fileEnvs.push(parseEnvFile(envFile));
			});
		}

		const launchArgsEnv = launchArgs.env || {};
		const programEnv = Object.assign({}, process.env, ...fileEnvs, launchArgsEnv);

		log(`Current working directory: ${dirname}`);
		const goExe = getBinPathWithPreferredGopathGoroot('go', []);
		log(`Running: ${goExe} ${goRunArgs.join(' ')}`);

		this.debugProcess = spawn(goExe, goRunArgs, {
			cwd: dirname,
			env: programEnv
		});
		this.debugProcess.stderr.on('data', (str) => {
			this.sendEvent(new OutputEvent(str.toString(), 'stderr'));
		});
		this.debugProcess.stdout.on('data', (str) => {
			this.sendEvent(new OutputEvent(str.toString(), 'stdout'));
		});
		this.debugProcess.on('close', (rc) => {
			this.sendEvent(new TerminatedEvent());
		});
	}
}

// DelveClient provides a DAP client to talk to a DAP server in Delve.
//
// After creation, it emits the following events:
//
//    'connected':            client is connected to delve
//    'request (request)':    delve sent request
//    'response (response)':  delve sent response
//    'event (event)':        delve sent event
//    'stdout' (str):         delve emitted str to stdout
//    'stderr' (str):         delve emitted str to stderr
//    'close' (rc):           delve exited with return code rc
class DelveClient extends DAPClient {
	private debugProcess: ChildProcess;
	private serverStarted: boolean = false;

	constructor(launchArgs: LaunchRequestArguments) {
		super();

		const launchArgsEnv = launchArgs.env || {};
		const env = Object.assign({}, process.env, launchArgsEnv);

		// Let users override direct path to delve by setting it in the env
		// map in launch.json; if unspecified, fall back to dlvToolPath.
		let dlvPath = launchArgsEnv['dlvPath'];
		if (!dlvPath) {
			dlvPath = launchArgs.dlvToolPath;
		}

		if (!fs.existsSync(dlvPath)) {
			log(
				`Couldn't find dlv at the Go tools path, ${process.env['GOPATH']}${
				env['GOPATH'] ? ', ' + env['GOPATH'] : ''
				} or ${envPath}`
			);
			throw new Error(
				`Cannot find Delve debugger. Install from https://github.com/go-delve/delve/ & ensure it is in your Go tools path, "GOPATH/bin" or "PATH".`
			);
		}

		const dlvArgs = new Array<string>();
		dlvArgs.push('dap');
		dlvArgs.push(`--listen=${launchArgs.host}:${launchArgs.port}`);
		if (launchArgs.showLog) {
			dlvArgs.push('--log=' + launchArgs.showLog.toString());
		}
		if (launchArgs.logOutput) {
			dlvArgs.push('--log-output=' + launchArgs.logOutput);
		}

		log(`Running: ${dlvPath} ${dlvArgs.join(' ')}`);

		this.debugProcess = spawn(dlvPath, dlvArgs, {
			cwd: parseProgramArgSync(launchArgs).dirname,
			env
		});

		this.debugProcess.stderr.on('data', (chunk) => {
			const str = chunk.toString();
			this.emit('stderr', str);
		});

		this.debugProcess.stdout.on('data', (chunk) => {
			const str = chunk.toString();
			this.emit('stdout', str);

			if (!this.serverStarted) {
				this.serverStarted = true;
				this.connectSocketToServer(launchArgs.port, launchArgs.host);
			}
		});

		this.debugProcess.on('close', (rc) => {
			if (rc) {
				logError(`Process exiting with code: ${rc} signal: ${this.debugProcess.killed}`);
			} else {
				log(`Process exiting normally ${this.debugProcess.killed}`);
			}
			this.emit('close', rc);
		});

		this.debugProcess.on('error', (err) => {
			throw err;
		});
	}

	// Connect this client to the server. The server is expected to be listening
	// on host:port.
	private connectSocketToServer(port: number, host: string) {
		// Add a slight delay to ensure that Delve started up the server.
		setTimeout(() => {
			const socket = net.createConnection(
				port,
				host,
				() => {
					this.connect(socket, socket);
					this.emit('connected');
				});

			socket.on('error', (err) => {
				throw err;
			});
		}, 200);
	}
}

// Helper function to parse a program from LaunchRequestArguments. Returns:
// {
//    program: the program arg,
//    dirname: the directory containing the program (or 'program' itself if
//             it's already a directory),
//    programIsDirectory: is the program a directory?
// }
//
// The program argument is taken as-is from launchArgs. If the program path
// is relative, dirname will also be relative. If the program path is absolute,
// dirname will also be absolute.
//
// Throws an exception in case args.program is not a valid file or directory.
// This function can block because it calls a blocking fs function.
function parseProgramArgSync(launchArgs: LaunchRequestArguments
): { program: string, dirname: string, programIsDirectory: boolean } {
	const program = launchArgs.program;
	if (!program) {
		throw new Error('The program attribute is missing in the debug configuration in launch.json');
	}
	let programIsDirectory = false;
	try {
		programIsDirectory = fs.lstatSync(program).isDirectory();
	} catch (e) {
		throw new Error('The program attribute must point to valid directory, .go file or executable.');
	}
	if (!programIsDirectory && path.extname(program) !== '.go') {
		throw new Error('The program attribute must be a directory or .go file in debug mode');
	}
	const dirname = programIsDirectory ? program : path.dirname(program);
	return {program, dirname, programIsDirectory};
}
