/* This file is part of GQ
 *
 * AUTHORS
 *     Sven Herzberg  <herzi@gnome-de.org>
 *
 * Copyright (C) 2006  Sven Herzberg
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser 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
 */

#include "gq-diff-tab.h"

#include "gq-adjustment.h"
#include "gq-change-bar.h"
#include "gq-comparison.h"
#include "gq-input-form.h"
#include "gq-server-list.h"
#include "state.h"

struct GqDiffTabPrivate {
	GtkWidget* form1;
	GtkWidget* form2;
	GtkWidget* compare;
	GtkWidget* change1;
	GtkWidget* change2;

	GqAdjustment* hadj;
	GqAdjustment* vadj;
};
#define P(i) (G_TYPE_INSTANCE_GET_PRIVATE((i), GQ_TYPE_DIFF_TAB, struct GqDiffTabPrivate))

void
gq_diff_tab_set_entry(GqDiffTab * self     G_GNUC_UNUSED,
		      gint        position G_GNUC_UNUSED,
		      GqServerDn* entry    G_GNUC_UNUSED)
{
	g_return_if_fail(GQ_IS_DIFF_TAB(self));
	g_return_if_fail(0 <= position && position <= 1);
	g_return_if_fail(!entry || GQ_IS_SERVER_DN(entry));

	gq_input_form_set_entry(GQ_INPUT_FORM(position ? P(self)->form2 : P(self)->form1),
				entry);
}

/* GType */
G_DEFINE_TYPE(GqDiffTab, gq_diff_tab, GQ_TYPE_TAB);

static void
gq_diff_tab_init(GqDiffTab* self)
{
	GQ_TAB(self)->content = gtk_hbox_new(FALSE, 6);
	P(self)->form1 = gq_input_form_new();
	P(self)->form2 = gq_input_form_new();
	P(self)->compare = gq_comparison_new(GQ_INPUT_FORM(P(self)->form1),
					     GQ_INPUT_FORM(P(self)->form2));
	P(self)->change1 = gq_change_bar_new(GQ_COMPARISON(P(self)->compare),
					     GQ_INPUT_FORM(P(self)->form1));
	P(self)->change2 = gq_change_bar_new(GQ_COMPARISON(P(self)->compare),
					     GQ_INPUT_FORM(P(self)->form2));
	gtk_widget_show(P(self)->change1);
	gtk_box_pack_start(GTK_BOX(GQ_TAB(self)->content), P(self)->change1, FALSE, FALSE, 0);
	gtk_widget_show(P(self)->form1);
	gtk_box_pack_start_defaults(GTK_BOX(GQ_TAB(self)->content), P(self)->form1);

	gtk_widget_show(P(self)->compare);
	gtk_box_pack_start(GTK_BOX(GQ_TAB(self)->content), P(self)->compare, FALSE, FALSE, 0);

	gtk_widget_show(P(self)->form2);
	gtk_box_pack_start_defaults(GTK_BOX(GQ_TAB(self)->content), P(self)->form2);
	gtk_widget_show(GQ_TAB(self)->content);

	gtk_widget_show(P(self)->change2);
	gtk_box_pack_start(GTK_BOX(GQ_TAB(self)->content), P(self)->change2, FALSE, FALSE, 0);

	P(self)->hadj = gq_adjustment_new(GTK_SCROLLBAR(GTK_SCROLLED_WINDOW(gq_input_form_get_scrolled_window(GQ_INPUT_FORM(P(self)->form1)))->vscrollbar),
					  GTK_SCROLLBAR(GTK_SCROLLED_WINDOW(gq_input_form_get_scrolled_window(GQ_INPUT_FORM(P(self)->form2)))->vscrollbar));
	P(self)->vadj = gq_adjustment_new(GTK_SCROLLBAR(GTK_SCROLLED_WINDOW(gq_input_form_get_scrolled_window(GQ_INPUT_FORM(P(self)->form1)))->hscrollbar),
					  GTK_SCROLLBAR(GTK_SCROLLED_WINDOW(gq_input_form_get_scrolled_window(GQ_INPUT_FORM(P(self)->form2)))->hscrollbar));
}

static void
diff_tab_dispose(GObject* object)
{
	if(P(object)->hadj) {
		g_object_unref(P(object)->hadj);
		P(object)->hadj = NULL;
	}

	if(P(object)->vadj) {
		g_object_unref(P(object)->vadj);
		P(object)->vadj = NULL;
	}

	G_OBJECT_CLASS(gq_diff_tab_parent_class)->dispose(object);
}

static void
diff_tab_save_snapshot(gint   error_context G_GNUC_UNUSED,
		       gchar* state_name,
		       GqTab* tab)
{
	GqServerDn* entry = gq_input_form_get_entry(GQ_INPUT_FORM(P(tab)->form1));
	g_return_if_fail(entry);
	state_value_set_string(state_name, "server1", gq_server_get_name(gq_server_dn_get_server(entry)));
	state_value_set_string(state_name, "entry1",  gq_server_dn_get_dn(entry));
	entry = gq_input_form_get_entry(GQ_INPUT_FORM(P(tab)->form2));
	g_return_if_fail(entry);
	state_value_set_string(state_name, "server2", gq_server_get_name(gq_server_dn_get_server(entry)));
	state_value_set_string(state_name, "entry2",  gq_server_dn_get_dn(entry));
}

static void
diff_tab_restore_snapshot(gint             error_context G_GNUC_UNUSED,
			  gchar          * state_name,
			  GqTab          * tab,
			  struct pbar_win* progress      G_GNUC_UNUSED)
{
	gchar const* server = state_value_get_string(state_name, "server1", NULL);
	gchar const* dn     = state_value_get_string(state_name, "entry1",  NULL);

	if(!server || !*server || !dn) {
		g_warning("The config file didn't specify the first entry for comparison");
	}
	else {
		GqServerDn * entry = gq_server_dn_new(dn, gq_server_list_get_by_name(gq_server_list_get(), server));
		gq_input_form_set_entry(GQ_INPUT_FORM(P(tab)->form1), entry);
		g_object_unref(entry);
	}

	server = state_value_get_string(state_name, "server2", NULL);
	dn     = state_value_get_string(state_name, "entry2",  NULL);
	if(!server || !*server || !dn) {
		g_warning("The config file didn't specify the second entry for comparison");
	}
	else {
		GqServerDn * entry = gq_server_dn_new(dn, gq_server_list_get_by_name(gq_server_list_get(), server));
		gq_input_form_set_entry(GQ_INPUT_FORM(P(tab)->form2), entry);
		g_object_unref(entry);
	}
}

static void
gq_diff_tab_class_init(GqDiffTabClass* self_class)
{
	GObjectClass* object_class = G_OBJECT_CLASS(self_class);
	GqTabClass  * tab_class = GQ_TAB_CLASS(self_class);

	/* GObjectClass */
	object_class->dispose = diff_tab_dispose;

	/* GqTabClass */
	tab_class->save_snapshot    = diff_tab_save_snapshot;
	tab_class->restore_snapshot = diff_tab_restore_snapshot;

	/* GqDiffTabClass */
	g_type_class_add_private(self_class, sizeof(struct GqDiffTabPrivate));
}

