/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 *  Copyright © 2000-2003 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */

#include "config.h"
#include "popup-commands.h"

#include "ephy-bookmarks-ui.h"
#include "ephy-download.h"
#include "ephy-embed-container.h"
#include "ephy-embed-utils.h"
#include "ephy-file-chooser.h"
#include "ephy-file-helpers.h"
#include "ephy-prefs.h"
#include "ephy-private.h"
#include "ephy-settings.h"
#include "ephy-shell.h"
#include "ephy-web-view.h"

#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <string.h>
#ifdef HAVE_WEBKIT2
#include <webkit2/webkit2.h>
#else
#include <webkit/webkit.h>
#endif

void
popup_cmd_link_in_new_window (GtkAction *action,
		              EphyWindow *window)
{
	EphyEmbedEvent *event;
	EphyEmbed *embed;
	GValue value = { 0, };

	embed = ephy_embed_container_get_active_child 
		(EPHY_EMBED_CONTAINER (window));

	event = ephy_window_get_context_event (window);
	g_return_if_fail (event != NULL);

	ephy_embed_event_get_property (event, "link-uri", &value);

	ephy_shell_new_tab (ephy_shell_get_default (),
			    NULL, embed,
			    g_value_get_string (&value),
			    EPHY_NEW_TAB_OPEN_PAGE |
			    EPHY_NEW_TAB_IN_NEW_WINDOW);
	g_value_unset (&value);
}

void
popup_cmd_link_in_new_tab (GtkAction *action,
		           EphyWindow *window)
{
	EphyEmbedEvent *event;
	EphyEmbed *embed;
	GValue value = { 0, };

	embed = ephy_embed_container_get_active_child
		(EPHY_EMBED_CONTAINER (window));

	event = ephy_window_get_context_event (window);
	g_return_if_fail (event != NULL);

	ephy_embed_event_get_property (event, "link-uri", &value);

	ephy_shell_new_tab (ephy_shell_get_default (),
			    window, embed,
			    g_value_get_string (&value),
			    EPHY_NEW_TAB_OPEN_PAGE |
			    EPHY_NEW_TAB_IN_EXISTING_WINDOW |
			    EPHY_NEW_TAB_APPEND_AFTER);
	g_value_unset (&value);
}

void
popup_cmd_bookmark_link (GtkAction *action,
			 EphyWindow *window)
{
#ifdef HAVE_WEBKIT2
	EphyEmbedEvent *event;
	WebKitHitTestResult *result;
	const char *title;
	const char *location;

	event = ephy_window_get_context_event (window);

	result = ephy_embed_event_get_hit_test_result (event);
	if (!webkit_hit_test_result_context_is_link (result))
	{
		return;
	}

	location = webkit_hit_test_result_get_link_uri (result);
	title = webkit_hit_test_result_get_link_title (result);
	if (!title)
	{
		title = webkit_hit_test_result_get_link_label (result);
	}

	ephy_bookmarks_ui_add_bookmark (GTK_WINDOW (window), location, title);
#else
	EphyEmbedEvent *event;
	char *title;
	char *location = NULL;
	guint context;
	WebKitHitTestResult *result;
	WebKitDOMNode *node, *first_child;

	event = ephy_window_get_context_event (window);
	g_return_if_fail (event != NULL);

	result = ephy_embed_event_get_hit_test_result (event);
	g_object_get (result, "context", &context, NULL);
	g_object_get (result, "inner-node", &node, NULL);

	if (context != WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK)
	{
		node = WEBKIT_DOM_NODE (webkit_dom_node_get_parent_element (WEBKIT_DOM_NODE (node)));
		if (WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (node))
			location = webkit_dom_html_anchor_element_get_href (WEBKIT_DOM_HTML_ANCHOR_ELEMENT (node));
	}
	else
	{
		g_object_get (result, "link-uri", &location, NULL);
	}

	if (!node || !location)
		return;

	title = webkit_dom_html_element_get_title (WEBKIT_DOM_HTML_ELEMENT (node));
	
	if (title == NULL || title[0] == '\0')
	{
		title = webkit_dom_html_anchor_element_get_text (WEBKIT_DOM_HTML_ANCHOR_ELEMENT (node));
	}

	/* Sometimes boorkmaklets are presented as images inside a
	 * link, try that. */
	if (title == NULL || title[0] == '\0')
	{
		first_child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (node));
		if (first_child && WEBKIT_DOM_IS_HTML_IMAGE_ELEMENT (first_child))
		{
			title = webkit_dom_html_image_element_get_alt (WEBKIT_DOM_HTML_IMAGE_ELEMENT (first_child));
			if (title == NULL || title[0] == '\0')
				title = webkit_dom_html_image_element_get_name (WEBKIT_DOM_HTML_IMAGE_ELEMENT (first_child));
		}
	}

	if (title == NULL || title[0] == '\0')
	{
		title = location;
	}
	
	ephy_bookmarks_ui_add_bookmark (GTK_WINDOW (window), location, title);
	g_free (title);
	g_free (location);
#endif
}

static void
popup_cmd_copy_to_clipboard (EphyWindow *window, const char *text)
{
	gtk_clipboard_set_text (gtk_clipboard_get (GDK_NONE),
				text, -1);
	gtk_clipboard_set_text (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
				text, -1);
}

void
popup_cmd_copy_link_address (GtkAction *action,
			     EphyWindow *window)
{
	EphyEmbedEvent *event;
	guint context;
	const char *address;
	GValue value = { 0, };

	event = ephy_window_get_context_event (window);
	g_return_if_fail (event != NULL);

	context = ephy_embed_event_get_context (event);

	if (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK)
	{
		ephy_embed_event_get_property (event, "link-uri", &value);
		address = g_value_get_string (&value);

		if (g_str_has_prefix (address, "mailto:"))
			address = address + 7;

		popup_cmd_copy_to_clipboard (window, address);
		g_value_unset (&value);
	}
}

static void
save_property_url_to_destination (EphyWindow *window,
				  const char *location,
				  const char *destination)
{
	EphyDownload *download;

	download = ephy_download_new_for_uri (location, GTK_WINDOW (window));

	if (destination)
		ephy_download_set_destination_uri (download, destination);
	else
		ephy_download_set_auto_destination (download);

	ephy_download_start (download);
}

static void
response_cb (GtkDialog *dialog,
	     int response_id,
	     char *location)
{
	if (response_id == GTK_RESPONSE_ACCEPT)
	{
		char *uri;
		GtkWindow *window;

		window = gtk_window_get_transient_for (GTK_WINDOW (dialog));

		uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
		save_property_url_to_destination (EPHY_WINDOW (window), location, uri);
		g_free (uri);
	}

	g_free (location);
	gtk_widget_destroy (GTK_WIDGET (dialog));
}

static void
save_property_url (GtkAction *action,
		   const char *title,
		   EphyWindow *window,
		   gboolean ask_dest,
		   const char *property)
{
	EphyEmbedEvent *event;
	const char *location;
	GValue value = { 0, };

	event = ephy_window_get_context_event (window);
	g_return_if_fail (event != NULL);

	ephy_embed_event_get_property (event, property, &value);
	location = g_value_get_string (&value);

	if (ask_dest)
	{
		EphyFileChooser *dialog;
		char *base;

		base = g_path_get_basename (location);
		dialog = ephy_file_chooser_new (title, GTK_WIDGET (window),
						GTK_FILE_CHOOSER_ACTION_SAVE,
						EPHY_FILE_FILTER_NONE);

		gtk_file_chooser_set_do_overwrite_confirmation
				(GTK_FILE_CHOOSER (dialog), TRUE);
		gtk_file_chooser_set_current_name
				(GTK_FILE_CHOOSER (dialog), base);
		g_signal_connect (dialog, "response",
				  G_CALLBACK (response_cb), g_strdup (location));
		gtk_widget_show (GTK_WIDGET (dialog));

		g_free (base);
	}
	else
	{
		save_property_url_to_destination (window, location, NULL);
	}
}

void
popup_cmd_open_link (GtkAction *action,
		     EphyWindow *window)
{
	EphyEmbedEvent *event;
	const char *location;
	GValue value = { 0, };
	EphyEmbed *embed;

	embed = ephy_embed_container_get_active_child 
		(EPHY_EMBED_CONTAINER (window));
	g_return_if_fail (embed != NULL);

	event = ephy_window_get_context_event (window);
	ephy_embed_event_get_property (event, "link-uri", &value);
	location = g_value_get_string (&value);
	ephy_web_view_load_url (ephy_embed_get_web_view (embed), location);
	g_value_unset (&value);
}

void
popup_cmd_download_link (GtkAction *action,
			 EphyWindow *window)
{
	save_property_url (action, _("Download Link"), window, 
			   FALSE, "link-uri");
}

void
popup_cmd_download_link_as (GtkAction *action,
			    EphyWindow *window)
{
	save_property_url (action, _("Save Link As"), window, 
			   TRUE, "link-uri");
}
void
popup_cmd_save_image_as (GtkAction *action,
			 EphyWindow *window)
{
	save_property_url (action, _("Save Image As"),
			   window, TRUE, "image-uri");
}

static void
background_download_completed (EphyDownload *download,
			       GtkWidget *window)
{
	const char *uri;
	GSettings *settings;

	uri = ephy_download_get_destination_uri (download);
	settings = ephy_settings_get ("org.gnome.desktop.background");
	g_settings_set_string (settings, "picture-uri", uri);
}

void
popup_cmd_set_image_as_background (GtkAction *action,
				   EphyWindow *window)
{
	EphyEmbedEvent *event;
	const char *location;
	char *dest_uri, *dest, *base, *base_converted;
	GValue value = { 0, };
	EphyDownload *download;

	event = ephy_window_get_context_event (window);
	g_return_if_fail (event != NULL);

	ephy_embed_event_get_property (event, "image-uri", &value);
	location = g_value_get_string (&value);

	download = ephy_download_new_for_uri (location, GTK_WINDOW (window));

	base = g_path_get_basename (location);
	base_converted = g_filename_from_utf8 (base, -1, NULL, NULL, NULL);
	dest = g_build_filename (g_get_user_special_dir (G_USER_DIRECTORY_PICTURES), base_converted, NULL);
	dest_uri = g_filename_to_uri (dest, NULL, NULL);

	ephy_download_set_destination_uri (download, dest_uri);
	ephy_download_set_action (download, EPHY_DOWNLOAD_ACTION_DO_NOTHING);

	g_signal_connect (download, "completed",
			  G_CALLBACK (background_download_completed), window);

	ephy_download_start (download);

	g_value_unset (&value);
	g_free (base);
	g_free (base_converted);
	g_free (dest);
	g_free (dest_uri);
}

void
popup_cmd_copy_image_location (GtkAction *action,
			       EphyWindow *window)
{
	EphyEmbedEvent *event;
	const char *location;
	GValue value = { 0, };

	event = ephy_window_get_context_event (window);
	ephy_embed_event_get_property (event, "image-uri", &value);
	location = g_value_get_string (&value);
	popup_cmd_copy_to_clipboard (window, location);
	g_value_unset (&value);
}

/* Opens an image URI using its associated handler. Or, if that
 * doesn't work, fallback to open the URI in a new browser window.
 */
static void
image_open_uri (GFile *file,
                const char *remote_address,
		guint32 user_time)
{
	gboolean success;

	success = ephy_file_launch_handler (NULL, file, user_time);

	if (!success)
	{
		ephy_shell_new_tab (ephy_shell_get_default (),
				    NULL, NULL, remote_address,
				    EPHY_NEW_TAB_OPEN_PAGE |
				    EPHY_NEW_TAB_IN_NEW_WINDOW);
	}

	if (strcmp (remote_address, g_file_get_uri (file)) != 0)
	{
		if (success)
			ephy_file_delete_on_exit (file);
		else
			g_file_delete (file, NULL, NULL);
	}
}

static void
save_source_completed_cb (EphyDownload *download)
{
	const char *dest;
	const char *source;
	guint32 user_time;
	GFile *file;

	user_time = ephy_download_get_start_time (download);
	dest = ephy_download_get_destination_uri (download);
	source = ephy_download_get_source_uri (download);
	g_return_if_fail (dest != NULL);
	
	file = g_file_new_for_uri (dest);

	image_open_uri (file, source, user_time);
	g_object_unref (file);
}

static void
save_temp_source (const char *address)
{
	EphyDownload *download;
	const char *static_temp_dir;
	char *base, *tmp_name, *tmp_path, *dest, *dest_uri;

	if (address == NULL) return;

	static_temp_dir = ephy_file_tmp_dir ();
	if (static_temp_dir == NULL) return;

	base = g_path_get_basename (address);
	tmp_name = g_strconcat (base, ".XXXXXX", NULL);
	g_free (base);

	tmp_path = g_build_filename (static_temp_dir, tmp_name, NULL);
	g_free (tmp_name);

	dest = ephy_file_tmp_filename (tmp_path, NULL);
	g_free (tmp_path);

	if (dest == NULL) return;

	dest_uri = g_filename_to_uri (dest, NULL, NULL);
	download = ephy_download_new_for_uri (address, NULL);
	ephy_download_set_destination_uri (download, dest_uri);

	g_signal_connect (download, "completed",
			  G_CALLBACK (save_source_completed_cb), NULL);

	ephy_download_start (download);

	g_free (dest);
	g_free (dest_uri);
}

void
popup_replace_spelling (GtkAction *action,
			EphyWindow *window)
{
#ifndef HAVE_WEBKIT2
	EphyEmbed *embed;
	WebKitWebView *view;
	WebKitWebFrame *frame;
	WebKitDOMDOMSelection *selection;
	WebKitDOMDocument *document;
	WebKitDOMDOMWindow *default_view;

	embed = ephy_embed_container_get_active_child 
		(EPHY_EMBED_CONTAINER (window));
	g_return_if_fail (embed != NULL);

	view = WEBKIT_WEB_VIEW (ephy_embed_get_web_view (embed));
	g_return_if_fail (view != NULL);

	document = webkit_web_view_get_dom_document (view);
	default_view = webkit_dom_document_get_default_view (document);
	selection = webkit_dom_dom_window_get_selection (default_view);
	webkit_dom_dom_selection_modify (selection, "move", "backward", "word");
	webkit_dom_dom_selection_modify (selection, "extend", "forward", "word");
	frame = webkit_web_view_get_focused_frame (view);
	webkit_web_frame_replace_selection (frame, gtk_action_get_label (action));
#endif
}

void
popup_cmd_open_image (GtkAction *action,
		      EphyWindow *window)
{
	EphyEmbedEvent *event;
	const char *address;
	char *scheme = NULL;
	GValue value = { 0, };
	EphyEmbed *embed;

	event = ephy_window_get_context_event (window);
	g_return_if_fail (event != NULL);

	embed = ephy_embed_container_get_active_child 
		(EPHY_EMBED_CONTAINER (window));
	g_return_if_fail (embed != NULL);

	ephy_embed_event_get_property (event, "image-uri", &value);
	address = g_value_get_string (&value);

	scheme = g_uri_parse_scheme (address);
	if (scheme == NULL) goto out;

	if (strcmp (scheme, "file") == 0)
	{
		GFile *file;
		
		file = g_file_new_for_uri (address);
		image_open_uri (file, address,
				gtk_get_current_event_time ());
		g_object_unref (file);
	}
	else
	{
		save_temp_source (address);
	}

 out:
	g_value_unset (&value);
	g_free (scheme);
}

void
popup_cmd_inspect_element (GtkAction *action, EphyWindow *window)
{
#ifndef HAVE_WEBKIT2
	EphyEmbedEvent *event;
	EphyEmbed *embed;
	WebKitWebInspector *inspector;
	guint x, y;

	embed = ephy_embed_container_get_active_child
		(EPHY_EMBED_CONTAINER (window));

	event = ephy_window_get_context_event (window);
	g_return_if_fail (event != NULL);

	inspector = webkit_web_view_get_inspector
		(EPHY_GET_WEBKIT_WEB_VIEW_FROM_EMBED (embed));

	ephy_embed_event_get_coords (event, &x, &y);
	webkit_web_inspector_inspect_coordinates (inspector, (gdouble)x, (gdouble)y);
#endif
}
