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

/*
 *  Copyright (C) 2007 Hiroyuki Ikezoe
 *
 *  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.
 *
 *  $Id: kz-gtk-webcore.cpp 3207 2007-04-20 12:38:40Z ikezoe $
 */

#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif /* HAVE_CONFIG_H */

#include <glib/gi18n.h>
#include <math.h>
#include <webkit-gtk/webkit-ui-delegate.h>
#include <webi.h>

#include "kazehakase.h"
#include "kz-webkit-gtk.h"
#include "kz-embed-prefs.h"
#include "kz-embed.h"
#include "kz-prompt-dialog.h"
#include "kz-proxy-item.h"
#include "gtk-utils.h"
#include "utils.h"

typedef struct _KzWebkitGtkPrivate	KzWebkitGtkPrivate;
struct _KzWebkitGtkPrivate
{
	gint cur_requests;
	gint total_requests;
	gchar *link_message;
	guint32 button_press_time;

	gboolean is_loading;
	gboolean lock;
	WebiSettings *settings;
};
#define KZ_WEBKIT_GTK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), KZ_TYPE_WEBKIT_GTK, KzWebkitGtkPrivate))

static GType kz_type_webkit_gtk = 0;
static WebkitViewClass *kz_webkit_gtk_parent_class;

GtkWidget  *kz_webkit_gtk_new          (void);
static void kz_webkit_gtk_class_init   (KzWebkitGtkClass *klass);
static void kz_webkit_gtk_iface_init   (KzEmbedIFace *iface);
static void kz_webkit_gtk_init         (KzWebkitGtk *webkit_gtk);
static void kz_webkit_gtk_dispose      (GObject      *object);

/* webkit_gtk class */
static void         kz_webkit_gtk_status           (WebkitView     *webkit_view,
						     WebiLoadStatus *status);
static void         kz_webkit_gtk_load_start       (WebkitView     *webkit_view);
static void         kz_webkit_gtk_load_stop        (WebkitView     *webkit_view);
static void         kz_webkit_gtk_location         (WebkitView     *webkit_view);
static void         kz_webkit_gtk_title            (WebkitView     *webkit_view);
static void         kz_webkit_gtk_req_js_prompt    (WebkitView     *webkit_view,
						     WebiPromptArgs *args);
static void         kz_webkit_gtk_req_auth_prompt  (WebkitView     *webkit_view,
						     WebiAuthArgs   *args);
static WebkitView  *kz_webkit_gtk_req_new_window   (WebkitView     *webkit_view,
						     const gchar *url);
static void         kz_webkit_gtk_close_window     (WebkitView     *webkit_view);

static gboolean     kz_webkit_gtk_set_cookie       (WebkitView       *webkit_view,
						     const gchar *url,
						     WebiCookie *cookie);
/* embed iface */
static void         kz_webkit_gtk_load_url         (KzEmbed      *kzembed,
						     const gchar  *url);
static gboolean     kz_webkit_gtk_is_loading       (KzEmbed      *kzembed);
static const gchar *kz_webkit_gtk_get_title        (KzEmbed      *kzembed);
static const gchar *kz_webkit_gtk_get_location     (KzEmbed      *kzembed);
static gchar       *kz_webkit_gtk_ensure_title     (KzEmbed      *kzembed);
static gchar       *kz_webkit_gtk_get_link_message (KzEmbed      *kzembed);

static void         kz_webkit_gtk_reload           (KzEmbed      *kzembed,
						     KzEmbedReloadFlag flags);
static void         kz_webkit_gtk_stop_load        (KzEmbed      *kzembed);
static void         kz_webkit_gtk_go_back          (KzEmbed      *kzembed);
static void         kz_webkit_gtk_go_forward       (KzEmbed      *kzembed);
static gboolean     kz_webkit_gtk_can_go_back      (KzEmbed      *kzembed);
static gboolean     kz_webkit_gtk_can_go_forward   (KzEmbed      *kzembed);
static gboolean     kz_webkit_gtk_can_go_nav_link  (KzEmbed      *kzembed,
						     KzEmbedNavLink link);
static void         kz_webkit_gtk_go_nav_link      (KzEmbed      *kzembed,
						     KzEmbedNavLink link);
static void         kz_webkit_gtk_set_nth_nav_link (KzEmbed      *kzembed,
						     KzEmbedNavLink link,
						     KzNavi       *navi,
						     guint         n);
static KzNavi      *kz_webkit_gtk_get_nth_nav_link (KzEmbed      *kzembed,
						     KzEmbedNavLink link,
						     guint         n);
static GList       *kz_webkit_gtk_get_nav_links    (KzEmbed      *kzembed,
						     KzEmbedNavLink link);

static gboolean     kz_webkit_gtk_get_lock         (KzEmbed      *kzembed);
static void         kz_webkit_gtk_set_lock         (KzEmbed      *kzembed,
						     gboolean      lock);

static void         kz_webkit_gtk_shistory_get_nth (KzEmbed      *kzembed, 
						     int           nth,
						     gboolean      is_relative,
						     char        **aUrl,
						     char        **aTitle);

static gboolean     kz_webkit_gtk_can_cut_selection  (KzEmbed      *kzembed);
static gboolean     kz_webkit_gtk_can_copy_selection (KzEmbed      *kzembed);
static gboolean     kz_webkit_gtk_can_paste          (KzEmbed      *kzembed);
static void         kz_webkit_gtk_cut_selection      (KzEmbed      *kzembed);
static void         kz_webkit_gtk_copy_selection     (KzEmbed      *kzembed);
static void         kz_webkit_gtk_paste              (KzEmbed      *kzembed);
static void         kz_webkit_gtk_select_all         (KzEmbed      *kzembed);

static gdouble      kz_webkit_gtk_get_progress     (KzEmbed      *kzembed);

static gint         kz_webkit_gtk_get_text_size    (KzEmbed      *kzembed);
static void         kz_webkit_gtk_set_text_size    (KzEmbed      *kzembed,
						     gint         zoom,
						     gboolean     reflow);

static gboolean     kz_webkit_gtk_find             (KzEmbed      *kzembed,
						     const char   *keyword,
						     gboolean      backward);

static gboolean     kz_webkit_gtk_selection_is_collapsed (KzEmbed      *kzembed);

static gboolean	    kz_webkit_gtk_get_allow_javascript  (KzEmbed      *kzembed);
static void	    kz_webkit_gtk_set_allow_javascript  (KzEmbed      *kzembed,
							  gboolean      allow);
static gboolean	    kz_webkit_gtk_get_allow_images      (KzEmbed      *kzembed);
static void	    kz_webkit_gtk_set_allow_images      (KzEmbed      *kzembed,
							  gboolean      allow);
/* WebiMouseDelegate interfaces */
static void          kz_webkit_gtk_ui_iface_init        (WebkitUIDelegateInterface *iface);
static gboolean	     kz_webkit_gtk_ui_mouse_action_on_element
							 (WebkitUIDelegate	*self,
							  WebkitView		*sender,
							  WebkitElementInfo	*element_info,
							  WebkitMouseEventInfo	*mouse_info);

/* KzEmbedPrefs interfaces */
static void          kz_webkit_gtk_prefs_iface_init      (KzEmbedPrefsIFace *iface);
#if 0
static gboolean      kz_webkit_gtk_prefs_init	    (KzEmbedPrefs *embed_prefs);
static gboolean      kz_webkit_gtk_prefs_get_font_list   (KzEmbedPrefs *embed_prefs,
						     const gchar  *lang_group,
						     const gchar  *font_type,
						     GList      **font_list,
						     GList      **all_font_list,
						     gchar       **default_font);
static gboolean      kz_webkit_gtk_prefs_get_passwords   (KzEmbedPrefs *embed_prefs,
						     GList **passwords);
static gboolean      kz_webkit_gtk_prefs_remove_passwords(KzEmbedPrefs *embed_prefs,
						     GList *passwords);
#endif
void
kz_webkit_gtk_register_type (GTypeModule *module)
{
	static const GTypeInfo kz_webkit_gtk_info =
	{
		sizeof (KzWebkitGtkClass),
		NULL,		/* base_init */
		NULL,		/* base_finalize */
		(GClassInitFunc) kz_webkit_gtk_class_init,
		NULL,		/* class_finalize */
		NULL,		/* class_data */
		sizeof (KzWebkitGtk),
		0,		/* n_preallocs */
		(GInstanceInitFunc) kz_webkit_gtk_init,
	};

	const GInterfaceInfo kz_embed_info =
	{
		(GInterfaceInitFunc) kz_webkit_gtk_iface_init,
		NULL,
		NULL
	};

	const GInterfaceInfo kz_embed_prefs_info =
	{
		(GInterfaceInitFunc) kz_webkit_gtk_prefs_iface_init,
		NULL,
		NULL
	};

	const GInterfaceInfo webi_ui_delegate_info =
	{
		(GInterfaceInitFunc) kz_webkit_gtk_ui_iface_init,
		NULL,
		NULL
	};

	kz_type_webkit_gtk = g_type_module_register_type(module,
						    WEBKIT_TYPE_VIEW,
						    "KzWebkitGtk",
						    &kz_webkit_gtk_info,
						    (GTypeFlags)0);

	g_type_module_add_interface(module,
				    KZ_TYPE_WEBKIT_GTK,
				    KZ_TYPE_EMBED,
				    &kz_embed_info);

	g_type_module_add_interface(module,
				    KZ_TYPE_WEBKIT_GTK,
				    KZ_TYPE_EMBED_PREFS,
				    &kz_embed_prefs_info);
	
	g_type_module_add_interface(module,
				    KZ_TYPE_WEBKIT_GTK,
				    WEBKIT_TYPE_UI_DELEGATE,
				    &webi_ui_delegate_info);
}

GType
kz_webkit_gtk_get_type (void)
{
       return kz_type_webkit_gtk;
}

static void
kz_webkit_gtk_class_init (KzWebkitGtkClass *klass)
{
	GObjectClass *object_class;
	GtkWidgetClass *widget_class;
	WebkitViewClass *webkit_gtk_class;

	kz_webkit_gtk_parent_class = (WebkitViewClass *)g_type_class_peek_parent (klass);
	object_class = (GObjectClass *) klass;
	widget_class = (GtkWidgetClass *) klass;
	webkit_gtk_class  = (WebkitViewClass *) klass;

	object_class->dispose   = kz_webkit_gtk_dispose;
#if 0
	webkit_gtk_class->status     = kz_webkit_gtk_status;
	webkit_gtk_class->load_start = kz_webkit_gtk_load_start;
	webkit_gtk_class->load_stop  = kz_webkit_gtk_load_stop;
	webkit_gtk_class->location   = kz_webkit_gtk_location;
	webkit_gtk_class->title      = kz_webkit_gtk_title;
#if 0
	webkit_gtk_class->progress   = kz_webkit_gtk_progress;
#endif
	webkit_gtk_class->req_js_prompt   = kz_webkit_gtk_req_js_prompt;
	webkit_gtk_class->req_auth_prompt = kz_webkit_gtk_req_auth_prompt;
	webkit_gtk_class->req_new_window  = kz_webkit_gtk_req_new_window;
	webkit_gtk_class->close_window    = kz_webkit_gtk_close_window;
	webkit_gtk_class->set_cookie      = kz_webkit_gtk_set_cookie;
#endif
	g_type_class_add_private (object_class, sizeof(KzWebkitGtkPrivate));
}


static void
kz_webkit_gtk_iface_init (KzEmbedIFace *iface)
{
	iface->load_url               = kz_webkit_gtk_load_url;
	iface->view_source            = NULL;
	iface->is_loading             = kz_webkit_gtk_is_loading;
	iface->get_title              = kz_webkit_gtk_get_title;
	iface->get_location           = kz_webkit_gtk_get_location;
	iface->ensure_title           = kz_webkit_gtk_ensure_title;
	iface->get_link_message       = kz_webkit_gtk_get_link_message;
	iface->get_progress           = kz_webkit_gtk_get_progress;
	iface->can_cut_selection      = kz_webkit_gtk_can_cut_selection;
	iface->can_copy_selection     = kz_webkit_gtk_can_copy_selection;
	iface->can_paste              = kz_webkit_gtk_can_paste;
	iface->cut_selection          = kz_webkit_gtk_cut_selection;
	iface->copy_selection         = kz_webkit_gtk_copy_selection;
	iface->paste                  = kz_webkit_gtk_paste;
	iface->select_all             = kz_webkit_gtk_select_all;
	iface->get_selection_string   = NULL;
	iface->find                   = kz_webkit_gtk_find;
	iface->incremental_search     = kz_webkit_gtk_find; /* tentavie */
	iface->selection_is_collapsed = kz_webkit_gtk_selection_is_collapsed;
	iface->get_links              = NULL;
	iface->copy_page              = NULL;
	iface->shistory_copy          = NULL;
	iface->shistory_get_pos       = NULL;
	iface->shistory_get_nth       = kz_webkit_gtk_shistory_get_nth;
	iface->reload                 = kz_webkit_gtk_reload;
	iface->stop_load              = kz_webkit_gtk_stop_load;
	iface->go_back                = kz_webkit_gtk_go_back;
	iface->go_forward             = kz_webkit_gtk_go_forward;
	iface->can_go_back            = kz_webkit_gtk_can_go_back;
	iface->can_go_forward         = kz_webkit_gtk_can_go_forward;
	iface->can_go_nav_link        = kz_webkit_gtk_can_go_nav_link;
	iface->go_nav_link            = kz_webkit_gtk_go_nav_link;
	iface->append_nav_link        = NULL;
	iface->set_nav_link           = NULL;
	iface->set_nth_nav_link       = kz_webkit_gtk_set_nth_nav_link;
	iface->get_nav_link           = NULL;
	iface->get_nth_nav_link       = kz_webkit_gtk_get_nth_nav_link;
	iface->get_nav_links          = kz_webkit_gtk_get_nav_links;
	iface->go_history_index       = NULL;
	iface->do_command             = NULL;
	iface->can_do_command         = NULL;
	iface->get_lock               = kz_webkit_gtk_get_lock;
	iface->set_lock               = kz_webkit_gtk_set_lock;
	iface->get_body_text          = NULL;
#if 0
	iface->get_selection_source   = NULL;
#endif
	iface->set_encoding           = NULL;
	iface->get_encoding           = NULL;
	iface->print                  = NULL;
	iface->print_preview          = NULL;
	iface->get_printer_list       = NULL;
	iface->create_thumbnail       = NULL;
	iface->save_with_content      = NULL;
	iface->set_text_into_textarea = NULL;
	iface->get_text_from_textarea = NULL;
	iface->zoom_set               = kz_webkit_gtk_set_text_size; /* tentative */
	iface->zoom_get               = kz_webkit_gtk_get_text_size; /* tentative */
	iface->set_text_size          = kz_webkit_gtk_set_text_size;
	iface->get_text_size          = kz_webkit_gtk_get_text_size;
	iface->get_html_with_contents = NULL;
	iface->set_history            = NULL;
	iface->get_history            = NULL;
	iface->get_last_modified      = NULL;
	iface->fine_scroll            = NULL;
	iface->page_up                = NULL;
	iface->page_down              = NULL; 
	iface->get_allow_javascript   = kz_webkit_gtk_get_allow_javascript; 
	iface->set_allow_javascript   = kz_webkit_gtk_set_allow_javascript; 
	iface->get_allow_images       = kz_webkit_gtk_get_allow_images;
	iface->set_allow_images       = kz_webkit_gtk_set_allow_images;
#if 0
	iface->set_edit_mode          = NULL;
	iface->set_view_mode          = NULL;
#endif

	iface->link_message           = NULL;
	iface->js_status              = NULL;
	iface->location               = NULL;
	iface->title                  = NULL;
	iface->progress               = NULL;
	iface->net_start              = NULL;
	iface->net_stop               = NULL;
	iface->new_window             = NULL;
	iface->open_uri               = NULL;
	iface->size_to                = NULL;
	iface->dom_key_down           = NULL;
	iface->dom_key_press          = NULL;
	iface->dom_key_up             = NULL;
	iface->dom_mouse_down         = NULL;
	iface->dom_mouse_up           = NULL;
	iface->dom_mouse_click        = NULL;
	iface->dom_mouse_dbl_click    = NULL;
	iface->dom_mouse_over         = NULL;
	iface->dom_mouse_out          = NULL;
	iface->security_change        = NULL;
	iface->status_change          = NULL;
}


static void
kz_webkit_gtk_prefs_iface_init (KzEmbedPrefsIFace *iface)
{
	iface->init             = NULL; /* kz_webkit_gtk_prefs_init;*/
	iface->get_font_list    = NULL; /* kz_webkit_gtk_prefs_get_font_list; */
	iface->get_passwords    = NULL; /* kz_webkit_gtk_prefs_get_passwords; */
	iface->remove_passwords = NULL; /* kz_webkit_gtk_prefs_remove_passwords; */
}

static void
kz_webkit_gtk_ui_iface_init (WebkitUIDelegateInterface *iface)
{
	iface->mouse_action_on_element  = NULL;
}

static void
set_font_preferences (KzProfile *profile, KzWebkitGtk *webkit_gtk)
{
	WebiSettings *settings = KZ_WEBKIT_GTK_GET_PRIVATE(webkit_gtk)->settings;
	/* font settings */
	GList *list, *node;
	gint i = 0;
	gint size_variable = -1, size_fixed = -1;
	gint min_size_variable = -1, min_size_fixed = -1;

	/* workaround */
	gchar langs[1024], *lang = NULL;
	if (kz_profile_get_value(profile, "Language", "accept_languages", 
				&langs, G_N_ELEMENTS(langs),
				KZ_PROFILE_VALUE_TYPE_STRING))
	{
		gchar **split_str;
		split_str = g_strsplit(langs, ",", 1);

		if (split_str[0])
		{
			lang = g_strdup(split_str[0]);
			g_strfreev(split_str);
		}
	}
	if (!lang)
		lang = g_strdup("");

	gchar *serif_font, *sans_font, *mono_font;
	serif_font = g_strdup_printf("name_serif_%s", lang);
	sans_font = g_strdup_printf("name_sans-serif_%s", lang);
	mono_font = g_strdup_printf("name_monospace_%s", lang);

	list = kz_profile_enum_key(profile, "Font", TRUE);
	for (node = list; node; node = g_list_next(node))
	{
		const gchar *key = (const gchar*)node->data;

		if (!key || !*key) continue;
		if (g_str_has_prefix(key, "size_variable_"))
		{
			gint value;
			kz_profile_get_value(profile, "Font", key,
					&value, sizeof(value),
					KZ_PROFILE_VALUE_TYPE_INT);
			if (value > size_variable)
				size_variable = value;
		}
		else if (g_str_has_prefix(key, "size_fixed_"))
		{
			gint value;
			kz_profile_get_value(profile, "Font", key,
					&value, sizeof(value),
					KZ_PROFILE_VALUE_TYPE_INT);
			if (value > size_fixed)
				size_fixed = value;
		}
		else if (g_str_has_prefix(key, "min-size_variable_"))
		{
			gint value;
			kz_profile_get_value(profile, "Font", key,
					&value, sizeof(value),
					KZ_PROFILE_VALUE_TYPE_INT);
			if (value > min_size_variable)
				min_size_variable = value;
		}
		else if (g_str_has_prefix(key, "min-size_fixed_"))
		{
			gint value;
			kz_profile_get_value(profile, "Font", key,
					&value, sizeof(value),
					KZ_PROFILE_VALUE_TYPE_INT);
			if (value > min_size_fixed)
				min_size_fixed = value;
		}
		else if (!strcmp(key, serif_font))
		{
			gchar value[1024];
			kz_profile_get_value(profile, "Font", key,
					&value, strlen(value)+1,
					KZ_PROFILE_VALUE_TYPE_STRING);
			settings->serif_font_family = g_strdup(value);
			settings->standard_font_family = g_strdup(value);
		}
		else if (!strcmp(key, sans_font))
		{
			gchar value[1024];
			kz_profile_get_value(profile, "Font", key,
					&value, strlen(value)+1,
					KZ_PROFILE_VALUE_TYPE_STRING);
			settings->sans_serif_font_family = g_strdup(value);
		}
		else if (!strcmp(key, mono_font))
		{
			gchar value[1024];
			kz_profile_get_value(profile, "Font", key,
					&value, strlen(value)+1,
					KZ_PROFILE_VALUE_TYPE_STRING);
			settings->fixed_font_family = g_strdup(value);
		}
	}
	g_list_free(list);
	g_free(serif_font);
	g_free(sans_font);
	g_free(mono_font);

	double dpi_pixel_ratio = 72.0 / 96.0;
	if (size_variable >= 0)
		settings->default_font_size = (gfloat)(size_variable * dpi_pixel_ratio);
	if (size_fixed >= 0)
		settings->default_fixed_font_size = (gfloat)(size_fixed * dpi_pixel_ratio);
	if (min_size_variable >= 0)
		settings->minimum_font_size = (gfloat)(min_size_variable * dpi_pixel_ratio);
	if (min_size_fixed >= 0)
		settings->minimum_font_size = (gfloat)(min_size_fixed * dpi_pixel_ratio);
}

static void
build_user_agent (gchar *user_agent, gint size)
{
	gchar *system;

	system = kz_utils_get_system_name();

	g_snprintf(user_agent, size,
		   "Mozilla/5.0 (X11; %s; U;) AppleWebKit/146.1 (KHTML, like Gecko) Kazehakase" VERSION,
		   system);
	g_free (system);
}

static void
set_user_agent (KzProfile *profile, KzWebkitGtk *webkit_gtk)
{
	WebiSettings *settings = KZ_WEBKIT_GTK_GET_PRIVATE(webkit_gtk)->settings;
	gchar tmp_string[1024];
	gboolean value = FALSE;
	kz_profile_get_value(profile, "Global", "override_user_agent", 
			     &value, sizeof(gboolean),
			     KZ_PROFILE_VALUE_TYPE_BOOL);
	if (value)
	{
		value = kz_profile_get_value(profile, "Global", "user_agent", 
				&tmp_string, G_N_ELEMENTS(tmp_string),
				KZ_PROFILE_VALUE_TYPE_STRING);
	}
	else /* set default */
	{
		build_user_agent(tmp_string, G_N_ELEMENTS(tmp_string));
	}

	settings->user_agent_string = g_strdup(tmp_string);
}

static void
set_proxy (KzProfile *profile, KzWebkitGtk *webkit_gtk)
{
	WebiSettings *settings = KZ_WEBKIT_GTK_GET_PRIVATE(webkit_gtk)->settings;
	gchar tmp_string[1024];
	gchar *http_host, *https_host, *ftp_host;
	guint http_port, https_port, ftp_port;
	gboolean value = FALSE, use_same_proxy;
	KzProxyItem *item = NULL;

	kz_profile_get_value(profile, "Global", "use_proxy", 
			     &value, sizeof(gboolean),
			     KZ_PROFILE_VALUE_TYPE_BOOL);
	if (!value)
		return;

	value = kz_profile_get_value(profile, "Global", "proxy_name", 
				&tmp_string, G_N_ELEMENTS(tmp_string),
				KZ_PROFILE_VALUE_TYPE_STRING);
	if (!value)
		return;
	
	item = kz_proxy_find(tmp_string);
	if (!item)
		return;

	g_object_get(G_OBJECT(item),
		     "use_same_proxy", &use_same_proxy,
		     NULL);
	if (use_same_proxy)
	{
		g_object_get(G_OBJECT(item),
			     "http_host",  &http_host,
			     "http_port",  &http_port,
			     NULL);
		if (!http_host)
			return;
	}
	else
	{
		g_object_get(G_OBJECT(item),
			     "http_host",  &http_host,
			     "http_port",  &http_port,
			     "https_host", &https_host,
			     "https_port", &https_port,
			     "ftp_host",   &ftp_host,
			     "ftp_port",   &ftp_port,
			     NULL);
	}

	/* proxy for HTTP protocol */
	if (http_host)
		settings->http_proxy = g_strdup(http_host);
#if 0
	/* proxy for HTTPS protocol */
	if (https_host)
		settings->https_proxy = g_strdup(https_host);
	
	/* proxy for FTP protocol */
	if (ftp_host)
		settings->ftp_proxy = g_strdup(ftp_host);
#endif	
	if (http_host)
		g_free(http_host);
	if (https_host)
		g_free(https_host);
	if (ftp_host)
		g_free(ftp_host);
}

static void
set_default_preferences (KzWebkitGtk *webkit_gtk)
{
	WebiSettings *settings = KZ_WEBKIT_GTK_GET_PRIVATE(webkit_gtk)->settings;
	KzProfile *profile = KZ_GET_GLOBAL_PROFILE;

	gchar value[1024];
	if (kz_profile_get_value(profile, "Language", "charset_default", 
				&value, G_N_ELEMENTS(value),
				KZ_PROFILE_VALUE_TYPE_STRING))
	{
		settings->default_text_encoding = g_strdup(value);
	}

	set_user_agent(profile, webkit_gtk);
	set_font_preferences (profile, webkit_gtk);
	set_proxy(profile, webkit_gtk);
	
	settings->plugins_enabled = TRUE;
	settings->javascript_enabled = TRUE;
	settings->java_enabled = TRUE;
	settings->autoload_images = TRUE;

	webi_set_settings(WEBI(webkit_gtk), settings);
#if 0
	OSB::Features *features = get_osb_features(WEBI(webkit_gtk));
	features->setToolbarsVisible(FALSE);
	features->setStatusBarVisible(FALSE);
#endif
}

static void
kz_webkit_gtk_init (KzWebkitGtk *webkit_gtk)
{
	KzWebkitGtkPrivate *priv = KZ_WEBKIT_GTK_GET_PRIVATE (webkit_gtk);

	priv->is_loading = FALSE;
	priv->cur_requests   = 0;
	priv->total_requests = 0;
	priv->link_message   = NULL;

	priv->button_press_time = 0;

	priv->settings = g_new0(WebiSettings, 1);

	set_default_preferences(webkit_gtk);
	webi_set_emit_internal_status(WEBI(webkit_gtk), TRUE);

	WebkitFrame *frame = webkit_view_get_main_frame(WEBKIT_VIEW(webkit_gtk));
	webkit_set_ui_delegate(frame, WEBKIT_UI_DELEGATE(webkit_gtk));
	gtk_widget_show(GTK_WIDGET(webkit_gtk));
}

static void
free_webi_settings (WebiSettings *settings)
{
	if (settings->default_text_encoding)
		g_free((gchar*)settings->default_text_encoding);
	if (settings->serif_font_family)
		g_free((gchar*)settings->serif_font_family);
	if (settings->sans_serif_font_family)
		g_free((gchar*)settings->sans_serif_font_family);
	if (settings->fixed_font_family)
		g_free((gchar*)settings->fixed_font_family);
	if (settings->standard_font_family)
		g_free((gchar*)settings->standard_font_family);
	if (settings->cursive_font_family)
		g_free((gchar*)settings->cursive_font_family);
	if (settings->fantasy_font_family)
		g_free((gchar*)settings->fantasy_font_family);
	if (settings->user_agent_string)
		g_free((gchar*)settings->user_agent_string);
	if (settings->http_proxy)
		g_free((gchar*)settings->http_proxy);
}

static void
kz_webkit_gtk_dispose (GObject *object)
{
	KzWebkitGtkPrivate *priv = KZ_WEBKIT_GTK_GET_PRIVATE(object);

	if (priv->link_message)
		g_free(priv->link_message);
	priv->link_message = NULL;

	if (priv->settings)
	{
		free_webi_settings(priv->settings);
		g_free(priv->settings);
	}
	priv->settings = NULL;

	if (G_OBJECT_CLASS(kz_webkit_gtk_parent_class)->dispose)
		G_OBJECT_CLASS(kz_webkit_gtk_parent_class)->dispose(object);
}

GtkWidget *
kz_webkit_gtk_new (void)
{
	return GTK_WIDGET(g_object_new(KZ_TYPE_WEBKIT_GTK, NULL));
}

static void
kz_webkit_gtk_status (Webi *webi, WebiLoadStatus *status)
{
	KzWebkitGtkPrivate *priv;
	g_return_if_fail(KZ_IS_WEBKIT_GTK(webi));
	g_return_if_fail(status);

	priv = KZ_WEBKIT_GTK_GET_PRIVATE (webi);

	switch(status->status) {
	case WEBI_LOADING_START:
		priv->is_loading = TRUE;
		priv->cur_requests = 0;
		priv->total_requests = 0;
		g_signal_emit_by_name(webi, "kz-net-start");
		break;
	case WEBI_LOADING:
		priv->cur_requests = status->totalReceived;
		priv->total_requests = status->totalSize;
		g_signal_emit_by_name(webi, "kz-progress");
		break;
	case WEBI_LOADING_COMPLETE:
	case WEBI_LOADING_ERROR:
		priv->is_loading = FALSE;
		priv->cur_requests = status->totalReceived;
		priv->total_requests = status->totalSize;
		g_signal_emit_by_name(webi, "kz-net-stop");
		break;
	default:
		break;
	}

	/* call parent method */
}


static void
kz_webkit_gtk_load_start (Webi *webi)
{
	KzWebkitGtkPrivate *priv;
	g_return_if_fail(KZ_IS_WEBKIT_GTK(webi));

	priv = KZ_WEBKIT_GTK_GET_PRIVATE (webi);
	priv->is_loading = TRUE;

	g_signal_emit_by_name(webi, "kz-net-start");

	/* call parent method */
}


static void
kz_webkit_gtk_load_stop (Webi *webi)
{
	KzWebkitGtkPrivate *priv;
	g_return_if_fail(KZ_IS_WEBKIT_GTK(webi));

	priv = KZ_WEBKIT_GTK_GET_PRIVATE (webi);
	priv->is_loading = FALSE;

	g_signal_emit_by_name(webi, "kz-net-stop");

	/* call parent method */
}


static void
kz_webkit_gtk_location (Webi *webi)
{
	g_return_if_fail(KZ_IS_WEBKIT_GTK(webi));

	g_signal_emit_by_name(webi, "kz-location");

	/* call parent method */
}


static void
kz_webkit_gtk_title (Webi *webi)
{
	g_return_if_fail(KZ_IS_WEBKIT_GTK(webi));

	g_signal_emit_by_name(webi, "kz-title");

	/* call parent method */
}


static void
kz_webkit_gtk_req_js_prompt (Webi *webi, WebiPromptArgs* args)
{
	g_return_if_fail(KZ_IS_WEBKIT_GTK(webi));
}


static void
kz_webkit_gtk_req_auth_prompt (Webi *webi, WebiAuthArgs* args)
{
	KzPromptDialog *prompt;
	gchar *message;

	g_return_if_fail(KZ_IS_WEBKIT_GTK(webi));

	prompt= KZ_PROMPT_DIALOG(kz_prompt_dialog_new(TYPE_PROMPT_USER_PASS));

	kz_prompt_dialog_set_title(prompt, _("Authentication"));
	message = g_strdup_printf (_("Enter username and password for %s at %s"),
				   args->realm, args->url);
	kz_prompt_dialog_set_message_text(prompt, message);
	g_free(message);
	kz_prompt_dialog_run(prompt);

	args->out_ok_pressed = kz_prompt_dialog_get_confirm_value(prompt);
	args->out_username = g_strdup(kz_prompt_dialog_get_user(prompt));
	args->out_password = g_strdup(kz_prompt_dialog_get_password(prompt));

	gtk_widget_destroy(GTK_WIDGET(prompt));
}


static Webi *
kz_webkit_gtk_req_new_window (Webi *webi, const gchar *url)
{
	Webi *new_webkit_gtk = NULL;
	g_return_val_if_fail(KZ_IS_WEBKIT_GTK(webi), NULL);
	
	g_signal_emit_by_name(webi, "kz-new-window", &new_webkit_gtk);
	webi_load_url(new_webkit_gtk, url);

	return new_webkit_gtk;
}

static void
kz_webkit_gtk_close_window (Webi *webi)
{
	g_return_if_fail(KZ_IS_WEBKIT_GTK(webi));
	
	gtk_widget_destroy(GTK_WIDGET(webi));
}

static void
get_mouse_event_info(KzEmbedEventMouse **kzevent)
{
	GdkModifierType state = (GdkModifierType)0;
	gint x, y;
	KzEmbedEventMouse *ret;
	KzEmbedEvent *info;

	gdk_window_get_pointer(NULL, &x, &y, &state);
	ret = (KzEmbedEventMouse *) kz_embed_event_new(KZ_EMBED_EVENT_MOUSE);

	info = (KzEmbedEvent *) ret;
	info->context = KZ_CONTEXT_NONE;

	ret->x = x;
	ret->y = y;
	if (state & GDK_SHIFT_MASK)
        	ret->modifier |= KZ_SHIFT_KEY;
	if (state & GDK_CONTROL_MASK)
        	ret->modifier |= KZ_CTRL_KEY;
	if (state & GDK_MOD1_MASK)
        	ret->modifier |= KZ_ALT_KEY;
	if (state & GDK_META_MASK)
        	ret->modifier |= KZ_META_KEY;
	
	*kzevent = ret;
}

static gboolean
kz_webkit_gtk_mouse_action_on_element (WebkitUIDelegate *delegate,
				       WebkitView *sender,
				       WebkitElementInfo *element_info,
				       WebkitMouseEventInfo *mouse_info)
{
	KzEmbedEventMouse *kzevent;
	gint ret = FALSE;
	KzWebkitGtkPrivate *priv;
	g_return_val_if_fail(KZ_IS_WEBKIT_GTK(delegate), FALSE);

	priv = KZ_WEBKIT_GTK_GET_PRIVATE(delegate);
	get_mouse_event_info(&kzevent);

	const gchar *link_url = webkit_element_info_get_link_url(element_info);
	if (!link_url)
	{
		if (priv->link_message)
		{
			g_free(priv->link_message);
			priv->link_message = NULL;
			g_signal_emit_by_name(delegate, "kz-link-message");
		}
	}
	else	
	{
		KzEmbedEvent *info = (KzEmbedEvent *) kzevent;
		info->context |= KZ_CONTEXT_LINK;
		info->link = g_strdup(link_url);
		info->linktext = g_strdup(webkit_element_info_get_link_label(element_info));

		if (priv->link_message)
			g_free(priv->link_message);

		priv->link_message = g_strdup(link_url);

		g_signal_emit_by_name(delegate, "kz-link-message");
	}

	g_signal_emit_by_name(delegate, "kz-dom-mouse-over",
			      kzevent, &ret);
	kz_embed_event_free((KzEmbedEvent *) kzevent);
}
#if 0
gboolean
kz_webkit_gtk_mouse_down (WebiMouseDelegate *webi, WebiEventInfo *event_info)
{
	KzEmbedEventMouse *kzevent;
	gint ret = FALSE;
	KzWebkitGtkPrivate *priv;
	g_return_val_if_fail(KZ_IS_WEBKIT_GTK(webi), FALSE);

	priv = KZ_WEBKIT_GTK_GET_PRIVATE(webi);
	priv->button_press_time = GDK_CURRENT_TIME;

	get_mouse_event_info(&kzevent);
	kzevent->button = webi_event_info_get_button((WebiEventInfo*)event_info);

	((KzEmbedEvent *)kzevent)->context |= KZ_CONTEXT_DOCUMENT;
	const gchar *link_url = webi_event_info_get_link_url((WebiEventInfo*)event_info);
	if (link_url)
	{
		((KzEmbedEvent *)kzevent)->context |= KZ_CONTEXT_LINK;
		((KzEmbedEvent *)kzevent)->link = g_strdup(link_url);
	}

	g_signal_emit_by_name(webi, "kz-dom-mouse-down",
			      kzevent, &ret);
	kz_embed_event_free((KzEmbedEvent *) kzevent);

	return ret;
}

static gboolean
kz_webkit_gtk_mouse_up (WebiMouseDelegate *webi, WebiEventInfo *event_info)
{
	KzEmbedEventMouse *kzevent;
	gint ret = FALSE;
	KzWebkitGtkPrivate *priv;
	g_return_val_if_fail(KZ_IS_WEBKIT_GTK(webi), FALSE);

	priv = KZ_WEBKIT_GTK_GET_PRIVATE(webi);

	get_mouse_event_info(&kzevent);
	kzevent->button = webi_event_info_get_button((WebiEventInfo*)event_info);

	((KzEmbedEvent *)kzevent)->context |= KZ_CONTEXT_DOCUMENT;

	g_signal_emit_by_name(webi, "kz-dom-mouse-up",
			      kzevent, &ret);

	if (!ret && GDK_CURRENT_TIME < priv->button_press_time + 1000)
	{
		const gchar *link_url = webi_event_info_get_link_url((WebiEventInfo*)event_info);
		if (link_url)
		{
			((KzEmbedEvent *)kzevent)->context |= KZ_CONTEXT_LINK;
			((KzEmbedEvent *)kzevent)->link = g_strdup(link_url);
		}

		g_signal_emit_by_name(webi, "kz-dom-mouse-click",
				      kzevent, &ret);
	}
	priv->button_press_time = 0;

	kz_embed_event_free((KzEmbedEvent *) kzevent);

	return ret;
}
#endif
static gboolean
kz_webkit_gtk_set_cookie (Webi *webi, const gchar *url, WebiCookie *cookie)
{
	g_return_val_if_fail(KZ_IS_WEBKIT_GTK(webi), FALSE);

	return TRUE;
}

static gboolean
kz_webkit_gtk_is_loading (KzEmbed *kzembed)
{
	g_return_val_if_fail(KZ_IS_WEBKIT_GTK(kzembed), FALSE);

	return KZ_WEBKIT_GTK_GET_PRIVATE(kzembed)->is_loading;
}


static void
kz_webkit_gtk_load_url (KzEmbed *kzembed, const gchar *url)
{
	g_return_if_fail(KZ_IS_WEBKIT_GTK(kzembed));

	webi_load_url(WEBI(kzembed), url);
}


static const gchar *
kz_webkit_gtk_get_title (KzEmbed *kzembed)
{
	g_return_val_if_fail(KZ_IS_WEBKIT_GTK(kzembed), NULL);

	return webi_get_title(WEBI(kzembed));
}


static const gchar *
kz_webkit_gtk_get_location (KzEmbed *kzembed)
{
	const gchar *location;
	g_return_val_if_fail(KZ_IS_WEBKIT_GTK(kzembed), NULL);

	location = webi_get_location(WEBI(kzembed));
	return location ? location : "";
}

static gchar *
kz_webkit_gtk_get_link_message (KzEmbed *kzembed)
{
	g_return_val_if_fail(KZ_IS_WEBKIT_GTK(kzembed), NULL);

	return g_strdup(KZ_WEBKIT_GTK_GET_PRIVATE(kzembed)->link_message);
}

static gchar *
kz_webkit_gtk_ensure_title (KzEmbed *kzembed)
{
	const gchar *title;

	title = kz_webkit_gtk_get_title(kzembed);
	if (title)
		return g_strdup(title);

	title = kz_webkit_gtk_get_location(kzembed);
	if (title)
		return g_strdup(title);

	return g_strdup(_("No title"));
}

static void
kz_webkit_gtk_shistory_get_nth (KzEmbed *kzembed, 
			         int nth,
				 gboolean is_relative,
				 char **aUrl,
				 char **aTitle)
{
	g_return_if_fail(KZ_IS_WEBKIT_GTK(kzembed));
}

static void
kz_webkit_gtk_reload (KzEmbed *kzembed, KzEmbedReloadFlag flags)
{
	g_return_if_fail(KZ_IS_WEBKIT_GTK(kzembed));

	webi_refresh(WEBI(kzembed));
}


static void
kz_webkit_gtk_stop_load (KzEmbed *kzembed)
{
	g_return_if_fail(KZ_IS_WEBKIT_GTK(kzembed));

	webi_stop_load(WEBI(kzembed));
}


static void
kz_webkit_gtk_go_back (KzEmbed *kzembed)
{
	g_return_if_fail(KZ_IS_WEBKIT_GTK(kzembed));

	return webi_go_back(WEBI(kzembed));
}


static void
kz_webkit_gtk_go_forward (KzEmbed *kzembed)
{
	g_return_if_fail(KZ_IS_WEBKIT_GTK(kzembed));

	return webi_go_forward(WEBI(kzembed));
}


static gboolean
kz_webkit_gtk_can_go_back (KzEmbed *kzembed)
{
	g_return_val_if_fail(KZ_IS_WEBKIT_GTK(kzembed), FALSE);

	return webi_can_go_back(WEBI(kzembed));
}


static gboolean
kz_webkit_gtk_can_go_forward (KzEmbed *kzembed)
{
	g_return_val_if_fail(KZ_IS_WEBKIT_GTK(kzembed), FALSE);

	return webi_can_go_forward(WEBI(kzembed));
}


static gboolean
kz_webkit_gtk_can_go_nav_link (KzEmbed *kzembed, KzEmbedNavLink link)
{
	g_return_val_if_fail(KZ_IS_WEBKIT_GTK(kzembed), FALSE);

	return FALSE;
}

static void
kz_webkit_gtk_go_nav_link (KzEmbed *kzembed, KzEmbedNavLink link)
{
	g_return_if_fail(KZ_IS_WEBKIT_GTK(kzembed));

	return;
}

static void
kz_webkit_gtk_set_nth_nav_link (KzEmbed *kzembed,
			   KzEmbedNavLink link,
			   KzNavi *navi,
			   guint n)
{
	g_return_if_fail(KZ_IS_WEBKIT_GTK(kzembed));

	return;
}

static KzNavi *
kz_webkit_gtk_get_nth_nav_link (KzEmbed *kzembed,
			   KzEmbedNavLink link,
			   guint n)
{
	g_return_val_if_fail(KZ_IS_WEBKIT_GTK(kzembed), NULL);

	return NULL;
}

static GList *
kz_webkit_gtk_get_nav_links (KzEmbed *kzembed,
			KzEmbedNavLink link)
{
	g_return_val_if_fail(KZ_IS_WEBKIT_GTK(kzembed), NULL);

	return NULL;
}

static gdouble
kz_webkit_gtk_get_progress (KzEmbed *kzembed)
{
	gdouble progress;
	KzWebkitGtk *webkit_gtk;
	KzWebkitGtkPrivate *priv;

	g_return_val_if_fail(KZ_IS_WEBKIT_GTK(kzembed), 0.0);

	priv = KZ_WEBKIT_GTK_GET_PRIVATE (kzembed);

	webkit_gtk = KZ_WEBKIT_GTK(kzembed);
	if (priv->total_requests <= 0 ||
	    priv->cur_requests <= 0)
	{
		return 0.0;
	}

	progress = (gdouble) priv->cur_requests
		/ (gdouble) priv->total_requests;

	return (progress < 1.0) ? progress : 1.0;
}


static gint
kz_webkit_gtk_get_text_size (KzEmbed *kzembed)
{
	gfloat multiplier;

	g_return_val_if_fail(KZ_IS_WEBKIT_GTK(kzembed), 100);

	multiplier = webi_get_text_multiplier(WEBI(kzembed));
	
	if (multiplier == -1.0) return 100;

	return (gint) rint(multiplier * 100);
}


static void
kz_webkit_gtk_set_text_size (KzEmbed *kzembed, gint zoom, gboolean reflow)
{
	gfloat multiplier;

	g_return_if_fail(KZ_IS_WEBKIT_GTK(kzembed));

	multiplier = (gfloat)(zoom) / 100;

	webi_set_text_multiplier(WEBI(kzembed), multiplier);
}


static gboolean
kz_webkit_gtk_find (KzEmbed *kzembed, const char *keyword, gboolean backward)
{
	g_return_val_if_fail(KZ_IS_WEBKIT_GTK(kzembed), FALSE);

	return webi_find(WEBI(kzembed), keyword, FALSE, backward); 
}

static gboolean
kz_webkit_gtk_can_cut_selection (KzEmbed *kzembed)
{
	g_return_val_if_fail(KZ_IS_WEBKIT_GTK(kzembed), FALSE);

	/* not implemented yet */
	return FALSE;
}

static gboolean
kz_webkit_gtk_can_copy_selection (KzEmbed *kzembed)
{
	g_return_val_if_fail(KZ_IS_WEBKIT_GTK(kzembed), FALSE);

	/* alwasy return TRUE */
	return TRUE;
}

static gboolean
kz_webkit_gtk_can_paste (KzEmbed *kzembed)
{
	g_return_val_if_fail(KZ_IS_WEBKIT_GTK(kzembed), FALSE);
	/* not implemented yet */
	return FALSE;
}

static void
kz_webkit_gtk_cut_selection (KzEmbed *kzembed)
{
	/* not implemented yet */
}

static void
kz_webkit_gtk_copy_selection (KzEmbed *kzembed)
{
	gchar *selected;
	selected = webi_get_current_selection_as_text(WEBI(kzembed));

	gtkutil_copy_text(selected);

	if (selected)
		g_free (selected);
}

static void
kz_webkit_gtk_paste (KzEmbed *kzembed)
{
	/* not implemented yet */
}

static void
kz_webkit_gtk_select_all (KzEmbed *kzembed)
{
	/* not implemented yet */
}

static gboolean
kz_webkit_gtk_selection_is_collapsed (KzEmbed *kzembed)
{
	/* not implemented yet */
	return FALSE;
}

static gboolean
kz_webkit_gtk_get_allow_javascript (KzEmbed *kzembed)
{
	g_return_val_if_fail(KZ_IS_WEBKIT_GTK(kzembed), FALSE);

	WebiSettings *settings = KZ_WEBKIT_GTK_GET_PRIVATE(kzembed)->settings;

	return settings->javascript_enabled ? TRUE : FALSE;
}

static void
kz_webkit_gtk_set_allow_javascript (KzEmbed *kzembed, gboolean allow)
{
	g_return_if_fail(KZ_IS_WEBKIT_GTK(kzembed));

	WebiSettings *settings = KZ_WEBKIT_GTK_GET_PRIVATE(kzembed)->settings;

	settings->javascript_enabled = allow;
	webi_set_settings(WEBI(kzembed), settings);
}

static gboolean
kz_webkit_gtk_get_allow_images (KzEmbed *kzembed)
{
	g_return_val_if_fail(KZ_IS_WEBKIT_GTK(kzembed), FALSE);

	WebiSettings *settings = KZ_WEBKIT_GTK_GET_PRIVATE(kzembed)->settings;

	return settings->autoload_images;
}

static void
kz_webkit_gtk_set_allow_images (KzEmbed *kzembed, gboolean allow)
{
	g_return_if_fail(KZ_IS_WEBKIT_GTK(kzembed));

	WebiSettings *settings = KZ_WEBKIT_GTK_GET_PRIVATE(kzembed)->settings;

	settings->autoload_images = allow;
	webi_set_settings(WEBI(kzembed), settings);
}

static gboolean
kz_webkit_gtk_get_lock (KzEmbed *kzembed)
{
	g_return_val_if_fail(KZ_IS_WEBKIT_GTK(kzembed), FALSE);
	return KZ_WEBKIT_GTK_GET_PRIVATE(kzembed)->lock;
}

static void
kz_webkit_gtk_set_lock (KzEmbed *kzembed, gboolean lock)
{
	g_return_if_fail(KZ_IS_WEBKIT_GTK(kzembed));
	KZ_WEBKIT_GTK_GET_PRIVATE(kzembed)->lock = lock;
}

