/* 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 vscode = require('vscode');
import { listPackages } from '../../goImport';

export class GoCodeActionProvider implements vscode.CodeActionProvider {
	public provideCodeActions(
		document: vscode.TextDocument,
		range: vscode.Range,
		context: vscode.CodeActionContext,
		// eslint-disable-next-line @typescript-eslint/no-unused-vars
		token: vscode.CancellationToken
	): Thenable<vscode.Command[]> {
		const promises = context.diagnostics.map((diag) => {
			// When a name is not found but could refer to a package, offer to add import
			if (diag.message.indexOf('undefined: ') === 0) {
				const [, name] = /^undefined: (\S*)/.exec(diag.message) ?? [];
				return listPackages().then((packages) => {
					const commands = packages
						.filter((pkg) => pkg === name || pkg.endsWith('/' + name))
						.map((pkg) => {
							return {
								title: 'import "' + pkg + '"',
								command: 'go.import.add',
								arguments: [{ importPath: pkg, from: 'codeAction' }]
							};
						});
					return commands;
				});
			}
			return [];
		});

		return Promise.all(promises).then((arrs) => {
			const results: { [key: string]: any } = {};
			for (const segment of arrs) {
				for (const item of segment) {
					results[item.title] = item;
				}
			}
			const ret = [];
			for (const title of Object.keys(results).sort()) {
				ret.push(results[title]);
			}
			return ret;
		});
	}
}
