// SPDX-License-Identifier: GPL-2.0
#include "cache.h"
#include "config.h"
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <subcmd/help.h>
#include "../builtin.h"
#include "levenshtein.h"
#include <linux/zalloc.h>

static int autocorrect;

static int perf_unknown_cmd_config(const char *var, const char *value,
				   void *cb __maybe_unused)
{
	if (!strcmp(var, "help.autocorrect"))
		return perf_config_int(&autocorrect, var,value);

	return 0;
}

static int levenshtein_compare(const void *p1, const void *p2)
{
	const struct cmdname *const *c1 = p1, *const *c2 = p2;
	const char *s1 = (*c1)->name, *s2 = (*c2)->name;
	int l1 = (*c1)->len;
	int l2 = (*c2)->len;
	return l1 != l2 ? l1 - l2 : strcmp(s1, s2);
}

static int add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
{
	unsigned int i, nr = cmds->cnt + old->cnt;
	void *tmp;

	if (nr > cmds->alloc) {
		/* Choose bigger one to alloc */
		if (alloc_nr(cmds->alloc) < nr)
			cmds->alloc = nr;
		else
			cmds->alloc = alloc_nr(cmds->alloc);
		tmp = realloc(cmds->names, cmds->alloc * sizeof(*cmds->names));
		if (!tmp)
			return -1;
		cmds->names = tmp;
	}
	for (i = 0; i < old->cnt; i++)
		cmds->names[cmds->cnt++] = old->names[i];
	zfree(&old->names);
	old->cnt = 0;
	return 0;
}

const char *help_unknown_cmd(const char *cmd, struct cmdnames *main_cmds)
{
	unsigned int i, n = 0, best_similarity = 0;
	struct cmdnames other_cmds;

	memset(&other_cmds, 0, sizeof(other_cmds));

	perf_config(perf_unknown_cmd_config, NULL);

	load_command_list("perf-", main_cmds, &other_cmds);

	if (add_cmd_list(main_cmds, &other_cmds) < 0) {
		fprintf(stderr, "ERROR: Failed to allocate command list for unknown command.\n");
		goto end;
	}
	qsort(main_cmds->names, main_cmds->cnt,
	      sizeof(main_cmds->names), cmdname_compare);
	uniq(main_cmds);

	if (main_cmds->cnt) {
		/* This reuses cmdname->len for similarity index */
		for (i = 0; i < main_cmds->cnt; ++i) {
			main_cmds->names[i]->len =
				levenshtein(cmd, main_cmds->names[i]->name,
					/*swap_penalty=*/0,
					/*substition_penality=*/2,
					/*insertion_penality=*/1,
					/*deletion_penalty=*/1);
		}
		qsort(main_cmds->names, main_cmds->cnt,
		      sizeof(*main_cmds->names), levenshtein_compare);

		best_similarity = main_cmds->names[0]->len;
		n = 1;
		while (n < main_cmds->cnt && best_similarity == main_cmds->names[n]->len)
			++n;
	}

	if (autocorrect && n == 1) {
		const char *assumed = main_cmds->names[0]->name;

		main_cmds->names[0] = NULL;
		clean_cmdnames(&other_cmds);
		fprintf(stderr, "WARNING: You called a perf program named '%s', "
			"which does not exist.\n"
			"Continuing under the assumption that you meant '%s'\n",
			cmd, assumed);
		if (autocorrect > 0) {
			fprintf(stderr, "in %0.1f seconds automatically...\n",
				(float)autocorrect/10.0);
			poll(NULL, 0, autocorrect * 100);
		}
		return assumed;
	}

	fprintf(stderr, "perf: '%s' is not a perf-command. See 'perf --help'.\n", cmd);

	if (main_cmds->cnt && best_similarity < 6) {
		fprintf(stderr, "\nDid you mean %s?\n",
			n < 2 ? "this": "one of these");

		for (i = 0; i < n; i++)
			fprintf(stderr, "\t%s\n", main_cmds->names[i]->name);
	}
end:
	clean_cmdnames(&other_cmds);
	return NULL;
}
