/*
 *  Copyright (C) 2000-2002 Marco Pesenti Gritti
 *
 *  This program 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 2, or (at your option)
 *  any later version.
 *
 *  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 02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "galeon-shell.h"
#include "galeon-automation.h"
#include "galeon-window.h"
#include "gul-state.h"
#include "galeon-debug.h"
#include "hig-alert.h"
#include "GaleonAutomation.h"

#include <libbonoboui.h>
#include <libgnome/gnome-program.h>
#include <libgnomeui/gnome-ui-init.h>
#include <libgnomeui/gnome-window-icon.h>
#include <libgnomeui/gnome-app-helper.h>
#include <libgnomevfs/gnome-vfs-init.h>
#include <glade/glade-init.h>
#ifdef ENABLE_NLS
# include <locale.h>
#endif

#define GALEON_FACTORY_OAFIID "OAFIID:GNOME_Galeon_Automation_Factory"

static gint
galeon_main_translate_url_arguments (poptContext context, gchar ***urls);
static void
galeon_main_start (void);

/* FIXME */
CORBA_Environment corba_env;			/* Global for downloader	*/
static gboolean open_in_existing      = FALSE;  /* load in existing window?     */
static gboolean open_in_new_tab       = FALSE;  /* force open in a new tab?     */
static gboolean noraise               = FALSE;  /* no raise                     */
static gboolean open_in_new_window    = FALSE;  /* force open in a new window?  */
static gboolean open_fullscreen       = FALSE;  /* open galeon in full screen ? */
static gchar   *session_filename      = NULL;   /* the session filename         */
static gchar   *geometry_string       = NULL;   /* the geometry string          */
static gchar   *bookmark_url          = NULL;   /* the temp bookmark to add     */
static gboolean close_option          = FALSE;  /* --close                      */
static gboolean quit_option           = FALSE;  /* --quit                       */
static gboolean galeon_server_mode    = FALSE;
static gboolean open_as_nautilus_view = FALSE;

static gint n_urls; 
static gchar **url;

/* command line argument parsing structure */
static struct poptOption popt_options[] =
{
	{ NULL, '\0', POPT_ARG_INCLUDE_TABLE, &bonobo_activation_popt_options, 0, NULL,
	  NULL },
	{ "new-tab", 'n', POPT_ARG_NONE, &open_in_new_tab, 0,
	  N_("Open a new tab in an existing Galeon window"),
	  NULL },
	{ "new-window", 'w', POPT_ARG_NONE, &open_in_new_window, 0,
	  N_("Open a new window in an existing Galeon process"),
	  NULL },
	{ "noraise", '\0', POPT_ARG_NONE, &noraise, 0,
	  N_("Do not raise the window when opening a page in an existing Galeon process"),
	  NULL },
	{ "fullscreen", 'f', POPT_ARG_NONE, &open_fullscreen, 0,
	  N_("Run Galeon in full screen mode"),
	  NULL },
	{ "existing", 'x', POPT_ARG_NONE, &open_in_existing, 0,
	  N_("Attempt to load URL in existing Galeon window"),
	  NULL },
	{ "load-session", 'l', POPT_ARG_STRING, &session_filename, 0,
	  N_("Load the given session file"),
	  N_("FILE") },
	{ "server", 's', POPT_ARG_NONE, &galeon_server_mode, 0,
	  N_("Don't open any windows; instead act as a server "
	     "for quick startup of new Galeon instances"),
	  NULL },		  
	{ "add-bookmark", 't', POPT_ARG_STRING, &bookmark_url,
	  0, N_("Add a bookmark (don't open any window)"), 
	  N_("URL")},
	{ "geometry", 'g', POPT_ARG_STRING, &geometry_string,
	  0, N_("Create the initial window with the given geometry, "
		"see X(1) for the GEOMETRY format"),
	  N_("GEOMETRY")},
	{ "close", 'c', POPT_ARG_NONE, &close_option, 0,
	  N_("Close all Galeon windows"),
	  NULL },
	{ "quit", 'q', POPT_ARG_NONE, &quit_option, 0,
	  N_("Same as --close, but exits server mode too"),
	  NULL },
	{ "nautilus-view", 'v', POPT_ARG_NONE, &open_as_nautilus_view, 0,
	  N_("Used internally by the nautilus view"),
	  NULL },

	/* terminator, must be last */
	{ NULL, 0, 0, NULL, 0, NULL, NULL }
};

static gboolean
unref_when_idle (gpointer user_data)
{
	g_object_unref (user_data);
	return FALSE;
}

int
main (int argc, char *argv[])
{
	poptContext context;
        GValue context_as_value = { 0 };
	GnomeProgram *program;
	CORBA_Object factory;
	
#ifdef ENABLE_NLS
	/* Initialize the i18n stuff */
	setlocale(LC_ALL, "");
	bindtextdomain(GETTEXT_PACKAGE, DATADIR "/locale");
	textdomain(GETTEXT_PACKAGE);
#endif
	/* set the application name manually until gnome handles the
	 * GNOME_PARAM_HUMAN_READABLE_NAME in a sane fashion */
	g_set_application_name (_("Galeon"));

	program = gnome_program_init (PACKAGE, VERSION,
                                      LIBGNOMEUI_MODULE, argc, argv,
                                      GNOME_PARAM_POPT_TABLE, popt_options,
                                      GNOME_PARAM_HUMAN_READABLE_NAME, _("Galeon"),
				      GNOME_PARAM_APP_DATADIR, DATADIR,
                                      NULL);
#ifdef ENABLE_NLS
	bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
#endif

        g_object_get_property (G_OBJECT (program),
                               GNOME_PARAM_POPT_CONTEXT,
                               g_value_init (&context_as_value, G_TYPE_POINTER));

        context = g_value_get_pointer (&context_as_value);

	/* load arguments that aren't regular options (urls to load) */
        n_urls = galeon_main_translate_url_arguments (context, &url);

	g_value_unset (&context_as_value);

	factory = bonobo_activation_activate_from_id 
		(GALEON_FACTORY_OAFIID,
		 Bonobo_ACTIVATION_FLAG_EXISTING_ONLY, 
		 NULL, NULL);

	if (factory != NULL)
	{
		/* Connect to existing instance */
		galeon_main_start ();
		gdk_notify_startup_complete ();
	}
	else
	{
		galeon_debug_init ();

		gul_state_init ();
		
		gnome_vfs_init ();
		
		glade_init ();

		gnome_window_icon_set_default_from_file (DATADIR "/pixmaps/galeon.png");
		
		galeon_shell_new ();
		
		galeon_main_start ();

		/* Flush any pending GTK events, this works around crashes when
		 * it takes a long time to startup. */
		while (gtk_events_pending())
			gtk_main_iteration();
		
		galeon_automation_complete_initialization ();
		
		g_idle_add (unref_when_idle, galeon_shell);
		
		bonobo_main ();
		
		gul_state_shutdown ();

		gnome_accelerators_sync ();

		gnome_vfs_shutdown ();
	} 

	return 0;
}

static void
galeon_main_start (void)
{
	GNOME_GaleonAutomation gaserver;
	int i;

	CORBA_exception_init (&corba_env);
	
	gaserver = bonobo_activation_activate_from_id ("OAFIID:GNOME_Galeon_Automation",
						       0, NULL, &corba_env);
	
	if (corba_env._major != CORBA_NO_EXCEPTION)
	{
		g_warning ("Error: unable to initialize corba: %s\n", 
			   CORBA_exception_id (&corba_env));
	} 

	/* if none of the open in tab/window/existing options is given, fall
	 * back to open in a new window, otherwise the url can get opened in a
	 * different desktop without the user realizing it */
	if (!open_in_existing && !open_in_new_window && !open_in_new_tab)
	{
		open_in_new_window = TRUE;
	}

	if (gaserver == NULL)
	{
		/* At this point the galeon_shell will have initialized the
		 * AutomationFactory, that obviously worked, so the .server file
		 * exists, therefore this was probably because a previous instance
		 * locked up */

		GtkWidget *dialog;
		dialog = hig_alert_new (NULL,
					GTK_DIALOG_MODAL,
					HIG_ALERT_ERROR,
					_("Galeon failed to start."),
					_("The existing Galeon instance is not responding. "
					  "Terminating the <tt>\"galeon-bin\"</tt> processes "
					  "may fix the problem."),
					GTK_STOCK_OK,
					GTK_RESPONSE_OK,
					NULL);
		gtk_dialog_run (GTK_DIALOG (dialog));
		gtk_widget_destroy (dialog);
		exit(1);
	}
	/* Server mode */
	if (galeon_server_mode && !close_option)
	{
		GNOME_GaleonAutomation_setServerMode (gaserver, TRUE, &corba_env);
	}

	/* load the session if requested */
	if (session_filename)
	{
		GNOME_GaleonAutomation_loadSession 
			(gaserver, session_filename, &corba_env);
	}
	/* if found and we're given a bookmark to add... */
	else if (bookmark_url != NULL)
	{
		GNOME_GaleonAutomation_addBookmark 
			(gaserver, bookmark_url, &corba_env);
	}
	else if (close_option || quit_option)
	{
		GNOME_GaleonAutomation_quit 
			(gaserver, quit_option, &corba_env);
	}
	/* provided with urls? */
	else if (n_urls == 0 && 
		 !open_as_nautilus_view &&
		 !galeon_server_mode)
	{
		/* no, open a default window */
		GNOME_GaleonAutomation_loadurl 
			(gaserver, "",
			 geometry_string ?
			 geometry_string : "",
			 open_fullscreen,
			 open_in_existing,
			 open_in_new_window,
			 open_in_new_tab,
			 !noraise,
			 &corba_env);
	}
	else
	{
		/* open all of the urls */
		for (i = 0; i < n_urls; i++)
		{
			GNOME_GaleonAutomation_loadurl 
				(gaserver, url[i],
				 geometry_string ?
				 geometry_string : "",
				 open_fullscreen,
				 open_in_existing,
				 open_in_new_window,
				 open_in_new_tab,
				 !noraise,
				 &corba_env);
		}
	}

	if (gaserver)
	{
		bonobo_object_release_unref (gaserver, &corba_env);
	}

	CORBA_exception_free (&corba_env);
}

/**
 * translate_url_arguments: gather URL arguments and expand them fully
 * with realpath if they're filenames
 */
static gint
galeon_main_translate_url_arguments (poptContext context, gchar ***urls)
{
        gchar buffer[PATH_MAX];
        gchar **args;
        gint i, n;

        /* any context remaining? */
        if (context == NULL)
        {
                *urls = NULL;
                return 0;
        }

        /* get the args and check */
        args = (gchar **) poptGetArgs (context);
        if (args == NULL)
        {
                poptFreeContext (context);
                *urls = NULL;
                return 0;
        }

        /* count args */
        for (n = 0; args[n] != NULL; n++)
                /* nothing */;

        /* allocate pointer array */
        *urls = g_new0 (gchar *, n + 1);
        
        /* translate each one */
        for (i = 0; i < n; i++)
        {
                /* try to expand as files */
                if (realpath (args[i], buffer) != NULL)
                {
                        (*urls)[i] = g_strconcat ("file://", buffer, NULL);
                }
                else
                {
                        (*urls)[i] = g_strdup (args[i]);
                }
        }
        poptFreeContext (context);
        (*urls)[i] = NULL;

        /* return the number of urls */
        return n;
}
