/*
 * Copyright (c) 2003-2005 Silicon Graphics, Inc.
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it would be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write the Free Software Foundation,
 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "platform_defs.h"
#include "command.h"
#include "input.h"

cmdinfo_t	*cmdtab;
int		ncmds;

static iterfunc_t	iter_func;
static checkfunc_t	check_func;

struct cmdline {
	char	*cmdline;
	bool	iterate;
};

static int	ncmdline;
struct cmdline	*cmdline;

static int
compare(const void *a, const void *b)
{
	return strcmp(((const cmdinfo_t *)a)->name,
		      ((const cmdinfo_t *)b)->name);
}

void
add_command(
	const cmdinfo_t	*ci)
{
	cmdtab = realloc((void *)cmdtab, ++ncmds * sizeof(*cmdtab));
	cmdtab[ncmds - 1] = *ci;
	qsort(cmdtab, ncmds, sizeof(*cmdtab), compare);
}

static int
check_command(
	const cmdinfo_t	*ci)
{
	/* always run internal library supplied commands */
	if (ci->flags & CMD_FLAG_LIBRARY)
		return 1;

	if (check_func)
		return check_func(ci);
	return 1;
}

void
add_check_command(
	checkfunc_t	cf)
{
	check_func = cf;
}

int
command_usage(
	const cmdinfo_t *ci)
{
	printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
	return 0;
}

int
command(
	const cmdinfo_t	*ct,
	int		argc,
	char		**argv)
{
	char		*cmd = argv[0];

	if (!check_command(ct))
		return 0;

	if (argc-1 < ct->argmin || (ct->argmax != -1 && argc-1 > ct->argmax)) {
		if (ct->argmax == -1)
			fprintf(stderr,
	_("bad argument count %d to %s, expected at least %d arguments\n"),
				argc-1, cmd, ct->argmin);
		else if (ct->argmin == ct->argmax)
			fprintf(stderr,
	_("bad argument count %d to %s, expected %d arguments\n"),
				argc-1, cmd, ct->argmin);
		else
			fprintf(stderr,
	_("bad argument count %d to %s, expected between %d and %d arguments\n"),
			argc-1, cmd, ct->argmin, ct->argmax);
		return 0;
	}
	platform_getoptreset();
	return ct->cfunc(argc, argv);
}

const cmdinfo_t *
find_command(
	const char	*cmd)
{
	cmdinfo_t	*ct;

	for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
		if (strcmp(ct->name, cmd) == 0 ||
		    (ct->altname && strcmp(ct->altname, cmd) == 0))
			return (const cmdinfo_t *)ct;
	}
	return NULL;
}

void
add_user_command(char *optarg)
{
	ncmdline++;
	cmdline = realloc(cmdline, sizeof(struct cmdline) * (ncmdline));
	if (!cmdline) {
		perror("realloc");
		exit(1);
	}
	cmdline[ncmdline-1].cmdline = optarg;
	cmdline[ncmdline-1].iterate = true;

}

void
add_oneshot_user_command(char *optarg)
{
	ncmdline++;
	cmdline = realloc(cmdline, sizeof(struct cmdline) * (ncmdline));
	if (!cmdline) {
		perror("realloc");
		exit(1);
	}
	cmdline[ncmdline-1].cmdline = optarg;
	cmdline[ncmdline-1].iterate = false;
}

/*
 * Run a command, iterating as necessary. Return 0 for success, non-zero
 * if an error occurred. Errors terminate loop iteration immediately.
 */
static int
iterate_command(
	const cmdinfo_t	*ct,
	int		argc,
	char		**argv)
{
	int		error = 0;
	int		j;

	/* if there's nothing to iterate, we're done! */
	if (!iter_func)
		return 0;

	for (j = iter_func(0); j; j = iter_func(j)) {
		error = command(ct, argc, argv);
		if (error)
			break;

	}

	return error;
}

void
add_command_iterator(
	iterfunc_t	func)
{
	iter_func = func;
}

static int
process_input(
	char		*input,
	bool		iterate)
{
	char		**v;
	const cmdinfo_t	*ct;
	int		c = 0;
	int		error = 0;

	v = breakline(input, &c);
	if (!c)
		goto out;

	ct = find_command(v[0]);
	if (!ct) {
		fprintf(stderr, _("command \"%s\" not found\n"), v[0]);
		goto out;
	}

	/* oneshot commands don't iterate */
	if (!iterate || (ct->flags & CMD_FLAG_ONESHOT))
		error = command(ct, c, v);
	else
		error = iterate_command(ct, c, v);
out:
	doneline(input, v);
	return error;
}

void
command_loop(void)
{
	char	*input;
	int	done = 0;
	int	i;

	if (!cmdline) {
		/* interactive mode */
		while (!done) {
			input = fetchline();
			if (!input)
				break;
			done = process_input(input, false);
		}
		return;
	}

	/* command line mode */
	for (i = 0; !done && i < ncmdline; i++) {
		input = strdup(cmdline[i].cmdline);
		if (!input) {
			fprintf(stderr,
				_("cannot strdup command '%s': %s\n"),
				cmdline[i].cmdline, strerror(errno));
			exit(1);
		}
		done = process_input(input, cmdline[i].iterate);
	}
	free(cmdline);
	return;
}

void
report_io_times(
	const char		*verb,
	struct timeval		*t2,
	long long		offset,
	long long		count,
	long long		total,
	int			ops,
	int			compact)
{
	char			s1[64], s2[64], ts[64];

	timestr(t2, ts, sizeof(ts), compact ? VERBOSE_FIXED_TIME : 0);
	if (!compact) {
		cvtstr((double)total, s1, sizeof(s1));
		cvtstr(tdiv((double)total, *t2), s2, sizeof(s2));
		printf(_("%s %lld/%lld bytes at offset %lld\n"),
			verb, total, count, (long long)offset);
		printf(_("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n"),
			s1, ops, ts, s2, tdiv((double)ops, *t2));
	} else {/* bytes,ops,time,bytes/sec,ops/sec */
		printf("%lld,%d,%s,%.3f,%.3f\n",
			total, ops, ts,
			tdiv((double)total, *t2), tdiv((double)ops, *t2));
	}
}
