/*
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License v2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will 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 to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 021110-1307, USA.
 */

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "crc32c.h"
#include "commands.h"
#include "version.h"

static const char * const btrfs_cmd_group_usage[] = {
	"btrfs [--help] [--version] <group> [<group>...] <command> [<args>]",
	NULL
};

static const char btrfs_cmd_group_info[] =
	"Use --help as an argument for information on a specific group or command.";

static char argv0_buf[ARGV0_BUF_SIZE] = "btrfs";

static inline const char *skip_prefix(const char *str, const char *prefix)
{
	size_t len = strlen(prefix);
	return strncmp(str, prefix, len) ? NULL : str + len;
}

int prefixcmp(const char *str, const char *prefix)
{
	for (; ; str++, prefix++)
		if (!*prefix)
			return 0;
		else if (*str != *prefix)
			return (unsigned char)*prefix - (unsigned char)*str;
}

static int parse_one_token(const char *arg, const struct cmd_group *grp,
			   const struct cmd_struct **cmd_ret)
{
	const struct cmd_struct *cmd = grp->commands;
	const struct cmd_struct *abbrev_cmd = NULL, *ambiguous_cmd = NULL;

	for (; cmd->token; cmd++) {
		const char *rest;

		rest = skip_prefix(arg, cmd->token);
		if (!rest) {
			if (!prefixcmp(cmd->token, arg)) {
				if (abbrev_cmd) {
					/*
					 * If this is abbreviated, it is
					 * ambiguous. So when there is no
					 * exact match later, we need to
					 * error out.
					 */
					ambiguous_cmd = abbrev_cmd;
				}
				abbrev_cmd = cmd;
			}
			continue;
		}
		if (*rest)
			continue;

		*cmd_ret = cmd;
		return 0;
	}

	if (ambiguous_cmd)
		return -2;

	if (abbrev_cmd) {
		*cmd_ret = abbrev_cmd;
		return 0;
	}

	return -1;
}

static const struct cmd_struct *
parse_command_token(const char *arg, const struct cmd_group *grp)
{
	const struct cmd_struct *cmd = NULL;

	switch(parse_one_token(arg, grp, &cmd)) {
	case -1:
		help_unknown_token(arg, grp);
	case -2:
		help_ambiguous_token(arg, grp);
	}

	return cmd;
}

static void handle_help_options_next_level(const struct cmd_struct *cmd,
		int argc, char **argv)
{
	if (argc < 2)
		return;

	if (!strcmp(argv[1], "--help")) {
		if (cmd->next) {
			argc--;
			argv++;
			help_command_group(cmd->next, argc, argv);
		} else {
			usage_command(cmd, 1, 0);
		}

		exit(0);
	}
}

static void fixup_argv0(char **argv, const char *token)
{
	int len = strlen(argv0_buf);

	snprintf(argv0_buf + len, sizeof(argv0_buf) - len, " %s", token);
	argv[0] = argv0_buf;
}

int handle_command_group(const struct cmd_group *grp, int argc,
			 char **argv)

{
	const struct cmd_struct *cmd;

	argc--;
	argv++;
	if (argc < 1) {
		usage_command_group(grp, 0, 0);
		exit(1);
	}

	cmd = parse_command_token(argv[0], grp);

	handle_help_options_next_level(cmd, argc, argv);

	fixup_argv0(argv, cmd->token);
	return cmd->fn(argc, argv);
}

int check_argc_exact(int nargs, int expected)
{
	if (nargs < expected)
		fprintf(stderr, "%s: too few arguments\n", argv0_buf);
	if (nargs > expected)
		fprintf(stderr, "%s: too many arguments\n", argv0_buf);

	return nargs != expected;
}

int check_argc_min(int nargs, int expected)
{
	if (nargs < expected) {
		fprintf(stderr, "%s: too few arguments\n", argv0_buf);
		return 1;
	}

	return 0;
}

int check_argc_max(int nargs, int expected)
{
	if (nargs > expected) {
		fprintf(stderr, "%s: too many arguments\n", argv0_buf);
		return 1;
	}

	return 0;
}

static const struct cmd_group btrfs_cmd_group;

static const char * const cmd_help_usage[] = {
	"btrfs help [--full]",
	"Display help information",
	"",
	"--full     display detailed help on every command",
	NULL
};

static int cmd_help(int argc, char **argv)
{
	help_command_group(&btrfs_cmd_group, argc, argv);
	return 0;
}

static const char * const cmd_version_usage[] = {
	"btrfs version",
	"Display btrfs-progs version",
	NULL
};

static int cmd_version(int argc, char **argv)
{
	printf("%s\n", BTRFS_BUILD_VERSION);
	return 0;
}

static void handle_options(int *argc, char ***argv)
{
	if (*argc > 0) {
		const char *arg = (*argv)[0];
		if (arg[0] != '-' ||
		    !strcmp(arg, "--help") ||
		    !strcmp(arg, "--version"))
			return;
		fprintf(stderr, "Unknown option: %s\n", arg);
		fprintf(stderr, "usage: %s\n",
			btrfs_cmd_group.usagestr[0]);
		exit(129);
	}
	return;
}

static const struct cmd_group btrfs_cmd_group = {
	btrfs_cmd_group_usage, btrfs_cmd_group_info, {
		{ "subvolume", cmd_subvolume, NULL, &subvolume_cmd_group, 0 },
		{ "filesystem", cmd_filesystem, NULL, &filesystem_cmd_group, 0 },
		{ "balance", cmd_balance, NULL, &balance_cmd_group, 0 },
		{ "device", cmd_device, NULL, &device_cmd_group, 0 },
		{ "scrub", cmd_scrub, NULL, &scrub_cmd_group, 0 },
		{ "check", cmd_check, cmd_check_usage, NULL, 0 },
		{ "rescue", cmd_rescue, NULL, &rescue_cmd_group, 0 },
		{ "restore", cmd_restore, cmd_restore_usage, NULL, 0 },
		{ "inspect-internal", cmd_inspect, NULL, &inspect_cmd_group, 0 },
		{ "property", cmd_property, NULL, &property_cmd_group, 0 },
		{ "send", cmd_send, cmd_send_usage, NULL, 0 },
		{ "receive", cmd_receive, cmd_receive_usage, NULL, 0 },
		{ "quota", cmd_quota, NULL, &quota_cmd_group, 0 },
		{ "qgroup", cmd_qgroup, NULL, &qgroup_cmd_group, 0 },
		{ "replace", cmd_replace, NULL, &replace_cmd_group, 0 },
		{ "help", cmd_help, cmd_help_usage, NULL, 0 },
		{ "version", cmd_version, cmd_version_usage, NULL, 0 },
		NULL_CMD_STRUCT
	},
};

int main(int argc, char **argv)
{
	const struct cmd_struct *cmd;
	const char *bname;

	if ((bname = strrchr(argv[0], '/')) != NULL)
		bname++;
	else
		bname = argv[0];

	if (!strcmp(bname, "btrfsck")) {
		argv[0] = "check";
	} else {
		argc--;
		argv++;
		handle_options(&argc, &argv);
		if (argc > 0) {
			if (!prefixcmp(argv[0], "--"))
				argv[0] += 2;
		} else {
			usage_command_group(&btrfs_cmd_group, 0, 0);
			exit(1);
		}
	}

	cmd = parse_command_token(argv[0], &btrfs_cmd_group);

	handle_help_options_next_level(cmd, argc, argv);

	crc32c_optimization_init();

	fixup_argv0(argv, cmd->token);
	exit(cmd->fn(argc, argv));
}
