/* eslint-disable @typescript-eslint/no-explicit-any */
/*---------------------------------------------------------
 * Copyright (C) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See LICENSE in the project root for license information.
 *--------------------------------------------------------*/

'use strict';

import cp = require('child_process');
import vscode = require('vscode');
import { toolExecutionEnvironment } from './goEnv';
import { promptForMissingTool } from './goInstallTools';
import { byteOffsetAt, getBinPath, getFileArchive, makeMemoizedByteOffsetConverter } from './util';

// Interface for the output from fillstruct
interface GoFillStructOutput {
	start: number;
	end: number;
	code: string;
}

export function runFillStruct(editor: vscode.TextEditor): Promise<void> {
	const args = getCommonArgs(editor);
	if (!args) {
		return Promise.reject('No args');
	}

	return execFillStruct(editor, args);
}

function getCommonArgs(editor: vscode.TextEditor): string[] | undefined {
	if (!editor) {
		vscode.window.showInformationMessage('No editor is active.');
		return;
	}
	if (!editor.document.fileName.endsWith('.go')) {
		vscode.window.showInformationMessage('Current file is not a Go file.');
		return;
	}
	const args = ['-modified', '-file', editor.document.fileName];
	if (editor.selection.isEmpty) {
		const offset = byteOffsetAt(editor.document, editor.selection.start);
		args.push('-offset');
		args.push(offset.toString());
	} else {
		args.push('-line');
		args.push(`${editor.selection.start.line + 1}`);
	}
	return args;
}

function getTabsCount(editor: vscode.TextEditor): number {
	const startline = editor.selection.start.line;
	const tabs = editor.document.lineAt(startline).text.match('^\t*');
	return tabs ? tabs.length : 0;
}

function execFillStruct(editor: vscode.TextEditor, args: string[]): Promise<void> {
	const fillstruct = getBinPath('fillstruct');
	const input = getFileArchive(editor.document);
	const tabsCount = getTabsCount(editor);

	return new Promise<void>((resolve, reject) => {
		const p = cp.execFile(fillstruct, args, { env: toolExecutionEnvironment() }, (err, stdout, stderr) => {
			try {
				if (err && (<any>err).code === 'ENOENT') {
					promptForMissingTool('fillstruct');
					return reject();
				}
				if (err) {
					vscode.window.showInformationMessage(`Cannot fill struct: ${stderr}`);
					return reject();
				}

				const output = <GoFillStructOutput[]>JSON.parse(stdout);

				if (output.length === 0) {
					vscode.window.showInformationMessage('Got empty fillstruct output');
					return reject();
				}

				const indent = '\t'.repeat(tabsCount);
				const offsetConverter = makeMemoizedByteOffsetConverter(Buffer.from(editor.document.getText()));

				editor
					.edit((editBuilder) => {
						output.forEach((structToFill) => {
							const out = structToFill.code.replace(/\n/g, '\n' + indent);
							const rangeToReplace = new vscode.Range(
								editor.document.positionAt(offsetConverter(structToFill.start)),
								editor.document.positionAt(offsetConverter(structToFill.end))
							);
							editBuilder.replace(rangeToReplace, out);
						});
					})
					.then(() => resolve());
			} catch (e) {
				reject(e);
			}
		});
		if (p.pid) {
			p.stdin.end(input);
		}
	});
}
