#include "config.h"
#include "gen.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "gen.h"
#include "main.h"
#include "help.h"
#include "utils.h"

void new_version_alert(void)
{
	char new_version = 0;
	FILE *fh = fopen(SPAM_FILE, "r");
	if (!fh)
		new_version = 1;
	else
	{
		char buffer[4096], *dummy = 0x00;

		fgets(buffer, sizeof buffer, fh);

		fclose(fh);

		dummy = strchr(buffer, '\n');
		if (dummy)
			*dummy = 0x00;

		if (strcmp(buffer, VERSION) != 0)
			new_version = 1;
	}

	if (new_version)
	{
		FILE *fh = fopen(SPAM_FILE, "w");
		if (fh)
		{
			fprintf(fh, "%s\n", VERSION);

			fclose(fh);
		}

		printf("Welcome to the new HTTPing version " VERSION "!\n\n");
#if HAVE_NCURSES
		printf("Did you know that with -K you can start a fullscreen GUI version with nice graphs and lots more information? And that you can disable the moving graphs with -D?\n");
#if !HAVE_FFTW3
		printf("And if you compile this program with libfftw3, that it can also show a fourier transform of the measured values?\n");
#endif
#else
		printf("Did you know that if you compile this program with NCURSES, that it then includes a nice GUI with lots more information and graphs?\n");
#endif

		printf("\n\n");
	}
}

void version(void)
{
	fprintf(stderr, gettext("HTTPing v" VERSION ", (C) 2003-2023 folkert@vanheusden.com\n"));
#ifndef NO_SSL
	fprintf(stderr, gettext(" * SSL support included (-l)\n"));
#endif

#if HAVE_NCURSES
#if HAVE_FFTW3
	fprintf(stderr, gettext(" * ncurses interface with FFT included (-K)\n"));
#else
	fprintf(stderr, gettext(" * ncurses interface included (-K)\n"));
#endif
#endif

	fprintf(stderr, gettext(" * TFO (TCP fast open) support included (-F)\n"));
	fprintf(stderr, gettext("\n"));
}

void format_help(const char *short_str, const char *long_str, const char *descr)
{
	int par_width = SWITCHES_COLUMN_WIDTH, max_wrap_width = par_width / 2, cur_par_width = 0;
	int descr_width = max_x - (par_width + 1);
	char *line = NULL, *p = (char *)descr;
	char first = 1;

	if (long_str && short_str)
		str_add(&line, "%-4s / %s", short_str, long_str);
	else if (long_str)
		str_add(&line, "%s", long_str);
	else
		str_add(&line, "%s", short_str);

	cur_par_width = fprintf(stderr, "%-*s ", par_width, line);

	free(line);

	if (par_width + 1 >= max_x || cur_par_width >= max_x)
	{
		fprintf(stderr, "%s\n", descr);
		return;
	}

	for(;strlen(p);)
	{
		char *n =  NULL, *kn = NULL, *copy = NULL;
		int n_len = 0, len_after_ww = 0, len_before_ww = 0;
		int str_len = 0, cur_descr_width = first ? max_x - cur_par_width : descr_width;

		while(*p == ' ')
			p++;

		str_len = strlen(p);
		if (!str_len)
			break;

		len_before_ww = min(str_len, cur_descr_width);

		n = &p[len_before_ww];
		kn = n;

		if (str_len > cur_descr_width)
		{ 
			while (*n != ' ' && n_len < max_wrap_width)
			{
				n--;
				n_len++;
			}

			if (n_len >= max_wrap_width)
				n = kn;
		}

		len_after_ww = (int)(n - p);
		if (len_after_ww <= 0)
			break;

		copy = (char *)malloc(len_after_ww + 1);
		memcpy(copy, p, len_after_ww);
		copy[len_after_ww] = 0x00;

		if (first)
			first = 0;
		else
			fprintf(stderr, "%*s ", par_width, "");

		fprintf(stderr, "%s\n", copy);

		free(copy);

		p = n;
	}
}

void usage(const char *me)
{
	char *dummy = NULL, has_color = 0;
	char host[256] = { 0 };

	/* where to connect to */
	fprintf(stderr, gettext(" *** where to connect to ***\n"));
	format_help("-g x", "--url", gettext("URL to ping (e.g. -g http://localhost/)"));
	format_help("-h x", "--hostname", gettext("hostname to ping (e.g. localhost) - use either -g or -h"));
	format_help("-p x", "--port", gettext("portnumber (e.g. 80) - use with -h"));
	format_help("-6", "--ipv6", gettext("use IPv6 when resolving/connecting"));
#ifndef NO_SSL
	format_help("-l", "--use-ssl", gettext("connect using SSL. pinging an https URL automatically enables this setting"));
#endif
	fprintf(stderr, gettext("\n"));

	/* proxy settings */
	fprintf(stderr, gettext(" *** proxy settings ***\n"));
	format_help("-x x", "--proxy", gettext("x should be \"host:port\" which are the network settings of the http/https proxy server. ipv6 ip-address should be \"[ip:address]:port\""));
	format_help("-E", NULL, gettext("fetch proxy settings from environment variables"));
	format_help(NULL, "--proxy-user x", gettext("username for authentication against proxy"));
	format_help(NULL, "--proxy-password x", gettext("password for authentication against proxy"));
	format_help(NULL, "--proxy-password-file x", gettext("read password for proxy authentication from file x"));
	format_help("-5", NULL, gettext("proxy is a socks5 server"));
	format_help(NULL, "--proxy-buster x", gettext("adds \"&x=[random value]\" to the request URL"));
	fprintf(stderr, gettext("\n"));

	/* timing settings */
	fprintf(stderr, gettext(" *** timing settings ***\n"));
	format_help("-c x", "--count", gettext("how many times to ping"));
	format_help("-i x", "--interval", gettext("delay between each ping"));
	format_help("-t x", "--timeout", gettext("timeout (default: 30s)"));
	format_help(NULL, "--ai / --adaptive-interval", gettext("execute pings at multiples of interval relative to start, automatically enabled in ncurses output mode"));
	format_help("-f", "--flood", gettext("flood connect (no delays)"));
	fprintf(stderr, gettext("\n"));

	/* http settings */
	fprintf(stderr, gettext(" *** HTTP settings ***\n"));
	format_help("-Z", "--no-cache", gettext("ask any proxies on the way not to cache the requests"));
	format_help(NULL, "--divert-connect", gettext("connect to a different host than in the URL given"));
	format_help(NULL, "--keep-cookies", gettext("return the cookies given by the HTTP server in the following request(s)"));
	format_help(NULL, "--no-host-header", gettext("do not add \"Host:\"-line to the request headers"));
	format_help("-Q", "--persistent-connections", gettext("use a persistent connection, i.e. reuse the same TCP connection for multiple HTTP requests. usually possible when 'Connection: Keep-Alive' is sent by server. adds a 'C' to the output if httping had to reconnect"));
	format_help("-I x", "--user-agent", gettext("use 'x' for the UserAgent header"));
	format_help("-R x", "--referer", gettext("use 'x' for the Referer header"));
	format_help(NULL, "--header", gettext("adds an extra request-header"));
	fprintf(stderr, gettext("\n"));

	/* network settings */
	fprintf(stderr, gettext(" *** networking settings ***\n"));
	format_help(NULL, "--max-mtu", gettext("limit the MTU size"));
	format_help(NULL, "--no-tcp-nodelay", gettext("do not disable Naggle"));
	format_help(NULL, "--recv-buffer", gettext("receive buffer size"));
	format_help(NULL, "--tx-buffer", gettext("transmit buffer size"));
	format_help("-r", "--resolve-once", gettext("resolve hostname only once (useful when pinging roundrobin DNS: also takes the first DNS lookup out of the loop so that the first measurement is also correct)"));
	format_help("-W", NULL, gettext("do not abort the program if resolving failed: keep retrying"));
	format_help("-y x", "--bind-to", gettext("bind to an ip-address (and thus interface) with an optional port"));
	format_help("-F", "--tcp-fast-open", gettext("\"TCP fast open\" (TFO), reduces the latency of TCP connects"));
#ifdef linux
	format_help(NULL, "--priority", gettext("set priority of packets"));
#endif
	format_help(NULL, "--tos", gettext("set TOS (type of service)"));
	fprintf(stderr, gettext("\n"));

	/* http authentication */
	fprintf(stderr, gettext(" *** HTTP authentication ***\n"));
	format_help("-A", "--basic-auth", gettext("activate (\"basic\") authentication"));
	format_help("-U x", "--username", gettext("username for authentication"));
	format_help("-P x", "--password", gettext("password for authentication"));
	format_help("-T x", NULL, gettext("read the password fom the file 'x' (replacement for -P)"));
	fprintf(stderr, gettext("\n"));

	/* output settings */
	fprintf(stderr, gettext(" *** output settings ***\n"));
	format_help("-s", "--show-statuscodes", gettext("show statuscodes"));
	format_help(NULL, "--median", gettext("show median"));
	format_help("-S", "--split-time", gettext("split measured time in its individual components (resolve, connect, send, receive, disconnect)"));
	format_help(NULL, "--threshold-red", gettext("from what ping value to show the value in red (must be bigger than yellow), only in color mode (-Y)"));
	format_help(NULL, "--threshold-yellow", gettext("from what ping value to show the value in yellow"));
	format_help(NULL, "--threshold-show", gettext("from what ping value to show the results"));
	format_help(NULL, "--timestamp / --ts", gettext("put a timestamp before the measured values, use -v to include the date and -vv to show in microseconds"));
	format_help(NULL, "--aggregate x[,y[,z]]", gettext("show an aggregate each x[/y[/z[/etc]]] seconds"));
#ifndef NO_SSL
	format_help("-k", "--insecure", gettext("allow insecure server connections"));
	format_help("-z", "--show-fingerprint", gettext("show fingerprint (SSL)"));
	format_help(NULL, "--ca-path", gettext("path to ca certificates (SSL)"));
#endif
	format_help("-v", NULL, gettext("verbose mode"));
	fprintf(stderr, gettext("\n"));

	/* GET settings */
	fprintf(stderr, gettext(" *** \"GET\" (instead of HTTP \"HEAD\") settings ***\n"));
	format_help("-G", "--get-request", gettext("do a GET request instead of HEAD (read the contents of the page as well)"));
	format_help("-b", "--show-transfer-speed", gettext("show transfer speed in KB/s (use with -G)"));
	format_help("-B", "--show-xfer-speed-compressed", gettext("like -b but use compression if available"));
	format_help("-L x", "--data-limit", gettext("limit the amount of data transferred (for -b) to 'x' (in bytes)"));
	format_help("-X", "--show-kb", gettext("show the number of KB transferred (for -b)"));
	fprintf(stderr, gettext("\n"));

	/* output mode settings */
	fprintf(stderr, gettext(" *** output mode settings ***\n"));
	format_help("-q", "--quiet", gettext("quiet, only returncode"));
	format_help("-m", "--parseable-output", gettext("give machine parseable output (see also -o and -e)"));
	format_help("-M", NULL, gettext("json output, cannot be combined with -m"));
	format_help("-o rc,rc,...", "--ok-result-codes", gettext("what http results codes indicate 'ok' comma separated WITHOUT spaces inbetween default is 200, use with -e"));
	format_help("-e x", "--result-string", gettext("string to display when http result code doesn't match"));
	format_help("-n warn,crit", "--nagios-mode-1 / --nagios-mode-2", gettext("Nagios-mode: return 1 when avg. response time >= warn, 2 if >= crit, otherwhise return 0"));
	format_help("-N x", NULL, gettext("Nagios mode 2: return 0 when all fine, 'x' when anything failes"));
	format_help("-C cookie=value", "--cookie", gettext("add a cookie to the request"));
	format_help("-Y", "--colors", gettext("add colors"));
	format_help("-a", "--audible-ping", gettext("audible ping"));
	fprintf(stderr, gettext("\n"));

	/* GUI/ncurses mode */
#if HAVE_NCURSES
	fprintf(stderr, gettext(" *** GUI/ncurses mode settings ***\n"));
	format_help("-K", "--ncurses / --gui", gettext("ncurses/GUI mode"));
#if HAVE_FFTW3
	format_help(NULL, "--draw-phase", gettext("draw phase (fourier transform) in gui"));
#endif
	format_help(NULL, "--slow-log", gettext("when the duration is x or more, show ping line in the slow log window (the middle window)"));
	format_help(NULL, "--graph-limit x", gettext("do not scale to values above x"));
	format_help("-D", "--no-graph", gettext("do not show graphs (in ncurses/GUI mode)"));
	fprintf(stderr, gettext("\n"));
#endif

	format_help("-V", "--version", gettext("show the version"));
	fprintf(stderr, gettext("\n"));

	dummy = getenv("TERM");
	if (dummy)
	{
		if (strstr(dummy, "ANSI") || strstr(dummy, "xterm") || strstr(dummy, "screen"))
			has_color = 1;
	}

	if (gethostname(host, sizeof host))
		strcpy(host, "localhost");

	fprintf(stderr, gettext("Example:\n"));
	fprintf(stderr, "\t%s %s%s -s -Z\n\n", me, host, has_color ? " -Y" : "");

	new_version_alert();
}
