/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* Copyright (c) 2020-2023 Brett Sheffield <bacs@librecast.net> */

#include "config.h"
#include "arg.h"
#include "globals.h"
#include "help.h"
#include "log.h"
#include "sync.h"
#include <errno.h>
#include <net/if.h>
#include <stdlib.h>
#include <string.h>

int arg_bwlimit(void)
{
	size_t len = strlen(bwlimit);
	char *endptr;
	if (!len) return -1;
	errno = 0;
	bpslimit = strtoul(bwlimit, &endptr, 10);
	if (errno) return -1;
	if (endptr) switch (endptr[0]) {
		case 'T':
			bpslimit *= 1000; /* fallthru */
		case 'G':
			bpslimit *= 1000; /* fallthru */
		case 'M':
			bpslimit *= 1000; /* fallthru */
		case 'K':
			bpslimit *= 1000;
	}
	DEBUG("bpslimit = %zu bps\n", bpslimit);
	return 0;
}

int arg_parse(int *argc, char **argv[])
{
	int rc = 0;
#ifdef LCSHARE
	opt_t oloop = { .olong = "loopback", .var = &loopback, .type = OTYPE_BOOL };
#endif
#ifdef LCSYNC
	opt_t odryrun = { .oshort = 'n', .olong = "dry-run", .var = &dryrun, .type = OTYPE_BOOL };
	opt_t oarchive = { .oshort = 'a', .olong = "archive", .var = &archive, .type = OTYPE_BOOL };
	opt_t operms = { .oshort = 'p', .olong = "perms", .var = &setperms, .type = OTYPE_BOOL };
	opt_t oowner = { .oshort = 'o', .olong = "owner", .var = &setowner, .type = OTYPE_BOOL };
	opt_t ogroup = { .oshort = 'g', .olong = "group", .var = &setgroup, .type = OTYPE_BOOL };
	opt_t otimes = { .oshort = 't', .olong = "times", .var = &settimes, .type = OTYPE_BOOL };
	opt_t oremote = { .olong = "remote", .var = &remote, .type = OTYPE_BOOL };
#endif
	opt_t obatch = { .oshort = 'b', .olong = "batchmode", .var = &batchmode, .type = OTYPE_BOOL };
	opt_t obwlimit = { .olong = "bwlimit", .var = &bwlimit, .type = OTYPE_STR };
	opt_t oiface = { .oshort = 'i', .olong = "interface", .var = &iface, .type = OTYPE_STR };
	opt_t ohex = { .var = &hex, .olong = "hex" };
	opt_t okeyfile = { .olong = "keyfile", .var = &keyfile, .type = OTYPE_STR };
	opt_t ologlevel = { .olong = "loglevel", .var = &loglevel, .type = OTYPE_INT };
	opt_t oquiet = { .oshort = 'q', .olong = "quiet", .var = &quiet, .type = OTYPE_BOOL };
	opt_t orecurse = { .oshort = 'r', .olong = "recursive", .var = &recurse, .type = OTYPE_BOOL };
	opt_t overbose = { .oshort = 'v', .olong = "verbose", .var = &verbose, .type = OTYPE_BOOL };
	opt_t oversion = { .oshort = 'V', .olong = "version", .var = &version, .type = OTYPE_BOOL };
	opt_parser_t *parser = opt_init(17);
#ifdef LCSHARE
	opt_new(parser, &oloop);
#endif
#ifdef LCSYNC
	opt_new(parser, &odryrun);
	opt_new(parser, &oarchive);
	opt_new(parser, &operms);
	opt_new(parser, &oowner);
	opt_new(parser, &ogroup);
	opt_new(parser, &otimes);
	opt_new(parser, &oremote);
#endif
	opt_new(parser, &obatch);
	opt_new(parser, &obwlimit);
	opt_new(parser, &ohex);
	opt_new(parser, &oiface);
	opt_new(parser, &okeyfile);
	opt_new(parser, &ologlevel);
	opt_new(parser, &oquiet);
	opt_new(parser, &orecurse);
	opt_new(parser, &overbose);
	opt_new(parser, &oversion);
	rc = opt_parse(parser, argc, argv);
	opt_free(parser);
	if (rc) return help_usage(), rc;
	if (verbose) loglevel = LOG_LOGLEVEL_VERBOSE;
	if (quiet) loglevel = 0;
	if (version) return help_version(), EXIT_SUCCESS;
#ifdef LCSYNC
	if (archive) {
		setperms = 1;
		setowner = 1;
		setgroup = 1;
		settimes = 1;
		recurse = 1;
	}
#endif
	if (bwlimit && arg_bwlimit()) rc = EXIT_FAILURE;
	if (iface) {
		ifx = if_nametoindex(iface);
		if (!ifx) {
			ERROR("%s '%s'\n", strerror(errno), iface);
			return EXIT_FAILURE;
		}
	}
#ifdef LCSHARE
	action = &net_share;
#endif
#ifdef LCSYNC
	if (hex) {
		if (*argc != 1) return help_usage_hex(), EXIT_FAILURE;
		else action = &file_dump;
		return rc;
	}
	if (*argc < 2) return help_usage(), EXIT_FAILURE;
	action = &net_sync;
#endif
	return rc;
}
