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

//
//  Copyright (C) 2002-2003 Hiroyuki Ikezoe
//  Copyright (C) 2003 Takuro Ashie
//
//  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.
//

#define MOZILLA_CLIENT

#include "mozilla-prefs.h"

#include <gtkmozembed.h>
#define MOZILLA_STRICT_API
#include <nsEmbedString.h>
#undef MOZILLA_STRICT_API
#include <nsCOMPtr.h>
#include <nsIPrefService.h>
#include <nsISupportsPrimitives.h>
#include <nsServiceManagerUtils.h>
#include <nsIFontEnumerator.h>
#include <nsISimpleEnumerator.h>
#include <nsMemory.h>

#include "kazehakase.h"
#include "kz-profile.h"
#include "kz-proxy-item.h"

typedef struct {
	const gchar *section_name;
	const gchar *key_name;
	const gchar *moz_pref_name;
} MigrationPref;

typedef struct {
	const gchar *section_name;
	const gchar *key_name;
	const gchar *moz_pref_name;
} MigrationIntPref;

const static MigrationPref str_pref[] =
{
  {"Font", "default", "font.default" },
  {"Font", "language_group", "font.language.group" },
  {"Language", "accept_languages", "intl.accept_languages" },
  {"Language", "charset_default", "intl.charset.default" },
  {"Language", "charset_detector", "intl.charset.detector" },
};
const static gint n_str_pref = G_N_ELEMENTS(str_pref);

const static MigrationPref int_pref[] =
{
  {"Privacy", "cookie_behaviour", "network.cookie.cookieBehavior" },
  {"Privacy", "cookie_lifetime_policy", "network.cookie.cookiePolicy" },
  {"Privacy", "cookie_lifetime_days", "network.cookie.lifetime.days" },
  {"Privacy", "cookie_always_accept_sesion_cookie", "network.cookie.alwaysAcceptSessionCookies" },
};
const static gint n_int_pref = G_N_ELEMENTS(int_pref);

const static MigrationPref boolean_pref[] =
{
  {"Privacy", "cookie_always_accept_sesion_cookie", "network.cookie.alwaysAcceptSessionCookies" },
};
const static gint n_boolean_pref = G_N_ELEMENTS(boolean_pref);

const static MigrationPref variable_str_pref[] =
{
  {"Font", NULL, "font.name." },
};
const static gint n_variable_str_pref = G_N_ELEMENTS(variable_str_pref);

const static MigrationPref variable_int_pref[] =
{
  {"Font", NULL, "font.size." },
  {"Font", NULL, "font.min-size." },
};

const static gint n_variable_int_pref = G_N_ELEMENTS(variable_int_pref);

#define MOZPREFS_TO_KZ_PROFILE(type_name, TYPE_NAME) \
{ \
	g##type_name value; \
	for (i = 0; i < n_##type_name##_pref; i++) \
	{ \
		if (mozilla_prefs_get_##type_name(type_name##_pref[i].moz_pref_name, &value)) \
		{ \
			kz_profile_set_value(profile, \
					     type_name##_pref[i].section_name, \
					     type_name##_pref[i].key_name, \
					     &value, sizeof(value), \
					     KZ_PROFILE_VALUE_TYPE_##TYPE_NAME); \
		} \
	} \
}

static gchar *
convert_to_mozpref_name (const gchar *prefix, const gchar *key)
{
	gint i = 0;
	gchar *ret;

	g_return_val_if_fail(g_str_has_prefix(key, prefix), NULL);

	ret = g_strdup(key + strlen(prefix) + 1);	

	while (ret[i] != '\0')
	{
		switch (ret[i])
		{
		case '.': 
			ret[i] = '_';
			break;
		}
		i++;
	}

	return ret;
}

static void
mozilla_prefs_migrate (KzProfile *profile)
{
	gboolean exist;
	gchar dummy[1024];
	gchar *string_value = NULL;
	gint int_value, i;

	exist = kz_profile_get_value(profile, "Font", "default", 
				     &dummy, G_N_ELEMENTS(dummy),
				     KZ_PROFILE_VALUE_TYPE_STRING);
	if (exist)
		return;

	MOZPREFS_TO_KZ_PROFILE(int, INT);
	MOZPREFS_TO_KZ_PROFILE(boolean, BOOL);

	for (i = 0; i < n_str_pref; i++)
	{
		if (mozilla_prefs_get_string(str_pref[i].moz_pref_name, &string_value))
		{
			kz_profile_set_value(profile,
					     str_pref[i].section_name,
					     str_pref[i].key_name,
					     string_value, strlen(string_value) + 1,
					     KZ_PROFILE_VALUE_TYPE_STRING);
			g_free(string_value);
		}
	}

	for (i = 0; i < n_variable_str_pref; i++)
	{
		PRUint32 count, n;
		char **childArray;
		nsresult rv;
		nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
		if (NS_SUCCEEDED(prefs->GetChildList(variable_str_pref[i].moz_pref_name, &count, &childArray)))
		{
			for (n = 0; n < count; n++)
			{
				PRBool b;
				prefs->PrefHasUserValue(childArray[n], &b);
				if (b)
				{
					gchar *name;
					name = convert_to_mozpref_name("font", childArray[n]);
					if (!name) continue;

					prefs->GetCharPref(childArray[n], &string_value);
					kz_profile_set_value(profile,
							     variable_str_pref[i].section_name, name,
							     string_value, strlen(string_value) + 1,
							     KZ_PROFILE_VALUE_TYPE_STRING);
					g_free(string_value);
					g_free(name);
				}
			}
			NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, childArray);
		}
	}

	for (i = 0; i < n_variable_int_pref; i++)
	{
		PRUint32 count, n;
		char **childArray;
		nsresult rv;
		nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
		if (NS_SUCCEEDED(prefs->GetChildList(variable_int_pref[i].moz_pref_name, &count, &childArray)))
		{
			for (n = 0; n < count; n++)
			{
				PRBool b;
				prefs->PrefHasUserValue(childArray[n], &b);
				if (b)
				{
					gchar *name;
					name = convert_to_mozpref_name("font", childArray[n]);
					if (!name) continue;

					prefs->GetIntPref(childArray[n], &int_value);
					kz_profile_set_value(profile,
							     variable_int_pref[i].section_name, name,
							     &int_value, sizeof(int_value),
							     KZ_PROFILE_VALUE_TYPE_INT);
					g_free(name);
				}
			}
			NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, childArray);
		}
	}
}

gboolean
mozilla_prefs_init (void)
{
	gchar *full_path;

	full_path = g_build_filename(g_get_home_dir(), 
		   		     "."PACKAGE,
				     "mozilla",
				     NULL);
	gtk_moz_embed_set_profile_path(full_path, "kazehakase");

	g_free(full_path);

	return TRUE;
}


void 
mozilla_prefs_set (KzProfile *profile)
{
	char *value;
	gboolean use_proxy = FALSE;
	gchar proxy_name[1024];
	gboolean conf_exist = FALSE, use_proxy_exist = FALSE;
	KzProxyItem *item = NULL;

	if (!mozilla_prefs_get_string("kazehakase.font.language", &value))
	{
		mozilla_prefs_set_string("kazehakase.font.language",
					 "x-western");
	}
	else
	{
		g_free(value);
	}

	// set default charset to ISO-8859-1
	if (!mozilla_prefs_get_string("intl.charset.default", &value))
	{
		mozilla_prefs_set_string("intl.charset.default",
					 "ISO-8859-1");
	}
	else
	{
		if (!strcmp(value, "chrome://global-platform/locale/intl.properties"))
		{
			mozilla_prefs_set_string("intl.charset.default",
						 "ISO-8859-1");
		}
		g_free(value);
	}
	
	use_proxy_exist = kz_profile_get_value(profile, "Global", "use_proxy", 
					       &use_proxy, sizeof(gboolean),
					       KZ_PROFILE_VALUE_TYPE_BOOL);
	conf_exist = kz_profile_get_value(profile, "Global" , "proxy_name",
					  &proxy_name, sizeof(proxy_name),
					  KZ_PROFILE_VALUE_TYPE_STRING);

	if (!use_proxy_exist && conf_exist)
		use_proxy = TRUE;
	if (use_proxy)
	{
		mozilla_prefs_set_use_proxy(TRUE);
		if (conf_exist)
			item = kz_proxy_find(proxy_name);
		if (item)
		{
			mozilla_prefs_set_proxy(item);
			g_object_unref(item);
		}
	}
	else
	{
		mozilla_prefs_set_use_proxy(FALSE);
	}
	mozilla_prefs_migrate(profile);
}


gboolean
mozilla_prefs_get_string(const char *preference_name, char **value)
{
	g_return_val_if_fail(preference_name != NULL, FALSE);

	g_return_val_if_fail(value, FALSE);

	nsCOMPtr<nsIPrefService> prefService = 
				do_GetService (NS_PREFSERVICE_CONTRACTID);
	nsCOMPtr<nsIPrefBranch> pref;
	prefService->GetBranch("", getter_AddRefs(pref));

	if (pref)
	{
		nsresult rv = pref->GetCharPref(preference_name, value);
		return NS_SUCCEEDED(rv) ? TRUE : FALSE;
	}

	return FALSE;
}


gboolean
mozilla_prefs_get_int(const char *preference_name, int *value)
{
	g_return_val_if_fail(preference_name != NULL, FALSE);

	g_return_val_if_fail(value, FALSE);

	nsCOMPtr<nsIPrefService> prefService = 
				do_GetService(NS_PREFSERVICE_CONTRACTID);
	nsCOMPtr<nsIPrefBranch> pref;
	prefService->GetBranch("", getter_AddRefs(pref));

	if (pref)
	{
		nsresult rv = pref->GetIntPref(preference_name, value);
		return NS_SUCCEEDED(rv) ? TRUE : FALSE;
	}

	return FALSE;
}


gboolean
mozilla_prefs_get_boolean(const char *preference_name, gboolean *value)
{
	g_return_val_if_fail(preference_name != NULL, FALSE);

	g_return_val_if_fail(value, FALSE);

	nsCOMPtr<nsIPrefService> prefService = 
				do_GetService(NS_PREFSERVICE_CONTRACTID);
	nsCOMPtr<nsIPrefBranch> pref;
	prefService->GetBranch("", getter_AddRefs(pref));

	if (pref)
	{
		nsresult rv = pref->GetBoolPref(preference_name, value);
		return NS_SUCCEEDED(rv) ? TRUE : FALSE;
	}

	return FALSE;
}


//
// this function is picked from galeon-1.2.7
// mozilla_preference_set: set a string mozilla preference
//
gboolean
mozilla_prefs_set_string(const char *preference_name, const char *new_value)
{
	g_return_val_if_fail(preference_name != NULL, FALSE);

	// It is legitimate to pass in a NULL value sometimes. So let's not
	// assert and just check and return.
	if (!new_value) return FALSE;

	nsCOMPtr<nsIPrefService> prefService = 
				do_GetService(NS_PREFSERVICE_CONTRACTID);
	nsCOMPtr<nsIPrefBranch> pref;
	prefService->GetBranch("", getter_AddRefs(pref));

	if (pref)
	{
		nsresult rv = pref->SetCharPref(preference_name, new_value);
		return NS_SUCCEEDED(rv) ? TRUE : FALSE;
	}

	return FALSE;
}


//
// this function is picked from galeon-1.2.7
// mozilla_preference_set_boolean: set a boolean mozilla preference
//
gboolean
mozilla_prefs_set_boolean (const char *preference_name,
			   gboolean new_boolean_value)
{
	g_return_val_if_fail(preference_name != NULL, FALSE);
  
	nsCOMPtr<nsIPrefService> prefService = 
				do_GetService(NS_PREFSERVICE_CONTRACTID);
	nsCOMPtr<nsIPrefBranch> pref;
	prefService->GetBranch("", getter_AddRefs(pref));
  
	if (pref)
	{
		nsresult rv = pref->SetBoolPref(preference_name,
				new_boolean_value ? PR_TRUE : PR_FALSE);
		return NS_SUCCEEDED(rv) ? TRUE : FALSE;
	}

	return FALSE;
}


//
// this function is picked from galeon-1.2.7
// mozilla_preference_set_int: set an integer mozilla preference
//
gboolean
mozilla_prefs_set_int (const char *preference_name, int new_int_value)
{
	g_return_val_if_fail(preference_name != NULL, FALSE);

	nsCOMPtr<nsIPrefService> prefService = 
				do_GetService(NS_PREFSERVICE_CONTRACTID);
	nsCOMPtr<nsIPrefBranch> pref;
	prefService->GetBranch("", getter_AddRefs(pref));

	if (pref)
	{
		nsresult rv = pref->SetIntPref(preference_name, new_int_value);
		return NS_SUCCEEDED(rv) ? TRUE : FALSE;
	}

	return FALSE;
}


void
mozilla_prefs_set_use_proxy (gboolean use)
{
	if (use)
		mozilla_prefs_set_int("network.proxy.type", 1);
	else
		mozilla_prefs_set_int("network.proxy.type", 0);
}


void
mozilla_prefs_set_proxy (KzProxyItem *item)
{
	gboolean use_same_proxy;
	gchar *http_host, *https_host, *ftp_host, *no_proxies_on;
	guint http_port, https_port, ftp_port;

	g_return_if_fail(KZ_IS_PROXY_ITEM(item));

	g_object_get(G_OBJECT(item),
		     "use_same_proxy", &use_same_proxy,
		     "http_host", &http_host,
		     "http_port", &http_port,
		     "https_host", &https_host,
		     "https_port", &https_port,
		     "ftp_host", &ftp_host,
		     "ftp_port", &ftp_port,
		     "no_proxies_on", &no_proxies_on,
		     NULL);

	mozilla_prefs_set_use_proxy(TRUE);
	mozilla_prefs_set_string("network.proxy.http",          http_host);
	mozilla_prefs_set_int   ("network.proxy.http_port",     http_port);
	mozilla_prefs_set_string("network.proxy.no_proxies_on", no_proxies_on);

	if (use_same_proxy)
	{
		if (https_host)
			g_free(https_host);
		if (ftp_host)
			g_free(ftp_host);

		https_host = ftp_host = http_host;
		http_port = ftp_port = http_port;
	}
	else
	{
		if (!https_host)
		{
			https_host = "";
			https_port = 0;
		}
		if (!ftp_host)
		{
			ftp_host = "";
			ftp_port = 0;
		}
	}
	mozilla_prefs_set_string("network.proxy.ssl",      https_host);
	mozilla_prefs_set_int   ("network.proxy.ssl_port", https_port);
	mozilla_prefs_set_string("network.proxy.ftp",      ftp_host);
	mozilla_prefs_set_int   ("network.proxy.ftp_port", ftp_port);

	if (http_host)
		g_free(http_host);
	if (no_proxies_on)
		g_free(no_proxies_on);
}

gboolean
mozilla_prefs_clear (const char *preference_name)
{
	g_return_val_if_fail(preference_name != NULL, FALSE);

	nsCOMPtr<nsIPrefService> prefService =
		do_GetService(NS_PREFSERVICE_CONTRACTID);
	nsCOMPtr<nsIPrefBranch> pref;
	prefService->GetBranch("", getter_AddRefs(pref));

	if (pref)
	{
		nsresult rv = pref->ClearUserPref(preference_name);
		return NS_SUCCEEDED(rv) ? TRUE : FALSE;
	}

	return FALSE;
}
