/* 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 { ChildProcess, ChildProcessWithoutNullStreams, spawn } from 'child_process';
import * as fs from 'fs';
import { DebugConfiguration } from 'vscode';
import { envPath } from './utils/pathUtils';
import { killProcessTree } from './utils/processUtils';
import getPort = require('get-port');
import path = require('path');
import vscode = require('vscode');

export class GoDebugAdapterDescriptorFactory implements vscode.DebugAdapterDescriptorFactory {
	private dlvDapServer?: ChildProcess;

	public async createDebugAdapterDescriptor(
		session: vscode.DebugSession,
		executable: vscode.DebugAdapterExecutable | undefined
	): Promise<vscode.ProviderResult<vscode.DebugAdapterDescriptor>> {
		if (session.configuration.debugAdapter === 'dlv-dap') {
			return this.createDebugAdapterDescriptorDlvDap(session.configuration);
		}
		// Terminate any running dlv dap server process.
		await this.terminateDlvDapServerProcess();
		return executable;
	}

	public async dispose() {
		await this.terminateDlvDapServerProcess();
	}

	private async createDebugAdapterDescriptorDlvDap(
		configuration: vscode.DebugConfiguration
	): Promise<vscode.ProviderResult<vscode.DebugAdapterDescriptor>> {
		// The dlv-dap server currently receives certain flags and arguments on startup
		// and must be started in an appropriate folder for the program to be debugged.
		// In order to support this, we kill the current dlv-dap server, and start a
		// new one.
		await this.terminateDlvDapServerProcess();

		const { port, host, dlvDapServer } = await startDapServer(configuration);
		this.dlvDapServer = dlvDapServer;
		return new vscode.DebugAdapterServer(port, host);
	}

	private async terminateDlvDapServerProcess() {
		if (this.dlvDapServer) {
			await killProcessTree(this.dlvDapServer);
			this.dlvDapServer = null;
		}
	}
}

export async function startDapServer(
	configuration: DebugConfiguration
): Promise<{ port: number; host: string; dlvDapServer?: ChildProcessWithoutNullStreams }> {
	if (!configuration.host) {
		configuration.host = '127.0.0.1';
	}

	if (configuration.port) {
		// If a port has been specified, assume there is an already
		// running dap server to connect to.
		return { port: configuration.port, host: configuration.host };
	} else {
		configuration.port = await getPort();
	}
	const dlvDapServer = await spawnDlvDapServerProcess(configuration);
	return { dlvDapServer, port: configuration.port, host: configuration.host };
}

async function spawnDlvDapServerProcess(launchArgs: DebugConfiguration): Promise<ChildProcess> {
	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)) {
		appendToDebugConsole(
			`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');
	// add user-specified dlv flags first. When duplicate flags are specified,
	// dlv doesn't mind but accepts the last flag value.
	if (launchArgs.dlvFlags && launchArgs.dlvFlags.length > 0) {
		dlvArgs.push(...launchArgs.dlvFlags);
	}
	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);
	}
	appendToDebugConsole(`Running: ${dlvPath} ${dlvArgs.join(' ')}`);

	const dir = parseProgramArgSync(launchArgs).dirname;

	return await new Promise<ChildProcess>((resolve, reject) => {
		const p = spawn(dlvPath, dlvArgs, {
			cwd: dir,
			env
		});
		let started = false;
		const timeoutToken: NodeJS.Timer = setTimeout(
			() => reject(new Error('timed out while waiting for DAP server to start')),
			5_000
		);

		const stopWaitingForServerToStart = (err?: string) => {
			clearTimeout(timeoutToken);
			started = true;
			if (err) {
				killProcessTree(p); // We do not need to wait for p to actually be killed.
				reject(new Error(err));
			} else {
				resolve(p);
			}
		};

		p.stdout.on('data', (chunk) => {
			if (!started) {
				if (chunk.toString().startsWith('DAP server listening at:')) {
					stopWaitingForServerToStart();
				} else {
					stopWaitingForServerToStart(
						`Expected 'DAP server listening at:' from debug adapter got '${chunk.toString()}'`
					);
				}
			}
			appendToDebugConsole(chunk.toString());
		});
		p.stderr.on('data', (chunk) => {
			if (!started) {
				stopWaitingForServerToStart(`Unexpected error from dlv dap on start: '${chunk.toString()}'`);
			}
			appendToDebugConsole(chunk.toString());
		});
		p.on('close', (code) => {
			if (!started) {
				stopWaitingForServerToStart(`dlv dap closed with code: '${code}' signal: ${p.killed}`);
			}
			if (code) {
				appendToDebugConsole(`Process exiting with code: ${code} signal: ${p.killed}`);
			} else {
				appendToDebugConsole(`Process exited normally: ${p.killed}`);
			}
		});
		p.on('error', (err) => {
			if (!started) {
				stopWaitingForServerToStart(`Unexpected error from dlv dap on start: '${err}'`);
			}
			if (err) {
				appendToDebugConsole(`Error: ${err}`);
			}
		});
	});
}

function parseProgramArgSync(
	launchArgs: DebugConfiguration
): { 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 && launchArgs.mode !== 'exec' && path.extname(program) !== '.go') {
		throw new Error('The program attribute must be a directory or .go file in debug and test mode');
	}
	const dirname = programIsDirectory ? program : path.dirname(program);
	return { program, dirname, programIsDirectory };
}

function appendToDebugConsole(msg: string) {
	// TODO(hyangah): use color distinguishable from the color used from print.
	vscode.debug.activeDebugConsole.append(msg);
}
