/*
 *  Copyright (C) 2000, 2001, 2002 Marco Pesenti Gritti
 *
 *  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 "galeon-dnd.h"

#include <gtk/gtkselection.h>
#include <libgnomevfs/gnome-vfs-uri.h>

#include <string.h>

static GtkTargetEntry url_drag_types [] = 
{
        { GALEON_DND_URI_LIST_TYPE,   0, GALEON_DND_URI_LIST },
        { GALEON_DND_TEXT_TYPE,       0, GALEON_DND_TEXT },
        { GALEON_DND_URL_TYPE,        0, GALEON_DND_URL }
};

static GtkTargetEntry single_url_drag_types [] = 
{
        { GALEON_DND_TEXT_TYPE,       0, GALEON_DND_TEXT },
        { GALEON_DND_URL_TYPE,        0, GALEON_DND_URL }
};

const GtkTargetEntry url_drop_types[] =
{
        { GALEON_DND_URI_LIST_TYPE,   0, GALEON_DND_URI_LIST },
        { GALEON_DND_URL_TYPE,        0, GALEON_DND_URL }
};

/* Encode a "_NETSCAPE_URL_" selection.
 * As far as I can tell, Netscape is expecting a single
 * URL to be returned.  I cannot discover a way to construct
 * a list to be returned that Netscape can understand.
 * GMC also fails to do this as well.
 */
static void
add_one_netscape_url (const char *url, const char *title, int x, int y, int w, int h, gpointer data)
{
        GString *result;

        result = (GString *) data;
        if (result->len == 0) {
                g_string_append (result, url);
		/* Mozilla appends the title as a second line, so we will as well */
		if (title && title[0] != '\0' )
		{
			g_string_append (result, "\n");
			g_string_append (result, title);
		}
        }
}

static void
add_one_uri (const char *uri, const char *title, int x, int y, int w, int h, gpointer data)
{
        GString *result;
        
        result = (GString *) data;

        g_string_append (result, uri);
        g_string_append (result, "\r\n");
}

gboolean
galeon_dnd_drag_data_get (GtkWidget *widget,
                          GdkDragContext *context,
                          GtkSelectionData *selection_data,
                          guint info,
                          guint32 time,
                          gpointer container_context,
                          GaleonDragEachSelectedItemIterator each_selected_item_iterator)
{
        GString *result;
                
        switch (info) {
        case GALEON_DND_URI_LIST:
        case GALEON_DND_TEXT:
		result = g_string_new (NULL);
                (* each_selected_item_iterator) (add_one_uri, container_context, result);
                break;
                
        case GALEON_DND_URL:
		result = g_string_new (NULL);
                (* each_selected_item_iterator) (add_one_netscape_url, container_context, result);
                break;
                
        default:
                return FALSE;
        }
        
        gtk_selection_data_set (selection_data,
                                selection_data->target,
                                8, result->str, result->len);

        return TRUE;
}

void
galeon_dnd_url_drag_source_set (GtkWidget *widget)
{
	gtk_drag_source_set (widget, 
                             GDK_BUTTON1_MASK,
			     url_drag_types,
			     G_N_ELEMENTS (url_drag_types),
                             GDK_ACTION_COPY);
}

void
galeon_dnd_single_url_drag_source_set (GtkWidget *widget)
{
	gtk_drag_source_set (widget, 
                             GDK_BUTTON1_MASK,
			     single_url_drag_types,
			     G_N_ELEMENTS (single_url_drag_types),
                             GDK_ACTION_COPY);
}


gboolean
galeon_dnd_drag_data_receive (GtkWidget *widget,
			      GdkDragContext *context,
			      gint x,
			      gint y,
			      GtkSelectionData *selection_data,
			      guint info,
			      guint32 time,
			      gpointer container_context,
			      GaleonDragEachReceivedItemIterator each_received_item_iterator)
{
	char * data = selection_data->data;

	g_signal_stop_emission_by_name (widget, "drag_data_received");

        switch (info) {
        case GALEON_DND_URI_LIST: 
	{
		GList *uris = gnome_vfs_uri_list_parse (data);
		GList *item;
		if (uris == NULL) break;

		for (item = uris; item; item = item->next)
		{
			GnomeVFSURI *uri = (GnomeVFSURI*) item->data;
			char * url = gnome_vfs_uri_to_string (uri,GNOME_VFS_URI_HIDE_NONE);
			if (strlen(url))
			{
				(* each_received_item_iterator) (url, 0, container_context);
			}
			g_free (url);
		}
		gnome_vfs_uri_list_free (uris);
		break;
	}
        case GALEON_DND_URL:
	{
		/* Mozilla passes the page title as the second line */
		gchar** split = g_strsplit(data, "\n", 2);
		if (split && split[0] && split[1])
		{
			(* each_received_item_iterator) (split[0], split[1], container_context);
			g_strfreev (split);
		}
		else if (data[0] != '\0')
		{
			(* each_received_item_iterator) (data, 0, container_context);
		}
                break;
	}
                
        default:
		return FALSE;
        }
	return TRUE;
}


void
galeon_dnd_url_drag_dest_set (GtkWidget *widget)
{
	gtk_drag_dest_set (widget, 
			   GTK_DEST_DEFAULT_ALL,
			   url_drop_types,
			   G_N_ELEMENTS (url_drop_types),
			   GDK_ACTION_COPY);
}

void
galeon_dnd_url_drag_dest_set_with_flags (GtkWidget *widget, GtkDestDefaults flags)
{
	gtk_drag_dest_set (widget, 
			   flags,
			   url_drop_types,
			   G_N_ELEMENTS (url_drop_types),
			   GDK_ACTION_COPY);
}
