/*
 * Mail Notification
 * Copyright (C) 2003-2008 Jean-Yves Lefort <jylefort@brutele.be>
 *
 * 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 3 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 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.
 */

%headertop{
#include "mn-vfs-mailbox-backend.h"
%}

%{
#include <glib/gi18n.h>
#include "mn-mailbox-private.h"
#include "mn-reentrant-mailbox-private.h"
#include "mn-vfs-mailbox-backend-private.h"
#include "mn-vfs.h"
#include "mn-util.h"
#include "mn-message-mime.h"

#define SEQUENCES_FILE			".mh_sequences"
#define XMH_CACHE_FILE			".xmhcache"
%}

class MN:MH:Mailbox:Backend from MN:VFS:Mailbox:Backend
{
  class_init (class)
  {
    MN_VFS_MAILBOX_BACKEND_CLASS(class)->format = "MH";
  }

  constructor (self)
  {
    MNVFSMailboxBackend *backend = MN_VFS_MAILBOX_BACKEND(self);

    /*
     * There is no standard way of locking a MH mailbox, so avoid race
     * conditions by setting a check latency of 3 seconds.
     */

    backend->check_latency = 3000;
  }

  override (MN:VFS:Mailbox:Backend) void
    monitor_cb (MNVFSMailboxBackend *backend,
		const char *info_uri,
		GnomeVFSMonitorEventType event_type)
  {
    if (event_type == GNOME_VFS_MONITOR_EVENT_CHANGED
	|| event_type == GNOME_VFS_MONITOR_EVENT_DELETED
	|| event_type == GNOME_VFS_MONITOR_EVENT_CREATED)
      {
	char *filename;

	filename = mn_vfs_uri_extract_short_name(info_uri);
	if (filename)
	  {
	    if (! strcmp(filename, SEQUENCES_FILE) || mn_str_isnumeric(filename))
	      mn_vfs_mailbox_backend_queue_check(backend);

	    g_free(filename);
	  }
      }
  }

  override (MN:VFS:Mailbox:Backend) gboolean
    is (MNVFSMailboxBackend *dummy,
	MNVFSMailboxBackendClass *class,
	MNVFSMailbox *mailbox)
  {
    GnomeVFSURI *sequences_uri;
    gboolean is;

    sequences_uri = gnome_vfs_uri_append_file_name(mailbox->vfs_uri, SEQUENCES_FILE);
    is = mn_vfs_test(sequences_uri, G_FILE_TEST_IS_REGULAR);
    gnome_vfs_uri_unref(sequences_uri);

    if (! is)
      {
	GnomeVFSURI *cache_uri;

	cache_uri = gnome_vfs_uri_append_file_name(mailbox->vfs_uri, XMH_CACHE_FILE);
	is = mn_vfs_test(cache_uri, G_FILE_TEST_IS_REGULAR);
	gnome_vfs_uri_unref(cache_uri);
      }

    return is;
  }

  override (MN:VFS:Mailbox:Backend) void
    check (MNVFSMailboxBackend *backend, int check_id)
  {
    GnomeVFSURI *sequences_uri;
    GnomeVFSResult result;
    GnomeVFSHandle *handle;

    mn_vfs_mailbox_backend_monitor(backend, check_id, backend->mailbox->uri, GNOME_VFS_MONITOR_DIRECTORY);

    sequences_uri = gnome_vfs_uri_append_file_name(backend->mailbox->vfs_uri, SEQUENCES_FILE);
    result = gnome_vfs_open_uri(&handle, sequences_uri, GNOME_VFS_OPEN_READ);
    gnome_vfs_uri_unref(sequences_uri);

    if (result == GNOME_VFS_OK)
      {
	MNVFSReadLineContext *context = NULL;
	const char *line;
	GSList *messages = NULL;
	int num_errors = 0;
	GnomeVFSResult close_result;

	while ((result = mn_vfs_read_line(&context, handle, &line)) == GNOME_VFS_OK)
	  if (g_str_has_prefix(line, "unseen: "))
	    {
	      int first;
	      char **elements;
	      int i;

	      elements = g_strsplit(line + 8, " ", 0);
	      for (i = 0; elements[i]; i++)
		{
		  int last;
		  int n;

		  n = sscanf(elements[i], "%d-%d", &first, &last);
		  if (n >= 1)
		    {
		      int j;

		      if (n == 1)
			last = first;

		      for (j = first; j <= last; j++)
			{
			  char *filename;
			  GnomeVFSURI *message_uri;
			  MNMessage *message;
			  GError *err = NULL;

			  if (mn_reentrant_mailbox_check_aborted(MN_REENTRANT_MAILBOX(backend->mailbox), check_id))
			    {
			      g_strfreev(elements);
			      goto loop_end;
			    }

			  filename = g_strdup_printf("%i", j);
			  message_uri = gnome_vfs_uri_append_file_name(backend->mailbox->vfs_uri, filename);
			  g_free(filename);

			  /*
			   * We set handle_status to FALSE, since
			   * messages in the unseen sequence are by
			   * definition unseen (that is, new).
			   */

			  message = mn_message_new_from_uri(MN_MAILBOX(backend->mailbox),
							    message_uri,
							    MN_MESSAGE_NEW,
							    FALSE,
							    &err);
			  if (message)
			    messages = g_slist_prepend(messages, message);
			  else if (err)
			    {
			      char *message_text_uri;

			      message_text_uri = gnome_vfs_uri_to_string(message_uri, GNOME_VFS_URI_HIDE_PASSWORD);
			      mn_mailbox_warning(MN_MAILBOX(backend->mailbox), "cannot read message \"%s\": %s",
						 message_text_uri, err->message);
			      g_free(message_text_uri);
			      g_error_free(err);

			      num_errors++;
			    }

			  gnome_vfs_uri_unref(message_uri);
			}
		    }
		}
	      g_strfreev(elements);
	    }

      loop_end:
	mn_vfs_read_line_context_free(context);
	close_result = gnome_vfs_close(handle);

	GDK_THREADS_ENTER();

	if (! mn_reentrant_mailbox_check_aborted(MN_REENTRANT_MAILBOX(backend->mailbox), check_id))
	  {
	    if (result == GNOME_VFS_ERROR_EOF || result == GNOME_VFS_OK)
	      {
		if (close_result == GNOME_VFS_OK)
		  {
		    mn_mailbox_set_messages(MN_MAILBOX(backend->mailbox), messages);

		    if (num_errors != 0)
		      mn_mailbox_set_error(MN_MAILBOX(backend->mailbox),
					   ngettext("cannot read %i message",
						    "cannot read %i messages",
						    num_errors),
					   num_errors);
		  }
		else
		  mn_mailbox_set_error(MN_MAILBOX(backend->mailbox), _("unable to close %s: %s"), SEQUENCES_FILE, gnome_vfs_result_to_string(close_result));
	      }
	    else
	      mn_mailbox_set_error(MN_MAILBOX(backend->mailbox), _("error while reading %s: %s"), SEQUENCES_FILE, gnome_vfs_result_to_string(result));
	  }

	mn_g_object_slist_free(messages);

	gdk_flush();
	GDK_THREADS_LEAVE();
      }
    else
      {
	GnomeVFSURI *cache_uri;
	gboolean cache_exists;

	cache_uri = gnome_vfs_uri_append_file_name(backend->mailbox->vfs_uri, XMH_CACHE_FILE);
	cache_exists = mn_vfs_test(cache_uri, G_FILE_TEST_IS_REGULAR);
	gnome_vfs_uri_unref(cache_uri);

	if (! mn_reentrant_mailbox_check_aborted(MN_REENTRANT_MAILBOX(backend->mailbox), check_id))
	  {
	    GDK_THREADS_ENTER();

	    if (cache_exists)
	      mn_mailbox_set_messages(MN_MAILBOX(backend->mailbox), NULL);
	    else
	      mn_mailbox_set_error(MN_MAILBOX(backend->mailbox), _("unable to open %s: %s"), SEQUENCES_FILE, gnome_vfs_result_to_string(result));

	    gdk_flush();
	    GDK_THREADS_LEAVE();
	  }
      }
  }
}
