/*
 *  Copyright (C) 2003 Crispin Flowerday <gnome@flowerday.cx>
 *
 *  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.
 */

/*
 * Handle Migrations of old gconf keys to new ones
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <gtk/gtksettings.h>
#include <gdk/gdkx.h>
#include <glib.h>

#include "eel-gconf-extensions.h"
#include "galeon-embed-prefs.h"
#include "galeon-embed-shell.h"
#include "prefs-strings.h"
#include "galeon-shell.h"
#include "galeon-embed-shell.h"
#include "migrate.h"
#include "galeon-config.h"

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

#define GALEON_CONFIG_VERSION "/apps/galeon/config_version"

#define INT_ROUND(a) (gint)((a) + 0.5f)

/**
 *  This function gets the dpi in the same way that mozilla gets the dpi, 
 *  this allows us to convert from pixels to points easily
 */
static gint
mozilla_get_dpi ()
{
	GtkSettings* settings = gtk_settings_get_default ();
	gint dpi = 0;
	char *val;
	float screenWidthIn;

	/* Use the gdk-xft-dpi setting if it is set */
	if (g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (settings)),
					  "gtk-xft-dpi"))
	{
		g_object_get (G_OBJECT (settings), "gtk-xft-dpi", &dpi, NULL);
		if (dpi) return INT_ROUND (dpi / PANGO_SCALE);
	}

	/* Fall back to what xft thinks it is */
	val = XGetDefault (GDK_DISPLAY (), "Xft", "dpi");
	if (val)
	{
		char *e;
		double d = strtod(val, &e);
		if (e != val) return INT_ROUND (d);
	}
	
	/* Fall back to calculating manually from the gdk screen settings */
	screenWidthIn = ((float)gdk_screen_width_mm()) / 25.4f;
	return INT_ROUND (gdk_screen_width() / screenWidthIn);
}



static void
mozilla_migrate_font_gconf_key (const char *pixel_key, const char *point_key)
{
	int size;

	size = eel_gconf_get_integer (pixel_key);

	if (size > 0)
	{
		/* Use doubles to get more accurate arithmetic */
		double dpi   = (double)mozilla_get_dpi ();
		double value = (double)eel_gconf_get_integer (pixel_key);
		gint point = INT_ROUND ((value * 72) / dpi);

		eel_gconf_set_integer (point_key, point);
	}
}

#define CONF_RENDERING_FONT_VAR_SIZE_PX   "/apps/galeon/Rendering/font_var_size"
#define CONF_RENDERING_FONT_FIXED_SIZE_PX "/apps/galeon/Rendering/font_fixed_size"
#define CONF_RENDERING_FONT_MIN_SIZE_PX   "/apps/galeon/Rendering/font_min_size"

/*
 * Migrate the mozilla font preferences from pixels to points
 * 
 * Old pref was in 1.3.10, new in 1.3.11
 */
static void
migrate_mozilla_font_prefs ()
{
	GList *list;
	GList *l;
	GaleonEmbedShell *ges= galeon_shell_get_embed_shell (galeon_shell);
	
	galeon_embed_shell_get_font_langs (ges, &list);

	for (l = list ; l ; l = l->next)
	{
		char key[512], oldkey[512];
		const char* language = ((FontLangInfo*)l->data)->key;
		
		sprintf (key, "%s_%s", CONF_RENDERING_FONT_MIN_SIZE, language);
		sprintf (oldkey, "%s_%s", CONF_RENDERING_FONT_MIN_SIZE_PX, language);
		mozilla_migrate_font_gconf_key (oldkey, key);

		sprintf (key, "%s_%s", CONF_RENDERING_FONT_FIXED_SIZE, language);
		sprintf (oldkey, "%s_%s", CONF_RENDERING_FONT_FIXED_SIZE_PX, language);
		mozilla_migrate_font_gconf_key (oldkey, key);

		sprintf (key, "%s_%s", CONF_RENDERING_FONT_VAR_SIZE, language);
		sprintf (oldkey, "%s_%s", CONF_RENDERING_FONT_VAR_SIZE_PX, language);
		mozilla_migrate_font_gconf_key (oldkey, key);
	}

	g_list_foreach (list, (GFunc)g_free, 0);
	g_list_free (list);
}


static void
check_mozilla_charset_pref ()
{
	gchar * value = eel_gconf_get_string (CONF_LANGUAGE_DEFAULT_CHARSET);

	if (value && strchr (value, '('))
	{
		g_warning ("Setting encoding preference to 'ISO-8859-1', was '%s'", value);
		eel_gconf_set_string (CONF_LANGUAGE_DEFAULT_CHARSET, "ISO-8859-1");
	}

	g_free (value);
}

/* Old keys to be able to migrate old proxy prefs to the new location */
#define OLD_NETWORK_PROXY_MODE "/apps/galeon/Advanced/Network/proxy_mode"
#define OLD_NETWORK_HTTP_PROXY "/apps/galeon/Advanced/Network/http_proxy"
#define OLD_NETWORK_SSL_PROXY "/apps/galeon/Advanced/Network/ssl_proxy"
#define OLD_NETWORK_FTP_PROXY "/apps/galeon/Advanced/Network/ftp_proxy"
#define OLD_NETWORK_SOCKS_PROXY "/apps/galeon/Advanced/Network/socks_proxy"
#define OLD_NETWORK_HTTP_PROXY_PORT "/apps/galeon/Advanced/Network/http_proxy_port"
#define OLD_NETWORK_SSL_PROXY_PORT "/apps/galeon/Advanced/Network/ssl_proxy_port"
#define OLD_NETWORK_FTP_PROXY_PORT "/apps/galeon/Advanced/Network/ftp_proxy_port"
#define OLD_NETWORK_SOCKS_PROXY_PORT "/apps/galeon/Advanced/Network/socks_proxy_port"
#define OLD_NETWORK_PROXY_AUTO_URL "/apps/galeon/Advanced/Network/proxy_auto_url"
#define CONF_NETWORK_PROXY_MIGRATED "/apps/galeon/Advanced/Network/proxy_prefs_converted"

static void
migrate_proxy_prefs ()
{
	const gchar *keys[][2] = 
	{{OLD_NETWORK_HTTP_PROXY,       CONF_NETWORK_HTTP_PROXY},
	 {OLD_NETWORK_SSL_PROXY,        CONF_NETWORK_SSL_PROXY},
	 {OLD_NETWORK_FTP_PROXY,        CONF_NETWORK_FTP_PROXY},
	 {OLD_NETWORK_SOCKS_PROXY,      CONF_NETWORK_SOCKS_PROXY}, 
	 {OLD_NETWORK_HTTP_PROXY_PORT,  CONF_NETWORK_HTTP_PROXY_PORT},
	 {OLD_NETWORK_SSL_PROXY_PORT,   CONF_NETWORK_SSL_PROXY_PORT},
	 {OLD_NETWORK_FTP_PROXY_PORT,   CONF_NETWORK_FTP_PROXY_PORT},
	 {OLD_NETWORK_SOCKS_PROXY_PORT, CONF_NETWORK_SOCKS_PROXY_PORT},
	 {OLD_NETWORK_PROXY_AUTO_URL,   CONF_NETWORK_PROXY_AUTO_URL},
	 {NULL, NULL}};
	int proxy_mode;
	const char *proxy_modes[3] = {"none", "manual", "auto"};
	/* 
	 * If the proxy prefs were never migrated, and if the user
	 * has no prefs set for the gnome-wide proxy settings, migrate
	 * its prefs
	 */
	if (!eel_gconf_key_exists (CONF_NETWORK_PROXY_AUTO_URL) &&
	    !eel_gconf_get_boolean (CONF_NETWORK_PROXY_MIGRATED)) 
	{
		GConfValue *value;	
		int i;

		for (i=0; keys[i][0] != NULL; i++)
		{		  
			value = eel_gconf_get_value (keys[i][0]);
			if (value)
			{
				eel_gconf_set_value (keys[i][1], value);
				eel_gconf_value_free (value);
			}
		}

		proxy_mode = eel_gconf_get_integer (OLD_NETWORK_PROXY_MODE);
		if (proxy_mode < 0 || proxy_mode > 2) 
		{
			proxy_mode = 0;
		}
		eel_gconf_set_string (CONF_NETWORK_PROXY_MODE, 
				      proxy_modes[proxy_mode]);
	}
	
	eel_gconf_set_boolean (CONF_NETWORK_PROXY_MIGRATED, TRUE);	
}


#define CONF_TOOLBAR_SETUP "/apps/galeon/UI/Toolbar/setup"

static struct toolbar_conversion
{
	const char *old_type;
	const char *new_type;
} toolbar_map[] = {
	{ "back=",         "GoBack" },
	{ "back_menu=",    "GoBackWithArrow" },
	{ "forward=",      "GoForward" },
	{ "forward_menu=", "GoForwardWithArrow" },
	{ "up=",           "GoUp" },
	{ "up_menu=",      "GoUpWithArrow" },
	{ "location=",     "LocationEntry" },
	{ "home=",         "GoHome" },
	{ "new=",          "New" },
	{ "reload=",       "Refresh" },
	{ "stop=",         "Stop" },
	{ "go=",           "GoTo" },
	{ "zoom=",         "ZoomSpinner" },
	{ "spinner=",      "LogoSpinner" },
	{ "favicon=",      "Favicon" },
	{ "fullscreen=",   "Fullscreen" }
};

/*! Migrate the toolbar settings from Galeon 1.3.11 to 1.3.12
 */
static void
migrate_toolbar ()
{
	gchar *tb_file = g_build_filename (g_get_home_dir (), 
					   GALEON_DIR, "toolbars.xml", NULL);

	gchar *toolbar;
	gchar **items, **item;
	GString *xml;
	FILE *file;

	if (g_file_test (tb_file, G_FILE_TEST_EXISTS))
	{
		g_free (tb_file);
		return;
	}

	toolbar = eel_gconf_get_string (CONF_TOOLBAR_SETUP);
	if (!toolbar)
	{
		g_free (tb_file);
		return;
	}

	xml = g_string_new (NULL);
	g_string_append (xml, "<?xml version=\"1.0\"?>\n"
			 "<toolbars version=\"0\">\n"
			 "  <toolbar name=\"MigratedToolbar\">\n");

	items = g_strsplit (toolbar, ";", 0);
	for (item = items; *item; item++)
	{
		gchar *str = *item;
		const gchar *new_type = NULL;
		guint i;

		for (i = 0 ; i < G_N_ELEMENTS (toolbar_map); i++)
		{
			if (g_str_has_prefix (str, toolbar_map[i].old_type))
			{
				new_type = toolbar_map[i].new_type;
				break;
			}
		}

		if (new_type)
		{
			g_string_append_printf (xml, 
				       "    <toolitem type=\"application/x-toolbar-item\""
               			       " name=\"%s\"/>\n", toolbar_map[i].new_type);

		}
		else if (strcmp (str, "=separator") == 0)
		{
			g_string_append (xml, "    <separator/>\n");
		}
		else
		{
			g_warning ("Unknown toolbar type: %s", str);
		}
	}

	g_free (toolbar);
	g_strfreev (items);
	
	g_string_append (xml, "  </toolbar>\n</toolbars>\n");

	if (!(file = fopen (tb_file, "w"))) 
	{
		g_warning ("Could not open file '%s': %s", 
			   tb_file, g_strerror (errno));
		g_string_free (xml, TRUE);
		g_free (tb_file);
		return;
	}

	if (fputs (xml->str, file) == -1)
	{
		g_warning ("Could not save to file '%s': %s",
			   tb_file, g_strerror (errno));
		g_string_free (xml, TRUE);
		g_free (tb_file);
		return;
	}
	g_string_free (xml, TRUE);

	if (fclose (file) == -1)
	{
		g_warning ("Could not close file '%s': %s",
			   tb_file, g_strerror (errno));
	}
	g_free (tb_file);
}


#define CONF_OLD_TOOLBAR_STYLE "/apps/galeon/UI/Toolbar/toolbar_style"

/**
 * Migrate the old toolbar style gconf key to the new (and better)
 * format (the format was changed in 1.3.13)
 */
static void
migrate_toolbar_style()
{
	const char * value = "system";
	int old_setting;

	if (!eel_gconf_is_default (CONF_TOOLBAR_STYLE) ||
	    !eel_gconf_key_exists (CONF_OLD_TOOLBAR_STYLE))
	{
		return;
	}

	old_setting = eel_gconf_get_integer (CONF_OLD_TOOLBAR_STYLE);
	switch (old_setting)
	{
	case 0: value = "text_beside"; break;
	case 1: value = "text_below";  break;
	case 2: value = "text_only";   break;
	case 3: value = "icons_only";  break;
	}
	eel_gconf_set_string (CONF_TOOLBAR_STYLE, value);
}


typedef void (*GaleonMigrateFunc) ();

/* The order of these functions is important, you MUST NOT remove
 * any entries (although they can be changed to NULL), and they
 * MUST not be re-ordered */
static GaleonMigrateFunc migrate_funcs[] = {
	migrate_proxy_prefs,
	check_mozilla_charset_pref,
	migrate_mozilla_font_prefs,
	migrate_toolbar,
	migrate_toolbar_style
	/* Add new Migrate functions here */
};

/*
 * Work out what settings need migrating, and migrate them
 */
void
migrate_gconf_settings ()
{
	int conf_version = 0;
	int i, num_migrate_funcs;

	if (eel_gconf_key_exists (GALEON_CONFIG_VERSION))
	{
		conf_version = eel_gconf_get_integer (GALEON_CONFIG_VERSION);
	}

	num_migrate_funcs = G_N_ELEMENTS(migrate_funcs);

	if (conf_version >= num_migrate_funcs) return;

	for (i = conf_version ; i < num_migrate_funcs ; i++ )
	{
		if (migrate_funcs[i]) (migrate_funcs[i])();	
	}

	eel_gconf_set_integer (GALEON_CONFIG_VERSION, num_migrate_funcs);
}
