/* $Id: e2_cl_option.c 708 2007-11-09 21:30:03Z tpgww $

Copyright (C) 2003-2007 tooar <tooar@gmx.net>

This file is part of emelFM2.
emelFM2 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; either version 3, or (at your option)
any later version.

emelFM2 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 emelFM2; see the file GPL. If not, contact the Free Software
Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

/*
@file src/config/e2_cl_option.c
@brief session-start command-line option processing, and help messages display

Glib's option parsing mechanism - GOptionContext and friends - ia not used
because several emelFM2 options may have whitespace inside an argument string -
and that is not supported by GOptionContext (nor is -h for help)
*/

#include "emelfm2.h"
#include <getopt.h>
#include <string.h>
#include <glib/gprintf.h>
#include "e2_cl_option.h"

/**
@brief print minimal usage message on console

@return
*/
static void _e2_cl_option_print_usage (void)
{
	g_printf (_("usage: %s [option]\n"), BINNAME);
}
/**
@brief print full usage message on console

@return
*/
static void _e2_cl_option_print_help (void)
{
	_e2_cl_option_print_usage ();
	/*NOTE for translators: do not translate the actual option strings
	  (-h, --help etc) but it's ok to translate any other part of this string */
	g_printf (
		_("Program options:\n"
		"-1,--one=DIR           set 1st pane's start directory to DIR\n"
		"-2,--two=DIR           set 2nd pane's start directory to DIR\n"
		"-c,--config=DIR        set config directory to DIR (default: ~/.config/emelfm2)\n"
		"-e,--encoding=TYPE     set filesystem character encoding to TYPE\n"
		"-f,--fallback-encoding set fallback encoding (default: ISO-8859-1)\n"
		"-i,--ignore-problems   ignore encoding/locale problems (at your own risk!)\n"
		"-l,--log-all           maximise scope of error logging\n"
		"-m,--daemon            run program as daemon\n"
		"-r,--run-at-start=CMD  run command CMD at session start\n"
		"-s,--set-option=OPT    set one-line gui option using config-file formatted OPT\n"
		"-t,--trash=DIR         set trash directory to DIR (default: ~/.local/share/Trash/files)\n"
		"\n"
		"Help options:\n"
		"-h,--help              show this help message\n"
		"-u,--usage             display brief usage messsage\n"
		"-v,--version           display version and build info\n")
	);
#ifdef DEBUG_MESSAGES
	/*need separate message to allow the main message to work regardless of debug mode
	  when the .po file is created and when the program is run */
	g_printf (
		_("-d,--debug=[1-5]       set debug level from 1 (low) to 5 (high)\n"
		  "-x,--verbose           display time/location info on debug messages\n")
	);
#endif
}
/**
@brief print build-related message on console

@return
*/
static void _e2_cl_option_print_version (void)
{
	g_printf (
		_("%s v. %s\n"
		"Licensed under the GPL\n"
		"Copyright (C) %s\n"	//&#169; doesn't work
		"Build date: %s\n"
		"Build platform: GTK+ %d.%d.%d %s\n"),
		PROGNAME, VERSION RELEASE, COPYRIGHT, BUILDDATE,	//BUILDDATE may be non-utf-8
		GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION, BUILDINFO
	);
}
/**
@brief parse commandline options and store results for later use

@param argc no. of commandline arguments, as supplied to main()
@param argv array of commanline arguments, as supplied to main()

@return
*/
void e2_cl_option_process (gint argc, gchar *argv[])
{
	//non-string non-zero-default values need to be set before the options are parsed
#ifdef DEBUG_MESSAGES
	e2_cl_options.debug_level = E2_DEBUG_LEVEL;
#endif
	//default to no logging when detailed messaging happening
	e2_cl_options.suppress_gtk_log = TRUE;	//(E2_DEBUG_LEVEL > 2);

	gchar *freeme;
	gint c;
#ifdef DEBUG_MESSAGES
	gint d = 0;
#endif
	while (TRUE)
	{
		gint option_index = 0;
		static struct option long_options[] =
		{
			{"one", required_argument, NULL, '1'},
			{"two", required_argument, NULL, '2'},
			{"config", required_argument, NULL, 'c'},
#ifdef DEBUG_MESSAGES
			{"debug", required_argument, NULL, 'd'},
#endif
			{"encoding", required_argument, NULL, 'e'},
			{"fallback-encoding", required_argument, NULL, 'f'},
			{"ignore-problems", no_argument, NULL, 'i'},
			{"log-all", no_argument, NULL, 'l'},
			{"daemon", no_argument, NULL, 'm'},
			{"run-at-start", required_argument, NULL, 'r'},
			{"set-option", required_argument, NULL, 's'},
			{"trash", required_argument, NULL, 't'},
#ifdef DEBUG_MESSAGES
			{"verbose", no_argument, NULL, 'x'},
#endif
			{"help", no_argument, NULL, 'h'},
			{"usage", no_argument, NULL, 'u'},
			{"version", no_argument, NULL, 'v'},
			{NULL, no_argument, NULL, 0}
		};

#ifdef DEBUG_MESSAGES
		c = getopt_long (argc, argv, "1:2:c:d:e:f:t:ilmr:s:xhuv", long_options, &option_index);
#else
		c = getopt_long (argc, argv, "1:2:c:e:f:t:ilmr:s:huv", long_options, &option_index);
#endif
		if (c == -1) break;
#ifdef DEBUG_MESSAGES
		d++;
#endif
		if (optarg != NULL && *optarg != '\0')
		{
			gchar *convert;
			switch (c)
			{
				case '1':
					printd (DEBUG, "setting pane 1 startup path '%s'", optarg);
					//no encoding conversion yet, the arrangements are not yet in place
					e2_cl_options.pane1_path = g_strdup (optarg);
					break;
				case '2':
					printd (DEBUG, "setting pane 2 startup path '%s'", optarg);
					//no encoding conversion yet, the arrangements are not yet in place
					e2_cl_options.pane2_path = g_strdup (optarg);
					break;
				case 'c':
					g_free (e2_cl_options.config_dir);
					if (g_path_is_absolute (optarg))
#ifdef E2_FILES_UTF8ONLY
						convert = g_strdup (optarg);
#else
						convert = optarg;
#endif
					else
					{
						freeme = g_get_current_dir ();
						convert = g_build_filename (freeme, optarg, NULL);
						g_free (freeme);
					}
#ifdef E2_FILES_UTF8ONLY
					e2_cl_options.config_dir = convert;
#else
					e2_cl_options.config_dir = e2_utf8_filename_from_locale (convert);
					if (convert != optarg)
						g_free (convert);
#endif
					printd (DEBUG, "setting config directory '%s'", e2_cl_options.config_dir);
					break;
#ifdef DEBUG_MESSAGES
				case 'd':
					printd (DEBUG, "setting debug level '%s'", optarg);
					{
						gchar *end;
						e2_cl_options.debug_level = g_ascii_strtoull (optarg, &end, 10);
						if (end == optarg)
						{
							e2_cl_options.debug_level = E2_DEBUG_LEVEL;
							printd (WARN, "failed setting debug level '%s'", optarg);
						}
//						e2_cl_options.suppress_gtk_log =
//							(e2_cl_options.debug_level > 2);
					}
					break;
#endif
				case 'e':
					g_free (e2_cl_options.encoding);
					e2_cl_options.encoding = g_strdup (optarg);
					break;
				case 'f':
					g_free (e2_cl_options.fallback_encoding);
					e2_cl_options.fallback_encoding = g_strdup (optarg);
					break;
				case 'r':
					e2_cl_options.startup_commands = g_list_append
						(e2_cl_options.startup_commands, g_strdup (optarg));
					break;
				case 's':
					e2_cl_options.option_overrides = g_list_append
						(e2_cl_options.option_overrides, g_strdup (optarg));
					break;
				case 't':
					g_free (e2_cl_options.trash_dir);
					if (g_path_is_absolute (optarg))
#ifdef E2_FILES_UTF8ONLY
						convert = g_strdup (optarg);
#else
						convert = optarg;
#endif
					else
					{
						freeme = g_get_current_dir ();
						convert = g_build_filename (freeme, optarg, NULL);
						g_free (freeme);
					}
#ifdef E2_FILES_UTF8ONLY
					e2_cl_options.trash_dir = convert;
#else
					e2_cl_options.trash_dir = e2_utf8_filename_from_locale (convert);
					if (convert != optarg)
						g_free (convert);
#endif
					printd (DEBUG, "setting trash directory '%s'", e2_cl_options.trash_dir);
					break;
				default:
					printd (ERROR, "unknown option with code: 0%o and value: %s", c, optarg);
					break;
			}
		}
		else	//no argument, or blank
		{
			switch (c)
			{
				case 'i':
					e2_cl_options.ignore_problems = TRUE;
					break;
				case 'l':
					e2_cl_options.suppress_gtk_log = FALSE;
				case 'm':
					e2_cl_options.detached = TRUE;
					break;
#ifdef DEBUG_MESSAGES
				case 'x':
					e2_cl_options.verbose = TRUE;
					break;
#endif
				case 'u':
					_e2_cl_option_print_usage ();
					exit (0);
					break;
				case 'h':
					_e2_cl_option_print_help ();
					exit (0);
					break;
				case 'v':
					_e2_cl_option_print_version ();
					exit (0);
					break;
				case '?':
					printd (ERROR, "unknown option");
//ignore			exit (0);
					break;
				default:
					printd (ERROR, "unknown option with code: 0%o", c);
					break;
			}
		}
	}

	if (optind < argc)
	{
		g_printf (_("Startup options must begin with \"-\" or \"--\"\n"));
		exit (0);	//FIXME do a clean exit
	}
	printd (DEBUG, "parsed %d command line options", d);

	//now we setup any missing default strings
	const gchar *usedir;
	if (e2_cl_options.config_dir == NULL)
	{
		usedir = g_getenv ("XDG_CONFIG_HOME");
		if (usedir == NULL || *usedir == '\0')
			usedir = g_get_user_config_dir ();
#ifdef E2_FILES_UTF8ONLY
		e2_cl_options.config_dir = g_build_filename (usedir, BINNAME, NULL);
#else
		freeme = g_build_filename (usedir, BINNAME, NULL);
		e2_cl_options.config_dir =  e2_utf8_filename_from_locale (freeme);
		g_free (freeme);
#endif
	}
	//setup local default trash dir (any others done elsewhere)
	if (e2_cl_options.trash_dir == NULL)
	{
		usedir = g_getenv ("XDG_DATA_HOME");
		if (usedir == NULL || *usedir == '\0')
			usedir = g_get_user_data_dir ();
#ifdef E2_FILES_UTF8ONLY
		e2_cl_options.trash_dir = g_build_filename (usedir, "Trash", "files", NULL);
#else
		freeme = g_build_filename (usedir, "Trash", "files", NULL);
		e2_cl_options.trash_dir = e2_utf8_filename_from_locale (freeme);
		g_free (freeme);
#endif
	}

	const gchar **encodings;
	g_get_filename_charsets (&encodings);
	if (e2_cl_options.encoding == NULL)
	{
		if (encodings[0] != NULL && *encodings[0] != '\0')
			e2_cl_options.encoding = g_strdup (encodings[0]);
		else
			e2_cl_options.encoding = g_strdup ("ISO-8859-1");
	}
	if (e2_cl_options.fallback_encoding == NULL)
	{
		if (encodings[1] != NULL && *encodings[1] != '\0')
			e2_cl_options.fallback_encoding = g_strdup (encodings[1]);
		else
			e2_cl_options.fallback_encoding = g_strdup ("ISO-8859-1");
	}
}
