/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/*
 *  Copyright (C) 2003 Takuro Ashie
 *
 *  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.
 */

#include "prefs_rss.h"

#include <stdlib.h>
#include <string.h>

#include "kz-rss.h"
#include "kz-rsslist.h"
#include "utils/intl.h"
#include "utils/gtk-utils.h"

#define DATA_KEY "KzPrefsRSS::info"


enum
{
	COLUMN_TERMINATOR = -1,
	COLUMN_TITLE,
	COLUMN_URI,
	COLUMN_INTERVAL,
	COLUMN_EDITABLE,
	COLUMN_RSS,
	N_COLUMNS
};


typedef struct _KzPrefsRSS
{
	GtkWidget     *main_vbox;
	GtkTreeView   *tree_view;
	GtkListStore  *store;
	GtkWidget     *up;
	GtkWidget     *down;
	GtkWidget     *add;
	GtkWidget     *remove;
	KzRSSList     *rsslist;
	gboolean       changed;
} KzPrefsRSS;


static GtkWidget     *prefs_rss_create          (void);
static void           prefs_rss_response        (GtkWidget *widget,
						 gint       response);
static void           prefs_rss_set_sensitive   (KzPrefsRSS *prefsui);
static void           prefs_rss_destroy         (gpointer data);


static KzPrefsWinPageEntry prefs_entry =
{
	path:            N_("/RSS"),
	priority_hint:   0,
	create:          prefs_rss_create,
	response:        prefs_rss_response,
};


static void
cb_up_button (GtkButton *button, KzPrefsRSS *prefsui)
{
	GtkTreeSelection *selection;
	GtkTreeModel *model;
	GtkTreeIter iter, prev;
	GtkTreePath *treepath;

	g_return_if_fail(prefsui);

	selection = gtk_tree_view_get_selection (prefsui->tree_view);
	if (!gtk_tree_selection_get_selected (selection, &model, &iter))
		return;

	treepath = gtk_tree_model_get_path(model, &iter);
	if (!gtk_tree_path_prev(treepath)) goto ERROR;
	gtk_tree_model_get_iter(model, &prev, treepath);

	gtkutil_list_store_swap(prefsui->store, &iter, &prev);

	prefsui->changed = TRUE;

ERROR:
	gtk_tree_path_free(treepath);

	prefs_rss_set_sensitive (prefsui);
}


static void
cb_down_button (GtkButton *button, KzPrefsRSS *prefsui)
{
	GtkTreeSelection *selection;
	GtkTreeModel *model;
	GtkTreeIter iter, next;

	g_return_if_fail(prefsui);

	selection = gtk_tree_view_get_selection (prefsui->tree_view);
	if (!gtk_tree_selection_get_selected (selection, &model, &iter))
		return;

	next = iter;
	if (!gtk_tree_model_iter_next(model, &next)) return;

	gtkutil_list_store_swap(prefsui->store, &iter, &next);

	prefsui->changed = TRUE;

	prefs_rss_set_sensitive (prefsui);
}


static void
cb_add_button (GtkButton *button, KzPrefsRSS *prefsui)
{
	GtkTreeIter iter;
	GtkTreePath *treepath;

	g_return_if_fail(prefsui);

	gtk_list_store_append(prefsui->store, &iter);
	gtk_list_store_set(prefsui->store, &iter,
			   COLUMN_TITLE,    _("Example"),
			   COLUMN_URI,      "http://",
			   COLUMN_INTERVAL, "0",
			   COLUMN_EDITABLE, TRUE,
			   COLUMN_TERMINATOR);

	treepath = gtk_tree_model_get_path(GTK_TREE_MODEL(prefsui->store),
					   &iter);
	gtk_tree_view_set_cursor(prefsui->tree_view,
				 treepath, NULL, FALSE);
	gtk_tree_path_free(treepath);

	prefsui->changed = TRUE;

	prefs_rss_set_sensitive (prefsui);
}


static void
cb_remove_button (GtkButton *button, KzPrefsRSS *prefsui)
{
	GtkTreeSelection *selection;
	GtkTreeModel *model;
	GtkTreeIter iter, next;
	GtkTreePath *treepath;
	gboolean select;

	g_return_if_fail(prefsui);

	selection = gtk_tree_view_get_selection (prefsui->tree_view);
	if (!gtk_tree_selection_get_selected (selection, &model, &iter))
		return;

	/* get next row to select */
	next = iter;
	select = gtk_tree_model_iter_next(model, &next);
	if (select)
	{
		treepath = gtk_tree_model_get_path(model, &next);
	}
	else
	{
		treepath = gtk_tree_model_get_path(model, &iter);
		select = gtk_tree_path_prev(treepath);
	}
	if (select)
		gtk_tree_view_set_cursor(prefsui->tree_view,
					 treepath, NULL, FALSE);
	gtk_tree_path_free(treepath);

	/* remove the row */
	gtk_list_store_remove(prefsui->store, &iter);

	prefsui->changed = TRUE;

	prefs_rss_set_sensitive (prefsui);
}


static void
cb_title_edited (GtkCellRendererText *cell,
		 const gchar *path_str,
		 const gchar *new_text,
		 KzPrefsRSS *prefsui)
{
        GtkTreeIter  iter;

        gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(prefsui->store),
					    &iter, path_str);
	gtk_list_store_set(prefsui->store, &iter,
			   COLUMN_TITLE, new_text,
			   COLUMN_TERMINATOR);

	prefsui->changed = TRUE;

	prefs_rss_set_sensitive (prefsui);
}


static void
cb_uri_edited (GtkCellRendererText *cell,
	       const gchar *path_str,
	       const gchar *new_text,
	       KzPrefsRSS *prefsui)
{
        GtkTreeIter  iter;

        gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(prefsui->store),
					    &iter, path_str);
	gtk_list_store_set(prefsui->store, &iter,
			   COLUMN_URI, new_text,
			   COLUMN_TERMINATOR);

	prefsui->changed = TRUE;

	prefs_rss_set_sensitive (prefsui);
}


static void
cb_interval_edited (GtkCellRendererText *cell,
		    const gchar *path_str,
		    const gchar *new_text,
		    KzPrefsRSS *prefsui)
{
        GtkTreeIter  iter;
	gint i;

#warning FIXME!! use special cell renderer.
	for (i = 0; i < strlen(new_text); i++)
	{
		if (!g_ascii_isdigit(new_text[i]))
		{
			new_text = "0";
			break;
		}
	}

        gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(prefsui->store),
					    &iter, path_str);
	gtk_list_store_set(prefsui->store, &iter,
			   COLUMN_INTERVAL, new_text,
			   COLUMN_TERMINATOR);

	prefsui->changed = TRUE;

	prefs_rss_set_sensitive (prefsui);
}


static void
cb_cursor_changed(GtkTreeView *tree_view, KzPrefsRSS *prefsui)
{
	g_return_if_fail(prefsui);
	prefs_rss_set_sensitive (prefsui);
}


static GtkWidget *
prefs_rss_create (void)
{
	KzPrefsRSS *prefsui = g_new0(KzPrefsRSS, 1);
	GtkWidget *main_vbox, *hbox;
	GtkWidget *label, *scrwin, *tree_view, *button;
	GtkListStore *store;
	GtkCellRenderer *cell;
	GtkTreeViewColumn *column;
	GSList *node;

	prefsui->changed = FALSE;

	main_vbox = gtk_vbox_new(FALSE, 0);
	prefsui->main_vbox = main_vbox;
	g_object_set_data_full(G_OBJECT(main_vbox), DATA_KEY,
			       prefsui, prefs_rss_destroy);

	label = kz_prefs_ui_utils_create_title(_("RSS/RDF"));
	gtk_box_pack_start(GTK_BOX(main_vbox), label,
			   FALSE, FALSE, 0);
	gtk_widget_show(label);

	/* scrolled window */
	scrwin = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrwin),
				       GTK_POLICY_AUTOMATIC,
				       GTK_POLICY_AUTOMATIC);
        gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrwin),
					    GTK_SHADOW_IN);
	gtk_container_set_border_width(GTK_CONTAINER(scrwin), 5);
	gtk_box_pack_start(GTK_BOX(main_vbox), scrwin, TRUE, TRUE, 0);
	gtk_widget_show(scrwin);

	/* tree view */
	store = gtk_list_store_new(N_COLUMNS,
				   G_TYPE_STRING,
				   G_TYPE_STRING,
				   G_TYPE_STRING,
				   G_TYPE_BOOLEAN,
				   KZ_TYPE_RSS);
	prefsui->store = store;

	tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
	prefsui->tree_view = GTK_TREE_VIEW(tree_view);
	gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (tree_view), TRUE);

	/* Title column */
	cell = gtk_cell_renderer_text_new();
	g_signal_connect(G_OBJECT(cell), "edited",
			 G_CALLBACK(cb_title_edited), prefsui);
	column = gtk_tree_view_column_new_with_attributes
			(_("Title"), cell,
			 "text",     COLUMN_TITLE,
			 "editable", COLUMN_EDITABLE,
			 NULL);
	gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
	gtk_tree_view_column_set_fixed_width (column, 100);
	gtk_tree_view_column_set_resizable(column, TRUE);
	gtk_tree_view_append_column(prefsui->tree_view, column);

	/* URI column */
	cell = gtk_cell_renderer_text_new();
	g_signal_connect(G_OBJECT(cell), "edited",
			 G_CALLBACK(cb_uri_edited), prefsui);
	column = gtk_tree_view_column_new_with_attributes
			(_("URI"), cell,
			 "text",     COLUMN_URI,
			 "editable", COLUMN_EDITABLE,
			 NULL);
	gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
	gtk_tree_view_column_set_fixed_width (column, 250);
	gtk_tree_view_column_set_resizable(column, TRUE);
	gtk_tree_view_append_column(prefsui->tree_view, column);

	/* Interval column */
	cell = gtk_cell_renderer_text_new();
	g_object_set(G_OBJECT(cell), "xalign", 0.8, NULL);
	g_signal_connect(G_OBJECT(cell), "edited",
			 G_CALLBACK(cb_interval_edited), prefsui);
	column = gtk_tree_view_column_new_with_attributes
			(_("Interval (min)"), cell,
			 "text",     COLUMN_INTERVAL,
			 "editable", COLUMN_EDITABLE,
			 NULL);
	g_object_set(G_OBJECT(column), "alignment", 0.5, NULL);
	gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
	gtk_tree_view_column_set_fixed_width (column, 30);
	gtk_tree_view_column_set_resizable(column, TRUE);
	gtk_tree_view_append_column(prefsui->tree_view, column);

	/* set default value */
	prefsui->rsslist = kz_rss_list_get_instance();
	for (node = prefsui->rsslist->items; node; node = g_slist_next(node))
	{
		KzRSS *rss = node->data;
		GtkTreeIter iter;
		gchar buf[32];

		g_snprintf(buf, sizeof(buf) / sizeof(gchar), "%d",
			   rss->update_interval);

		gtk_list_store_append(store, &iter);
		gtk_list_store_set(store, &iter,
				   COLUMN_TITLE,    rss->title,
				   COLUMN_URI,      rss->uri,
				   COLUMN_INTERVAL, buf,
				   COLUMN_EDITABLE, TRUE,
				   COLUMN_RSS,      rss,
				   COLUMN_TERMINATOR);
	}

	gtk_container_add(GTK_CONTAINER(scrwin), tree_view);
	gtk_widget_show(tree_view);

	/* button box */
	hbox = gtk_hbutton_box_new();
	gtk_box_pack_start(GTK_BOX(main_vbox), hbox, FALSE, FALSE, 0);
	gtk_container_set_border_width(GTK_CONTAINER(hbox), 5);
	gtk_widget_show(hbox);

	/* up button */
	button = gtk_button_new_from_stock(GTK_STOCK_GO_UP);
	prefsui->up = button;
	gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
	g_signal_connect(G_OBJECT(button), "clicked",
			 G_CALLBACK(cb_up_button), prefsui);
	gtk_widget_show(button);

	/* down button */
	button = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN);
	prefsui->down = button;
	gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
	g_signal_connect(G_OBJECT(button), "clicked",
			 G_CALLBACK(cb_down_button), prefsui);
	gtk_widget_show(button);

	/* add button */
	button = gtk_button_new_from_stock(GTK_STOCK_ADD);
	prefsui->add = button;
	gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
	g_signal_connect(G_OBJECT(button), "clicked",
			 G_CALLBACK(cb_add_button), prefsui);
	gtk_widget_show(button);

	/* remove button */
	button = gtk_button_new_from_stock(GTK_STOCK_REMOVE);
	prefsui->remove = button;
	gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
	g_signal_connect(G_OBJECT(button), "clicked",
			 G_CALLBACK(cb_remove_button), prefsui);
	gtk_widget_show(button);

	/* signal handler for GtkTreeView */
	g_signal_connect(G_OBJECT(tree_view), "cursor-changed",
			 G_CALLBACK(cb_cursor_changed), prefsui);

	prefs_rss_set_sensitive (prefsui);

	return main_vbox;
}



static void
prefs_rss_apply (KzPrefsRSS *prefsui)
{
	GtkTreeModel *model = GTK_TREE_MODEL(prefsui->store);
	GtkTreeIter iter;
	GSList *new_list = NULL;
	gboolean exist;

	if (!prefsui->changed) return;

	exist = gtk_tree_model_get_iter_first(model, &iter);
	while (exist)
	{
		KzRSS *rss = NULL;
		gchar *title = NULL, *uri = NULL, *interval_str = NULL;
		gint interval = 0;

		gtk_tree_model_get(model, &iter,
				   COLUMN_TITLE,    &title,
				   COLUMN_URI,      &uri,
				   COLUMN_INTERVAL, &interval_str,
				   COLUMN_RSS,      &rss,
				   COLUMN_TERMINATOR);
		if (interval_str)
			interval = atoi(interval_str);

		if (rss)
		{
			g_object_ref(rss);
		        g_object_set(G_OBJECT(rss),
				     "title",    title,
				     "uri",      uri,
				     "interval", interval,
				     NULL);
		}
		else
		{
			rss = kz_rss_new(uri, title, interval);
		}
		new_list = g_slist_append(new_list, rss);

		g_free(title);
		g_free(uri);
		g_free(interval_str);

		exist = gtk_tree_model_iter_next(model, &iter);
	}

	kz_rss_list_set_list(prefsui->rsslist, new_list);
	kz_rss_list_save(prefsui->rsslist);

	g_slist_foreach(new_list, (GFunc) g_object_unref, NULL);
	g_slist_free(new_list);

	prefsui->changed = FALSE;

	prefs_rss_set_sensitive (prefsui);
}


static void
prefs_rss_response (GtkWidget *widget, gint response)
{
	KzPrefsRSS *prefsui = g_object_get_data(G_OBJECT(widget), DATA_KEY);

	g_return_if_fail(prefsui);

	switch (response) {
	case GTK_RESPONSE_ACCEPT:
	case GTK_RESPONSE_APPLY:
		prefs_rss_apply(prefsui);
		break;
	case GTK_RESPONSE_REJECT:
		break;
	default:
		break;
	}
}


static void
prefs_rss_set_sensitive (KzPrefsRSS *prefsui)
{
	GtkTreeSelection *selection;
	GtkTreeModel *model;
	GtkTreeIter iter, next;
	gboolean select, can_up = FALSE, can_down = FALSE;

	g_return_if_fail(prefsui);

	selection = gtk_tree_view_get_selection (prefsui->tree_view);
	select = gtk_tree_selection_get_selected (selection, &model, &iter);

	if (select)
	{
		GtkTreePath *treepath;

		next = iter;
		can_down = gtk_tree_model_iter_next(model, &next);

		treepath = gtk_tree_model_get_path(model, &iter);
		can_up = gtk_tree_path_prev(treepath);
		gtk_tree_path_free(treepath);
	}

	gtk_widget_set_sensitive(prefsui->up,     can_up);
	gtk_widget_set_sensitive(prefsui->down,   can_down);
	gtk_widget_set_sensitive(prefsui->remove, select);
}


static void
prefs_rss_destroy (gpointer data)
{
	KzPrefsRSS *prefsui = data;

	if (prefsui->rsslist)
	{
		g_object_unref(prefsui->rsslist);
		prefsui->rsslist = NULL;
	}

	g_free(prefsui);
}


KzPrefsWinPageEntry *
prefs_rss_get_entry (gint idx)
{
	if (idx == 0)
		return &prefs_entry;
	else
		return NULL;
}
