/*
 *  Copyright (C) 2003 Philip Langdale
 *
 *  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 "bookmarks-add-dialog.h"
#include "bookmarks-tree-view.h"
#include "bookmarks-tree-model.h"

#include "gul-state.h"

#include <gtk/gtkwindow.h>
#include <gtk/gtkentry.h>
#include <gtk/gtklabel.h>
#include <gtk/gtktreeselection.h>
#include <glib/gi18n.h>

static void gb_add_dialog_class_init(GbAddDialogClass *klass);
static void gb_add_dialog_init(GbAddDialog *dialog);
static void gb_add_dialog_finalize(GObject *object);
static void gb_add_dialog_show(GaleonDialog *dialog);

static void
gb_add_dialog_get_property(GObject *object,
             	           guint prop_id,
                           GValue *value,
                           GParamSpec *pspec);
static void
gb_add_dialog_set_property(GObject *object,
             	           guint prop_id,
                           const GValue *value,
                           GParamSpec *pspec);

void gb_add_dialog_ok_clicked_cb(GtkWidget *widget,
				 GbAddDialog *dialog);
void gb_add_dialog_cancel_clicked_cb(GtkWidget *widget,
				     GbAddDialog *dialog);

GtkWidget *
gb_add_dialog_glade_treeview_helper(gchar *widget_name,
				    gchar *string1, gchar *string2,
				    gint int1, gint int2);

enum
{
	PROP_0,
	PROP_BOOKMARK_SET,
	PROP_SITES
};

enum
{
	PROP_DIALOG,

	PROP_NAME,
	PROP_LOCATION,
	PROP_LOCATION_LABEL,
	PROP_TREEVIEW,
	PROP_FOLDER_LABEL
};

static GObjectClass *parent_class = NULL;

struct _GbAddDialogPrivate
{
	GbBookmarkSet *set;

	GtkEntry *name;
	GtkEntry *location;
	GtkLabel *location_label;
	GbTreeView *treeview;

	GSList *sites;
};

static const
GaleonDialogProperty properties [] =
{
	{ PROP_DIALOG,         "bookmark_add_dialog",         NULL, PT_NORMAL, NULL },

	{ PROP_NAME,           "bookmark_add_name",           NULL, PT_NORMAL, NULL },
	{ PROP_LOCATION,       "bookmark_add_location",       NULL, PT_NORMAL, NULL },
	{ PROP_LOCATION_LABEL, "bookmark_add_location_label", NULL, PT_NORMAL, NULL },
	{ PROP_TREEVIEW,       "bookmark_add_treeview",       NULL, PT_NORMAL, NULL },
	{ PROP_FOLDER_LABEL,   "bookmark_add_folder_label",   NULL, PT_NORMAL, NULL },

	{ -1, NULL, NULL }
};

GType 
gb_add_dialog_get_type(void)
{
        static GType gb_add_dialog_type = 0;

        if (gb_add_dialog_type == 0)
        {
                static const GTypeInfo our_info =
                {
                        sizeof (GbAddDialogClass),
                        NULL, /* base_init */
                        NULL, /* base_finalize */
                        (GClassInitFunc) gb_add_dialog_class_init,
                        NULL,
                        NULL, /* class_data */
                        sizeof (GbAddDialog),
                        0, /* n_preallocs */
                        (GInstanceInitFunc) gb_add_dialog_init
                };

                gb_add_dialog_type = g_type_register_static(GALEON_DIALOG_TYPE,
						            "GbAddDialog",
						            &our_info, 0);
        }

        return gb_add_dialog_type;

}

static void
gb_add_dialog_class_init (GbAddDialogClass *klass)
{
        GObjectClass *object_class = G_OBJECT_CLASS(klass);
	GaleonDialogClass *dialog_class = GALEON_DIALOG_CLASS(klass);

        parent_class = g_type_class_peek_parent(klass);

	object_class->set_property = gb_add_dialog_set_property;
	object_class->get_property = gb_add_dialog_get_property;

        object_class->finalize = gb_add_dialog_finalize;
        dialog_class->show = gb_add_dialog_show;

	g_object_class_install_property(object_class,
                                        PROP_BOOKMARK_SET,
                                        g_param_spec_object("BookmarkSet",
                                                            "BookmarkSet",
                                                            "Bookmark Set",
                                                            GB_TYPE_BOOKMARK_SET,
                                                            G_PARAM_READWRITE));
	g_object_class_install_property(object_class,
                                        PROP_SITES,
                                        g_param_spec_pointer("Sites",
                                                             "Sites",
                                                             "Bookmark Sites",
                                                             G_PARAM_READWRITE));

}

static void
gb_add_dialog_init(GbAddDialog *dialog)
{	
	GtkLabel *folder_label;

	dialog->priv = g_new0(GbAddDialogPrivate, 1);

	galeon_dialog_construct(GALEON_DIALOG(dialog),
                                properties,
                                "bookmarks.glade",
                                "bookmark_add_dialog");

	gul_state_monitor_window
		(galeon_dialog_get_control(GALEON_DIALOG(dialog), PROP_DIALOG),
		 "BookmarkAdd", -1, -1);

	dialog->priv->treeview = GB_TREE_VIEW(galeon_dialog_get_control(
					      GALEON_DIALOG(dialog),
					      PROP_TREEVIEW));
	dialog->priv->name = GTK_ENTRY(galeon_dialog_get_control(
				       GALEON_DIALOG(dialog),
				       PROP_NAME));
	dialog->priv->location = GTK_ENTRY(galeon_dialog_get_control(
					   GALEON_DIALOG(dialog),
					   PROP_LOCATION));
	dialog->priv->location_label = GTK_LABEL(galeon_dialog_get_control(
						 GALEON_DIALOG(dialog),
						 PROP_LOCATION_LABEL));

	/* libglade is dumb and cannot associate a mnemonic with a custom
	 * widget, so we have to do it manually. The actual accel can be
	 * attached to the treeview in glade and we have done so
	 */
	folder_label = GTK_LABEL(galeon_dialog_get_control(
				 GALEON_DIALOG(dialog),
				 PROP_FOLDER_LABEL));

	gtk_label_set_mnemonic_widget(folder_label,
				      GTK_WIDGET(dialog->priv->treeview));
}

static void
gb_add_dialog_finalize (GObject *object)
{
	GbAddDialog *dialog;
	GSList *i;

        g_return_if_fail(object != NULL);
        g_return_if_fail(GB_IS_ADD_DIALOG (object));

	dialog = GB_ADD_DIALOG(object);

        g_return_if_fail(dialog->priv != NULL);

	for (i = dialog->priv->sites ; i ; i = i->next)
	{
		/* Each site object is automatically ref'ed
		 * on creation but when added to a folder
		 * an additional ref is made; so remove
		 * the first ref now.
		 */
		g_object_unref(i->data);
	}
	g_slist_free(dialog->priv->sites);

        g_free(dialog->priv);

        G_OBJECT_CLASS(parent_class)->finalize (object);
}


static void
gb_add_dialog_show(GaleonDialog *dialog)
{
	GbAddDialog *d = GB_ADD_DIALOG(dialog);
	GtkEntry *name = d->priv->name;
	GtkEntry *location = d->priv->location;
	GSList *sites = d->priv->sites;
	GbBookmarkSet *set = d->priv->set;
	GbTreeView *treeview = d->priv->treeview;
	GbTreeModel *model;
	GtkTreeSelection *selection;

	g_assert(set);
	g_assert(sites && g_slist_length(sites) > 0);

	model = gb_tree_model_new_for_set(set);

	gb_tree_model_set_only_folders(model, TRUE);

	gb_tree_view_set_model(treeview,
			       model);

	gb_tree_view_set_location_visible(treeview,
					  FALSE);

	gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview),
					  FALSE);

	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
	gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);

	gb_tree_view_select(treeview, GB_BOOKMARK(set->default_folder));

	if (g_slist_length(sites) == 1)
	{
		GbSite *b = GB_SITE(sites->data);
		gtk_entry_set_text(name, GB_BOOKMARK(b)->name);
		gtk_entry_set_text(location, b->url);
	}
	else
	{
		GtkWidget *dialog_widget;
		gtk_widget_hide(GTK_WIDGET(location));
		gtk_widget_hide(GTK_WIDGET(d->priv->location_label));

		dialog_widget = galeon_dialog_get_control(dialog,
							  PROP_DIALOG);

		gtk_window_set_title(GTK_WINDOW(dialog_widget),
				     _("Add Tabs As Folder"));
		gtk_entry_set_text(name, _("New Folder"));
	}

	gtk_editable_set_position(GTK_EDITABLE(name), -1);
	gtk_widget_grab_focus(GTK_WIDGET(name));

        GALEON_DIALOG_CLASS(parent_class)->show(dialog);
}

GaleonDialog *
gb_add_dialog_new(GtkWidget *window, GbBookmarkSet *set, GSList *sites)
{
	GbAddDialog *dialog;
	
	dialog = GB_ADD_DIALOG(g_object_new(GB_ADD_DIALOG_TYPE,
			       "ParentWindow", window,
			       "BookmarkSet", set,
			       "Sites", sites,
			       NULL));

	return GALEON_DIALOG(dialog);
}

static void
gb_add_dialog_set_property(GObject *object,
	                   guint prop_id,
	                   const GValue *value,
	                   GParamSpec *pspec)
{
        GbAddDialog *d = GB_ADD_DIALOG(object);

        switch (prop_id)
        {
                case PROP_BOOKMARK_SET:
                        d->priv->set = g_value_get_object(value);
                        break;
                case PROP_SITES:
                	d->priv->sites = g_value_get_pointer(value);
        }
}

static void
gb_add_dialog_get_property(GObject *object,
	             	   guint prop_id,
	                   GValue *value,
	                   GParamSpec *pspec)
{
        GbAddDialog *d = GB_ADD_DIALOG(object);

        switch (prop_id)
        {
                case PROP_BOOKMARK_SET:
                        g_value_set_object(value, d->priv->set);
                        break;
                case PROP_SITES:
                	g_value_set_pointer(value, d->priv->sites);
                	break;
        }
}

void
gb_add_dialog_ok_clicked_cb(GtkWidget *widget,
			    GbAddDialog *d)
{
	const gchar *name = gtk_entry_get_text(d->priv->name);
	const gchar *location = gtk_entry_get_text(d->priv->location);
	const GSList *l = gb_tree_view_get_selected_list(d->priv->treeview);
	GbFolder *folder = GB_FOLDER(l->data);
	GbBookmarkSet *set = d->priv->set;
	GSList *i, *sites = d->priv->sites;

	if (g_slist_length(sites) == 1)
	{
		GbSite *b = GB_SITE(sites->data);
		gb_bookmark_set_name(GB_BOOKMARK(b), name);
		gb_site_set_url(b, location);

		gb_folder_add_child(folder, GB_BOOKMARK(b), -1);
		gb_bookmark_set_time_added_now(GB_BOOKMARK(b));
		gb_site_set_time_visited_now(b);
	}
	else /* dialog_show asserted non-zero num_sites */
	{
		GbFolder *group = gb_folder_new(set, name);
		gb_folder_add_child(folder, GB_BOOKMARK(group), -1);
		gb_bookmark_set_time_added_now(GB_BOOKMARK(group));

		for (i = sites ; i ; i = i->next)
		{
			GbSite *b = GB_SITE(i->data);

			gb_folder_add_child(group, GB_BOOKMARK(b), -1);
			gb_bookmark_set_time_added_now(GB_BOOKMARK(b));
			gb_site_set_time_visited_now(b);
		}
		g_object_unref(group);
	}

	g_object_unref(d);
}

void
gb_add_dialog_cancel_clicked_cb(GtkWidget *widget,
				GbAddDialog *dialog)
{
	g_object_unref(dialog);
}
				     
GtkWidget *
gb_add_dialog_glade_treeview_helper(gchar *widget_name,
				    gchar *string1, gchar *string2,
				    gint int1, gint int2)
{
	GbTreeView *treeview = gb_tree_view_new();

	gtk_widget_show(GTK_WIDGET(treeview));
	return GTK_WIDGET(treeview);
}
