/*
 *  Copyright (C) 2004 Mathias Andre <mathias@openbrookes.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.
 *
 */

#include <glib.h>
#include <gtk/gtk.h>
#include <glade/glade.h>
#include <string.h>

#include "../nb_global.h"
#include "../nb_note.h"
#include "../nb_util.h"
#include "nb_ui_treeview.h"
#include "nb_ui_interface.h"
#include "nb_ui_attachment_view.h"
#include "nb_ui_note_view.h"

/* privates functions */
static void 	nb_ui_note_view_scan_url_tag_from_textview (GtkTextBuffer * buffer, gpointer user_data);

void
nb_ui_note_view_create (void)
{
	/* create the links tag for the text view and set wrap mode */
	extern GladeXML * xml;
	GtkTextTag * tag;
	GtkWidget * textview = glade_xml_get_widget (xml, "textview");
	GtkTextBuffer * buffer = gtk_text_view_get_buffer ( GTK_TEXT_VIEW (textview) );
	CursorList * cursors = g_malloc (sizeof (CursorList));

	/* create the mouse cursors */
	cursors->hand_cursor = gdk_cursor_new (GDK_HAND2);
	cursors->text_cursor = gdk_cursor_new (GDK_XTERM);
	cursors->current_cursor = GDK_XTERM;

	g_object_set_data ( G_OBJECT (textview), "cursors", cursors);

	gtk_text_view_set_wrap_mode ( GTK_TEXT_VIEW (textview), GTK_WRAP_WORD_CHAR);

	tag = gtk_text_buffer_create_tag (buffer, "links", "foreground", "blue", "underline", PANGO_UNDERLINE_SINGLE, NULL);

	g_signal_connect ( G_OBJECT (buffer), "changed", G_CALLBACK (nb_ui_note_view_scan_url_tag_from_textview), NULL);

	/* used to set up de date field */
	nb_ui_note_view_reset ();
	
	/* initialise the attachment view */
	nb_ui_attachment_view_create ();
}

void
nb_ui_note_view_set_cursor_if_appropriate (GtkTextView * textview, gint x, gint y)
{
	GtkTextBuffer * buffer;
	GtkTextIter iter;
	GtkTextTagTable * table;
	GtkTextTag * tag;
	CursorList * cursors = g_object_get_data ( G_OBJECT (textview), "cursors");

	buffer = gtk_text_view_get_buffer (textview);

	gtk_text_view_get_iter_at_location (textview, &iter, x, y);

	table = gtk_text_buffer_get_tag_table (buffer);

	tag = gtk_text_tag_table_lookup (table, "links");

	if ( gtk_text_iter_has_tag (&iter, tag) && (cursors->current_cursor != GDK_HAND2))
		gdk_window_set_cursor (gtk_text_view_get_window (textview, GTK_TEXT_WINDOW_TEXT), cursors->hand_cursor);
	else
		gdk_window_set_cursor (gtk_text_view_get_window (textview, GTK_TEXT_WINDOW_TEXT), cursors->text_cursor);
}

void	
nb_ui_note_view_reset (void)
{
	extern GladeXML * xml;
	GtkWidget * option_menu_type = glade_xml_get_widget (xml, "option_menu_type");
	GtkWidget * option_menu_status = glade_xml_get_widget (xml, "option_menu_status");
	GtkWidget * entry_subject = glade_xml_get_widget (xml, "entry_subject");
	GtkWidget * textview = glade_xml_get_widget (xml, "textview");
	GtkWidget * note = glade_xml_get_widget (xml, "note1");
	GtkWidget * none = glade_xml_get_widget (xml, "none1");
	GtkWidget * date = glade_xml_get_widget (xml, "label_date_value");
	GtkWidget * treeview = glade_xml_get_widget(xml, "treeview");
	GtkTreeSelection * selection;
	GtkTextBuffer * buffer = gtk_text_view_get_buffer ( GTK_TEXT_VIEW (textview) );

	/* reset option menus to default values */
	gtk_option_menu_set_history ( GTK_OPTION_MENU (option_menu_type), NOTE);
	gtk_option_menu_set_history ( GTK_OPTION_MENU (option_menu_status), NONE);

	gtk_text_buffer_set_text (buffer, "", 0);
	gtk_text_view_set_buffer ( GTK_TEXT_VIEW (textview) , buffer);
	gtk_entry_set_text ( GTK_ENTRY (entry_subject) , "");
	gtk_option_menu_set_menu ( GTK_OPTION_MENU (option_menu_type) , note);
	gtk_option_menu_set_menu ( GTK_OPTION_MENU (option_menu_status) , none);
	gtk_label_set_text ( GTK_LABEL (date) , nb_util_get_date_string (NULL));

	selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW (treeview));
	g_signal_handlers_block_by_func ( G_OBJECT (selection), nb_ui_treeview_cb_selection_changed, NULL);
	gtk_tree_selection_unselect_all (selection);
	g_signal_handlers_unblock_by_func ( G_OBJECT (selection), nb_ui_treeview_cb_selection_changed, NULL);
}

gboolean
nb_ui_note_view_is_empty (void)
{
	extern GladeXML * xml;
	GtkTextIter start;
	GtkTextIter end;

	GtkWidget * entry_subject = glade_xml_get_widget (xml, "entry_subject");
	GtkWidget * textview = glade_xml_get_widget (xml, "textview");

	GtkTextBuffer * buffer = gtk_text_view_get_buffer ( GTK_TEXT_VIEW (textview) );
	gtk_text_buffer_get_start_iter (buffer, &start);
	gtk_text_buffer_get_end_iter (buffer, &end);

	if ( (strlen (gtk_entry_get_text ( GTK_ENTRY (entry_subject) )) == 0) &&
			(strlen (gtk_text_buffer_get_text(buffer, &start, &end,TRUE)) == 0) )
		return TRUE;
	else
		return FALSE;
}

/* retrive fields value */
gchar *
nb_ui_note_view_get_title (void)
{
	extern GladeXML * xml;
	GtkWidget * entry_subject = glade_xml_get_widget (xml, "entry_subject");

	return gtk_editable_get_chars( GTK_EDITABLE( entry_subject ), 0, -1 );
}

gchar *
nb_ui_note_view_get_text (void)
{
	extern GladeXML * xml;
	GtkTextIter start;
	GtkTextIter end;
	GtkWidget * textview = glade_xml_get_widget (xml, "textview");
	GtkTextBuffer * buffer =  gtk_text_view_get_buffer ( GTK_TEXT_VIEW (textview) );

	gtk_text_buffer_get_start_iter (buffer, &start);
	gtk_text_buffer_get_end_iter (buffer, &end);

	return gtk_text_buffer_get_text (buffer, &start, &end, TRUE);
}

void
nb_ui_note_view_set_fields (gchar * title, gchar * text, int type, int status, gchar * date, AttachmentList * attachments)
{
	extern GladeXML * xml;
	GtkTextIter start;
	GtkTextIter end;
	GtkWidget * entry_subject = glade_xml_get_widget (xml, "entry_subject");
	GtkWidget * textview = glade_xml_get_widget (xml, "textview");
	GtkWidget * optionmenutype = glade_xml_get_widget (xml, "option_menu_type");
	GtkWidget * optionmenustatus = glade_xml_get_widget (xml, "option_menu_status");
	GtkWidget * date_label =  glade_xml_get_widget (xml, "label_date_value");
	gsize bytes_written;

	/* set the title field */
	gtk_entry_set_text ( GTK_ENTRY (entry_subject), g_locale_to_utf8 (title, -1, NULL, &bytes_written, NULL));

	/* set the text field */
	GtkTextBuffer * buffer =  gtk_text_view_get_buffer ( GTK_TEXT_VIEW (textview));
	gtk_text_buffer_get_start_iter (buffer, &start);
	gtk_text_buffer_get_end_iter (buffer, &end);
	gtk_text_buffer_delete (buffer, &start, &end);

	if ( text == NULL )
		text = "";

	gtk_text_buffer_set_text (buffer, g_locale_to_utf8 (text, -1, NULL, &bytes_written, NULL), strlen (text));

	nb_ui_note_view_scan_url_tag_from_textview (buffer, NULL);

	 /* set the type option menu */
	gtk_option_menu_set_history ( GTK_OPTION_MENU (optionmenutype), type);

	/* set the status option menu */
	gtk_option_menu_set_history ( GTK_OPTION_MENU (optionmenustatus), status);

	/* set the date field */
	gtk_label_set_label ( GTK_LABEL (date_label), g_locale_to_utf8 (date, -1, NULL, &bytes_written, NULL));

	nb_ui_attachment_view_update (attachments);
}

/* privates functions */
static void
nb_ui_note_view_scan_url_tag_from_textview (GtkTextBuffer * buffer, gpointer user_data)
{
	GtkTextIter start;
	GtkTextIter end;

	gtk_text_buffer_get_start_iter (buffer,&start);

	while ( gtk_text_iter_forward_search (&start, "http://", GTK_TEXT_SEARCH_TEXT_ONLY, &start, &end, NULL) )
	{
		gchar c;

		/* look for the end of the link */
		do
		{
			gtk_text_iter_forward_char (&end);
			c = gtk_text_iter_get_char (&end);
		}
		while ( (c != EOF) && (c != 0) && (c != ' ') && (c != '\n') );

		/* set the links tag */
		gtk_text_buffer_apply_tag_by_name (buffer, "links", &start, &end);

		start = end;
	}

	nb_ui_cb_on_note_edited  (NULL, NULL);
}

/* callbacks */
gboolean
nb_ui_note_view_on_link_clicked (GtkTextView * textview, GdkEvent * event)
{
	extern Global * g;
	GtkTextIter start, end;
	GtkTextBuffer * buffer;
	GdkEventButton * ev;
	GtkTextTagTable * table;
	GtkTextTag * tag;
	gchar c;
	gint x, y;

	if ( event->type != GDK_BUTTON_RELEASE )
		return FALSE;

	ev= (GdkEventButton *)event;

	if ( ev->button!= 1)
		return FALSE;

	buffer = gtk_text_view_get_buffer ( GTK_TEXT_VIEW (textview));

	/* don't follow link if user selected some text */
	gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
	if ( gtk_text_iter_get_offset (&start) != gtk_text_iter_get_offset (&end) )
		return FALSE;

	gtk_text_view_window_to_buffer_coords ( GTK_TEXT_VIEW (textview), GTK_TEXT_WINDOW_WIDGET, ev->x, ev->y, &x, &y);
	gtk_text_view_get_iter_at_location ( GTK_TEXT_VIEW (textview), &start, x, y);

	/* check if it has a link tag */
	/* TODO: we may do a text_iter_has_tag_by_name as we also do the check for cursor change in interface.c */
	table = gtk_text_buffer_get_tag_table (buffer);
	tag = gtk_text_tag_table_lookup (table, "links");

	if ( !gtk_text_iter_has_tag (&start, tag) )
		return FALSE;

	do
	{
		gtk_text_iter_backward_char (&start);
		c = gtk_text_iter_get_char (&start);
	}
	while ( (c != ' ')  && (c != 0) && (!gtk_text_iter_starts_line (&start)) );

	if ( !gtk_text_iter_starts_line (&start) )
		gtk_text_iter_forward_char (&start);

	end = start;

	/* look for the end of the link */
	do
	{
		gtk_text_iter_forward_char (&end);
		c = gtk_text_iter_get_char (&end);
	}
	while ( (c != EOF) && (c != 0) && (c != ' ') && (c != '\n') );

	nb_global_launch_web_browser (g, gtk_text_buffer_get_text (buffer, &start, &end, FALSE));

	return FALSE;
}

gboolean
nb_ui_note_view_motion_notify_event (GtkWidget * textview, GdkEventMotion * event)
{
	gint x, y;

	gtk_text_view_window_to_buffer_coords ( GTK_TEXT_VIEW (textview),
					       GTK_TEXT_WINDOW_WIDGET,
					       event->x, event->y, &x, &y);

	nb_ui_note_view_set_cursor_if_appropriate ( GTK_TEXT_VIEW (textview), x, y);

	gdk_window_get_pointer (textview->window, NULL, NULL, NULL);

	/* propagate the event */
	return FALSE;
}

gboolean
nb_ui_note_view_visibility_notify_event (GtkWidget * textview, GdkEventVisibility * event)
{
	gint wx, wy, bx, by;

	gdk_window_get_pointer (textview->window, &wx, &wy, NULL);

	gtk_text_view_window_to_buffer_coords ( GTK_TEXT_VIEW (textview),
					       GTK_TEXT_WINDOW_WIDGET,
					       wx, wy, &bx, &by);

	nb_ui_note_view_set_cursor_if_appropriate ( GTK_TEXT_VIEW (textview), bx, by);

	/* propagate the event */
	return FALSE;
}
