/*
 * libgit2 "remote" example - shows how to modify remotes for a repo
 *
 * Written by the libgit2 contributors
 *
 * To the extent possible under law, the author(s) have dedicated all copyright
 * and related and neighboring rights to this software to the public domain
 * worldwide. This software is distributed without any warranty.
 *
 * You should have received a copy of the CC0 Public Domain Dedication along
 * with this software. If not, see
 * <http://creativecommons.org/publicdomain/zero/1.0/>.
 */

#include "common.h"

/**
 * This is a sample program that is similar to "git remote".  See the
 * documentation for that (try "git help remote") to understand what this
 * program is emulating.
 *
 * This demonstrates using the libgit2 APIs to modify remotes of a repository.
 */

enum subcmd {
	subcmd_add,
	subcmd_remove,
	subcmd_rename,
	subcmd_seturl,
	subcmd_show,
};

struct opts {
	enum subcmd cmd;

	/* for command-specific args */
	int argc;
	char **argv;
};

static int cmd_add(git_repository *repo, struct opts *o);
static int cmd_remove(git_repository *repo, struct opts *o);
static int cmd_rename(git_repository *repo, struct opts *o);
static int cmd_seturl(git_repository *repo, struct opts *o);
static int cmd_show(git_repository *repo, struct opts *o);

static void parse_subcmd(
	struct opts *opt, int argc, char **argv);
static void usage(const char *msg, const char *arg);

int main(int argc, char *argv[])
{
	int retval = 0;
	struct opts opt = {0};
	git_buf buf = GIT_BUF_INIT_CONST(NULL, 0);
	git_repository *repo = NULL;

	parse_subcmd(&opt, argc, argv);

	git_libgit2_init();

	check_lg2(git_repository_discover(&buf, ".", 0, NULL),
		"Could not find repository", NULL);

	check_lg2(git_repository_open(&repo, buf.ptr),
		"Could not open repository", NULL);
	git_buf_free(&buf);

	switch (opt.cmd)
	{
	case subcmd_add:
		retval = cmd_add(repo, &opt);
		break;
	case subcmd_remove:
		retval = cmd_remove(repo, &opt);
		break;
	case subcmd_rename:
		retval = cmd_rename(repo, &opt);
		break;
	case subcmd_seturl:
		retval = cmd_seturl(repo, &opt);
		break;
	case subcmd_show:
		retval = cmd_show(repo, &opt);
		break;
	}

	git_libgit2_shutdown();

	return retval;
}

static int cmd_add(git_repository *repo, struct opts *o)
{
	char *name, *url;
	git_remote *remote = {0};

	if (o->argc != 2)
		usage("you need to specify a name and URL", NULL);

	name = o->argv[0];
	url = o->argv[1];

	check_lg2(git_remote_create(&remote, repo, name, url),
			"could not create remote", NULL);

	return 0;
}

static int cmd_remove(git_repository *repo, struct opts *o)
{
	char *name;

	if (o->argc != 1)
		usage("you need to specify a name", NULL);

	name = o->argv[0];

	check_lg2(git_remote_delete(repo, name),
			"could not delete remote", name);

	return 0;
}

static int cmd_rename(git_repository *repo, struct opts *o)
{
	int i, retval;
	char *old, *new;
	git_strarray problems = {0};

	if (o->argc != 2)
		usage("you need to specify old and new remote name", NULL);

	old = o->argv[0];
	new = o->argv[1];

	retval = git_remote_rename(&problems, repo, old, new);
	if (!retval)
		return 0;

	for (i = 0; i < (int) problems.count; i++) {
		puts(problems.strings[0]);
	}

	git_strarray_free(&problems);

	return retval;
}

static int cmd_seturl(git_repository *repo, struct opts *o)
{
	int i, retval, push = 0;
	char *name = NULL, *url = NULL;

	for (i = 0; i < o->argc; i++) {
		char *arg = o->argv[i];

		if (!strcmp(arg, "--push")) {
			push = 1;
		} else if (arg[0] != '-' && name == NULL) {
			name = arg;
		} else if (arg[0] != '-' && url == NULL) {
			url = arg;
		} else {
			usage("invalid argument to set-url", arg);
		}
	}

	if (name == NULL || url == NULL)
		usage("you need to specify remote and the new URL", NULL);

	if (push)
		retval = git_remote_set_pushurl(repo, name, url);
	else
		retval = git_remote_set_url(repo, name, url);

	check_lg2(retval, "could not set URL", url);

	return 0;
}

static int cmd_show(git_repository *repo, struct opts *o)
{
	int i;
	const char *arg, *name, *fetch, *push;
	int verbose = 0;
	git_strarray remotes = {0};
	git_remote *remote = {0};

	for (i = 0; i < o->argc; i++) {
		arg = o->argv[i];

		if (!strcmp(arg, "-v") || !strcmp(arg, "--verbose")) {
			verbose = 1;
		}
	}

	check_lg2(git_remote_list(&remotes, repo),
		"could not retrieve remotes", NULL);

	for (i = 0; i < (int) remotes.count; i++) {
		name = remotes.strings[i];
		if (!verbose) {
			puts(name);
			continue;
		}

		check_lg2(git_remote_lookup(&remote, repo, name),
			"could not look up remote", name);

		fetch = git_remote_url(remote);
		if (fetch)
			printf("%s\t%s (fetch)\n", name, fetch);
		push = git_remote_pushurl(remote);
		/* use fetch URL if no distinct push URL has been set */
		push = push ? push : fetch;
		if (push)
			printf("%s\t%s (push)\n", name, push);

		git_remote_free(remote);
	}

	git_strarray_free(&remotes);

	return 0;
}

static void parse_subcmd(
	struct opts *opt, int argc, char **argv)
{
	char *arg = argv[1];
	enum subcmd cmd = 0;

	if (argc < 2)
		usage("no command specified", NULL);

	if (!strcmp(arg, "add")) {
		cmd = subcmd_add;
	} else if (!strcmp(arg, "remove")) {
		cmd = subcmd_remove;
	} else if (!strcmp(arg, "rename")) {
		cmd = subcmd_rename;
	} else if (!strcmp(arg, "set-url")) {
		cmd = subcmd_seturl;
	} else if (!strcmp(arg, "show")) {
		cmd = subcmd_show;
	} else {
		usage("command is not valid", arg);
	}
	opt->cmd = cmd;

	opt->argc = argc - 2; /* executable and subcommand are removed */
	opt->argv = argv + 2;
}

static void usage(const char *msg, const char *arg)
{
	fputs("usage: remote add <name> <url>\n", stderr);
	fputs("       remote remove <name>\n", stderr);
	fputs("       remote rename <old> <new>\n", stderr);
	fputs("       remote set-url [--push] <name> <newurl>\n", stderr);
	fputs("       remote show [-v|--verbose]\n", stderr);

	if (msg && !arg)
		fprintf(stderr, "\n%s\n", msg);
	else if (msg && arg)
		fprintf(stderr, "\n%s: %s\n", msg, arg);
	exit(1);
}
