/*
 * 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.h"
%}

%{
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include "mn-mailbox-private.h"
#include "mn-reentrant-mailbox-private.h"
#include "mn-vfs-mailbox-private.h"
#include "mn-conf.h"
#include "mn-util.h"
%}

class MN:VFS:Mailbox:Backend from G:Object (abstract)
{
  classwide const char *format;

  /*
   * In order to not create reference cycles, we do not hold a
   * reference to the mailbox. The code is arranged so that a VFS
   * backend cannot survive its containing mailbox (no reference to
   * the backend is held outside of the mailbox code).
   */
  protected MNVFSMailbox *mailbox;
  property POINTER mailbox (link, flags = CONSTRUCT_ONLY, type = MNVFSMailbox *);

  private unsigned int queue_check_id;

  /*
   * The amount of time to wait between a queue_check() call and the
   * actual mailbox check, in milliseconds. If 0, the check is
   * performed immediately. Used to avoid race conditions with mailbox
   * formats which do not support locking.
   */
  protected int check_latency;

  finalize (self)
  {
    if (selfp->queue_check_id)
      g_source_remove(selfp->queue_check_id);

    /*
     * If the calling mailbox is being finalized, there is no need to
     * hold its lock. Otherwise, it holds its lock while finalizing us
     * (see reentrant_check() in mn-vfs-mailbox.gob).
     */
    mn_vfs_mailbox_remove_monitors_by_owner(self->mailbox, self);
  }

  protected void
    monitor (self,
	     int check_id,
	     const char *uri (check null),
	     GnomeVFSMonitorType type)
  {
    mn_vfs_mailbox_lock(self->mailbox);
    mn_vfs_mailbox_monitor(self->mailbox, uri, self, type, self_real_monitor_cb, self);
    mn_vfs_mailbox_unlock(self->mailbox);
  }

  private void
    real_monitor_cb (GnomeVFSMonitorHandle *handle,
		     const char *monitor_uri,
		     const char *info_uri,
		     GnomeVFSMonitorEventType event_type,
		     gpointer user_data)
  {
    self_monitor_cb(user_data, info_uri, event_type);
  }

  virtual private void
    monitor_cb (self,
		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)
      self_queue_check(self);
  }

  /**
   * queue_check():
   * @self: a backend
   *
   * Queues a mail check on the mailbox of @self or replaces an
   * already queued check. The check_latency member is respected.
   *
   * This function is not thread-safe. It is only called from main
   * loop callbacks (hence always from the same thread).
   **/
  protected void
    queue_check (self)
  {
    if (selfp->queue_check_id)
      mn_source_clear(&selfp->queue_check_id);

    if (self->check_latency)
      selfp->queue_check_id = gdk_threads_add_timeout(self->check_latency, self_queue_check_cb, self);
    else
      mn_reentrant_mailbox_queue_check(MN_REENTRANT_MAILBOX(self->mailbox));
  }

  private gboolean
    queue_check_cb (gpointer data)
  {
    Self *self = data;

    mn_mailbox_check(MN_MAILBOX(self->mailbox));

    selfp->queue_check_id = 0;
    return FALSE;		/* remove source */
  }

  virtual public gboolean
    is (self, MNVFSMailboxBackendClass *class, MN:VFS:Mailbox *mailbox);

  virtual public void
    check (self, int check_id (check != 0));
}
