/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/***************************************************************************
 *            camel-kolab-imapx-provider.c
 *
 *  Thu Jun 10 19:27:45 2010
 *  Copyright  2010  Christian Hilberg
 *  <hilberg@kernelconcepts.de>
 ****************************************************************************/

/*
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser 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
 */

/*----------------------------------------------------------------------------*/

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

#include <string.h>
#include <glib/gi18n-lib.h>

#include <libekolabutil/kolab-util-camel.h>
#include <libekolabutil/camel-system-headers.h>

/* IMAPX specifics
 *
 *      The following header files are not installed,
 *      their API is not public to Camel users, so we
 *      need to keep our own local IMAPX around.
 */
#include <camel/providers/imapx/camel-imapx-utils.h>

#include "camel-kolab-imapx-provider.h"
#include "camel-kolab-imapx-store.h"

/*----------------------------------------------------------------------------*/

CamelProviderConfEntry kolab_conf_entries[] = {
	{ CAMEL_PROVIDER_CONF_SECTION_START, "mailcheck", NULL,
	  N_("Checking for New Mail") },
	{ CAMEL_PROVIDER_CONF_CHECKBOX, "check-all", NULL,
	  N_("C_heck for new messages in all folders"), "1" },
	{ CAMEL_PROVIDER_CONF_CHECKBOX, "check-subscribed", NULL,
	  N_("Ch_eck for new messages in subscribed folders"), "0" },
	{ CAMEL_PROVIDER_CONF_CHECKBOX, "use-qresync", NULL,
	  N_("Use _Quick Resync if the server supports it"), "1" },
	{ CAMEL_PROVIDER_CONF_CHECKBOX, "use-idle", NULL,
	  N_("_Listen for server change notifications"), "1" },
	{ CAMEL_PROVIDER_CONF_SECTION_END },
#ifndef G_OS_WIN32
	{ CAMEL_PROVIDER_CONF_SECTION_START, "cmdsection", NULL,
	  N_("Connection to Server") },
	{ CAMEL_PROVIDER_CONF_CHECKBOX, "use-shell-command", NULL,
	  N_("_Use custom command to connect to server"), "0" },
	{ CAMEL_PROVIDER_CONF_ENTRY, "shell-command", "use-shell-command",
	  N_("Command:"), "ssh -C -l %u %h exec /usr/sbin/dovecot --exec-mail imap" },
	{ CAMEL_PROVIDER_CONF_CHECKSPIN, "concurrent-connections", NULL,
	  N_("Numbe_r of cached connections to use"), "y:1:5:7" },
	{ CAMEL_PROVIDER_CONF_SECTION_END },
#endif
	{ CAMEL_PROVIDER_CONF_SECTION_START, "folders", NULL,
	  N_("Folders") },
	{ CAMEL_PROVIDER_CONF_CHECKBOX, "use-subscriptions", NULL,
	  N_("_Show only subscribed folders"), "1" },
	{ CAMEL_PROVIDER_CONF_SECTION_END },
	{ CAMEL_PROVIDER_CONF_SECTION_START, "general", NULL, N_("Options") },
	{ CAMEL_PROVIDER_CONF_CHECKBOX, "filter-all", NULL,
	  N_("Apply _filters to new messages in all folders"), "0" },
	{ CAMEL_PROVIDER_CONF_CHECKBOX, "filter-inbox", "!filter-all",
	  N_("_Apply filters to new messages in Inbox on this server"), "1" },
	{ CAMEL_PROVIDER_CONF_CHECKBOX, "filter-junk", NULL,
	  N_("Check new messages for _Junk contents"), "0" },
	{ CAMEL_PROVIDER_CONF_CHECKBOX, "filter-junk-inbox", "filter-junk",
	  N_("Only check for Junk messages in the IN_BOX folder"), "0" },
	{ CAMEL_PROVIDER_CONF_CHECKBOX, "stay-synchronized", NULL,
	  N_("Automatically synchroni_ze remote mail locally"), "0" },
	{ CAMEL_PROVIDER_CONF_SECTION_END },
	{ CAMEL_PROVIDER_CONF_END }
};

CamelProviderPortEntry kolab_port_entries[] = {
	{ 143, N_("Default IMAP port"), FALSE },
	{ 993, N_("IMAP over SSL"), TRUE },
	{ 0, NULL, 0 }
};

static CamelProvider kolab_provider = {
	KOLAB_CAMEL_PROVIDER_PROTOCOL,

	N_("Kolab2"),

	N_("For reading and storing mail on Kolab servers."),

	"mail",

	CAMEL_PROVIDER_IS_REMOTE | CAMEL_PROVIDER_IS_SOURCE |
	CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_SUPPORTS_SSL,

	CAMEL_URL_NEED_USER | CAMEL_URL_NEED_HOST | CAMEL_URL_ALLOW_AUTH,

	kolab_conf_entries,

	kolab_port_entries,

	/* ... */
};

CamelServiceAuthType kolab_password_authtype = {
	N_("Password"),

	N_("This option will connect to the Kolab server using a "
	   "plaintext password."),

	"",
	TRUE
};

/*----------------------------------------------------------------------------*/
/* local forward declarations */

static guint kolab_url_hash (gconstpointer);
static gint kolab_url_equal (gconstpointer, gconstpointer);

/*----------------------------------------------------------------------------*/
/* external symbols */

extern void camel_imapx_module_init (void);

/*----------------------------------------------------------------------------*/

void
camel_kolab_imapx_provider_module_init (void)
{
	CamelProvider *imapx_provider = NULL;
	GError *tmp_err = NULL;

	/* Load and init the parent module, if that not already
	 * happened. The CamelProvider returned is owned by Camel,
	 * so we must not free() it
	 */
	imapx_provider = camel_provider_get ("imapx",
	                                     &tmp_err);
	if (tmp_err != NULL) {
		/* cannot propagate errors from here... */
		g_warning ("%s: %s",
		           __func__, tmp_err->message);
		g_error_free (tmp_err);
	}
	/* last resort... */
	g_assert (imapx_provider != NULL);

	kolab_provider.object_types[CAMEL_PROVIDER_STORE] = camel_kolab_imapx_store_get_type ();
	kolab_provider.object_types[CAMEL_PROVIDER_TRANSPORT] = G_TYPE_INVALID;
	kolab_provider.url_hash = kolab_url_hash;
	kolab_provider.url_equal = kolab_url_equal;
	kolab_provider.authtypes = camel_sasl_authtype_list (FALSE);
	kolab_provider.authtypes = g_list_prepend (kolab_provider.authtypes,
	                                           &kolab_password_authtype);
	kolab_provider.translation_domain = GETTEXT_PACKAGE;

	g_assert (kolab_provider.object_types[CAMEL_PROVIDER_STORE] != G_TYPE_INVALID);
	g_debug ("%s: done", __func__);
}

void
camel_provider_module_init (void)
{
	camel_kolab_imapx_provider_module_init ();
	camel_provider_register (&kolab_provider);
	g_debug ("%s: %s provider registered",
	         __func__, KOLAB_CAMEL_PROVIDER_PROTOCOL);
}

/*----------------------------------------------------------------------------*/

static void
kolab_add_hash (guint *hash, char *s)
{
	if (s)
		*hash ^= g_str_hash(s);
}

static guint
kolab_url_hash (gconstpointer key)
{
	const CamelURL *u = (CamelURL *)key;
	guint hash = 0;

	kolab_add_hash (&hash, u->user);
	kolab_add_hash (&hash, u->authmech);
	kolab_add_hash (&hash, u->host);
	hash ^= (guint)u->port;

	return hash;
}

static gint
kolab_check_equal (char *s1, char *s2)
{
	if (s1 == NULL) {
		if (s2 == NULL)
			return TRUE;
		else
			return FALSE;
	}
	if (s2 == NULL)
		return FALSE;

	return strcmp (s1, s2) == 0;
}

static gint
kolab_url_equal (gconstpointer a, gconstpointer b)
{
	const CamelURL	*u1 = a;
	const CamelURL	*u2 = b;

	return kolab_check_equal (u1->protocol, u2->protocol)
		&& kolab_check_equal (u1->user, u2->user)
		&& kolab_check_equal (u1->authmech, u2->authmech)
		&& kolab_check_equal (u1->host, u2->host)
		&& u1->port == u2->port;
}

/*----------------------------------------------------------------------------*/
