/** -*- Mode: C++; tab-width: 4 -*-
 * vim: sw=4 ts=4:
 *
 * Gnome Apt main program
 *
 * 	(C) 1998 Havoc Pennington <hp@pobox.com>
 * 	    2002-2004 Filip Van Raemdonck <mechanix@debian.org>
 *
 * 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 of the
 * License, 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
 *
 * 	$Id$
 *
 **/

using namespace std;

#include <signal.h>
#include <gtk/gtk.h>
#include <libgnome/gnome-config.h>
#include <libgnomeui/gnome-ui-init.h>
#include <apt-pkg/cmndline.h>
#include <apt-pkg/error.h>
#include <apt-pkg/init.h>
#include <iostream>
#include <set>

#include "app.h"
#include "cache.h"
#include "cachecontrol.h"
#include "dialogprogress.h"
#include "gnome-apt.h"

/* Popt Stuff */

static const gchar* cmdline_geometry = 0;

static const struct poptOption options[] = {
  {"geometry", 'g', POPT_ARG_STRING, &cmdline_geometry, 0, 
   N_("Set initial main window size and position\n"
      "GEOMETRY is <width>x<height>+<x>+<y>.\n"), 
   N_("GEOMETRY")},
  {NULL, '\0', 0, NULL, 0}
};

// so we don't have to include these headers
// extern void gnome_apt_sources_shutdown();
extern void gnome_apt_preferences_shutdown();

static GtkWindow* main_window = 0;
static set<GtkWidget*> pending_dialogs;

static GtkWidget* gnome_apt_splash_new();
static GAptCacheFile* cf = 0;

GAptCacheFile*
gnome_apt_cache_file (void) {
	return cf;
}

int
main (int argc, char* argv[]) {
  // Ensure FILE* and iostreams don't get confused
  // I think this should maybe be in ios_base:: according to the standard...
  ios::sync_with_stdio();

	bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
	textdomain (GETTEXT_PACKAGE);

#ifdef GNOME_ENABLE_DEBUG
  int x = 1;
  ga_debug("Got arguments:");
  while (x < argc)
    {
      ga_debug("%d %s", x, argv[x]);
      ++x;
    }
#endif

	gnome_program_init (APPNAME, VERSION, LIBGNOMEUI_MODULE, argc, argv,
	      GNOME_PARAM_POPT_TABLE, options, GNOME_PROGRAM_STANDARD_PROPERTIES, NULL);

  gchar* geometry = 0;
  if (cmdline_geometry != 0)
    {
      geometry = g_strdup(cmdline_geometry);
      cmdline_geometry = 0;
    }

  CommandLine::Args Args[] = {
    {0,0,0,0}};
  
  // Parse the command line and initialize the package library
  CommandLine CmdL(Args,_config);
  if (pkgInitConfig(*_config) == false ||
      CmdL.Parse(argc, (const char **) argv) == false ||
      pkgInitSystem(*_config, _system) == false)
    {
      _error->DumpErrors();
      return 100;
    }
  
  // Print any errors or warnings found during parsing
  if (_error->empty() == false)
    {
      bool Errors = _error->PendingError();
      _error->DumpErrors();
      if (Errors == true)
        exit(EXIT_FAILURE);
    }
  
	GtkWidget* splash = gnome_apt_splash_new();
	gtk_widget_show_all (splash);

	cf = gnome_apt_cache_file_init (
	      OpDialogProgress (GTK_WIDGET (g_object_get_data (G_OBJECT (splash), "splash_vbox"))).This());

	if (cf) {
    GAptApp* app = new GAptApp(geometry);

    if (geometry) 
      {
        g_free(geometry);
        geometry = 0;
      }

    main_window = GTK_WINDOW(app->widget());

		gtk_widget_destroy (splash);
    if (gnome_config_get_bool("/gnome-apt/testing/alpha_warning=true"))
      {
			GtkWidget* warning = gtk_message_dialog_new (
				NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
				GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
				_("This is alpha software, and may damage your system.\n"
					"Use at your own risk.\n"
					"There is ABSOLUTELY NO WARRANTY; see the GPL for details."));
        gnome_apt_setup_dialog(warning);
			gtk_dialog_run (GTK_DIALOG (warning));
			gtk_widget_destroy (warning);
        gnome_config_set_bool("/gnome-apt/testing/alpha_warning", FALSE);
      }

		if (gnome_config_get_bool ("/gnome-apt/testing/wishlist_banner=true")) {
			GtkWidget* banner = gtk_message_dialog_new (NULL,
				GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO,
				GTK_BUTTONS_NONE,
				_("Gnome-Apt is currently in a state of flux.\n"
					"Since I'm redesigning and rewriting some of it's major components, "
					"now would be a very good time to file wishlist bugs on gnome-apt, "
					"and especially about the user interface."));
			gtk_dialog_add_buttons (GTK_DIALOG (banner),
				_("Don't show again"), GTK_RESPONSE_APPLY,
				GTK_STOCK_CLOSE, GTK_RESPONSE_NONE);
			gtk_dialog_set_default_response (GTK_DIALOG (banner), GTK_RESPONSE_NONE);
			gint ret = gtk_dialog_run (GTK_DIALOG (banner));
			gtk_widget_destroy (banner);
			if (ret == GTK_RESPONSE_APPLY) {
				gnome_config_set_bool ("/gnome-apt/testing/wishlist_banner", FALSE);
			}
		}

    set<GtkWidget*>::iterator i = pending_dialogs.begin();
    while (i != pending_dialogs.end())
      {
        gnome_apt_setup_dialog(*i);
        ++i;
      }
 
    pending_dialogs.clear();

		gapt_cache_control_check (GAPT_CACHE_CONTROL (gapt_cache_control_new (gnome_apt_cache_file())),
		      _("The packages installed on your system are currently in a broken state;"));
		gtk_main();

		delete app, cf;
		app = 0; cf = 0;

    //    gnome_apt_sources_shutdown();
    gnome_apt_preferences_shutdown();

		return 0;
	} else {
		string errmsg;
		_error->PopMessage (errmsg);
		gnome_apt_fatal_dialog (errmsg.c_str());

		gtk_widget_destroy (splash);
    return 1;
  }  
}

void 
gnome_apt_quit(void)
{
  g_warning("Quitting without asking first");
  
  g_return_if_fail(gtk_main_level() == 1);

  gtk_main_quit();
}

static GtkWidget*
error_dialog(const char* message)
{
  g_return_val_if_fail(message != 0, 0);

  string all_errors;

  all_errors += message;

  all_errors += _("\nThe following errors may help:\n");

  while (!_error->empty()) {
    string next;
    _error->PopMessage(next);

    // Chill the line length - bad hack for now.
    size_t i = 80;
    while (i < next.size())
      {
        next.insert(i, "\n");
        
        i += 80;
      }

    all_errors += next;
    all_errors += "\n";
  }
  
  cerr << all_errors << endl; // be sure it goes somewhere visible

	GtkWidget* dialog = gtk_message_dialog_new (
		NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR,
		GTK_BUTTONS_OK, all_errors.c_str());
	return dialog;
}

void 
gnome_apt_error_dialog(const char* message)
{
  GtkWidget* dialog = error_dialog(message);
  gnome_apt_setup_dialog(dialog);
	gtk_dialog_run (GTK_DIALOG (dialog));
	gtk_widget_destroy (dialog);
}

static gint 
dialog_close_cb(GtkWidget* w, gpointer data)
{
  gnome_apt_quit();
  return FALSE;
}

void 
gnome_apt_fatal_dialog(const char* message)
{
  GtkWidget* dialog = error_dialog(message);
  gnome_apt_setup_dialog(dialog);  

	g_signal_connect (G_OBJECT (dialog), "close", G_CALLBACK (dialog_close_cb), NULL);
	gtk_dialog_run (GTK_DIALOG (dialog));
	gtk_widget_destroy (dialog);
}

static void
dialog_destroy_cb(GtkWidget* dialog, gpointer data)
{
  set<GtkWidget*>::iterator i = pending_dialogs.find(dialog);

  if (i != pending_dialogs.end())
    pending_dialogs.erase(i);
}

void 
gnome_apt_setup_dialog(GtkWidget* dialog)
{
	g_return_if_fail (dialog != NULL);
	g_return_if_fail (GTK_IS_DIALOG (dialog));

  if (main_window == 0)
    {
      pending_dialogs.insert(dialog);
      // arrange to forget about closed dialogs
		g_signal_connect (G_OBJECT (dialog), "destroy", G_CALLBACK (dialog_destroy_cb), NULL);
	} else {
		gtk_window_set_transient_for (GTK_WINDOW (dialog), main_window);
	}
}

static void
splash_map (void) {
	gtk_window_set_auto_startup_notification (TRUE);
}

GtkWidget*
gnome_apt_splash_new()
{
  GtkWidget *pix;
  GtkWidget *box;
	GtkWidget *splash, *vbox;
  gchar* pixfile;

	splash = gtk_window_new (GTK_WINDOW_TOPLEVEL);
	gtk_window_set_type_hint (GTK_WINDOW (splash), GDK_WINDOW_TYPE_HINT_SPLASHSCREEN);
	gtk_window_set_title (GTK_WINDOW (splash), _("GNOME Apt Startup"));
	gtk_window_set_position (GTK_WINDOW (splash), GTK_WIN_POS_CENTER_ALWAYS);
	gtk_window_set_resizable (GTK_WINDOW (splash), FALSE);

	gtk_window_set_auto_startup_notification (FALSE);
	g_signal_connect (splash, "map", G_CALLBACK (splash_map), NULL);

	vbox = gtk_vbox_new (0, TRUE);
	gtk_container_add (GTK_CONTAINER (splash), vbox);
	g_object_set_data (G_OBJECT (splash), "splash_vbox", vbox);

  box = gtk_hbox_new(0,TRUE);
  gtk_widget_show(box);
	gtk_box_pack_start (GTK_BOX (vbox), box, FALSE, FALSE, 0);

	pixfile = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_PIXMAP, "gnome-apt-splash.png", TRUE, NULL);
  if (pixfile)
    {
		pix = gtk_image_new_from_file (pixfile);
      if (pix)
        {
          gtk_widget_show(pix);
          gtk_container_add(GTK_CONTAINER(box),pix);
        }
      g_free(pixfile);
    }

	gtk_widget_show_now (splash);
	return splash;
}

