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

#include <glib.h>

#include <libgnomevfs/gnome-vfs-monitor.h>
#include <libgnomevfs/gnome-vfs-ops.h>

#include "eggfilemonitor.h"

#define TEST_URI	"file:///tmp/test.txt"

static gboolean
file_monitor_cb (const gchar  *uri,
		 EggFileEvent  event,
		 gpointer      user_data)
{
  switch (event)
    {
    case EGG_FILE_CREATED_EVENT:
      g_print ("File '%s' has been created\n", uri);
      break;
    case EGG_FILE_CHANGED_EVENT:
      g_print ("File '%s' has been changed\n", uri);
      break;
    case EGG_FILE_REMOVED_EVENT:
      g_print ("File '%s' has been removed\n", uri);
      break;
    default:
      g_print ("Unknown event id %d\n", event);
      return FALSE;
    }
  
  return TRUE;
}

typedef struct _FMData
{
  GnomeVFSMonitorHandle *handle;

  guint uri_changed : 1;
  GnomeVFSMonitorEventType last_event;
} FMData;

static void
fm_monitor_cb (GnomeVFSMonitorHandle    *gnome_handle,
	       const gchar              *monitor_uri,
	       const char               *info_uri,
	       GnomeVFSMonitorEventType  event_type,
	       gpointer                  user_data)
{
  FMData *fm_data = user_data;

  g_print ("(in %s) event %d\n", G_STRFUNC, event_type);

  fm_data->uri_changed = TRUE;
  fm_data->last_event = event_type;
}

static gboolean
fm_add_monitor (const gchar *uri,
		gpointer     user_data)
{
  FMData *fm_data = user_data;
  GnomeVFSResult res;

  g_print ("(in %s) adding monitor for %s\n", G_STRFUNC, uri);
  
  res = gnome_vfs_monitor_add (&(fm_data->handle),
		  	       uri,
			       GNOME_VFS_MONITOR_FILE,
			       fm_monitor_cb,
			       fm_data);

  return (res == GNOME_VFS_OK);
}

static gboolean
fm_cancel_monitor (const gchar *uri,
		   gpointer     user_data)
{
  FMData *fm_data = user_data;
  GnomeVFSResult res;

  g_print ("(in %s) removing the monitor on %s\n",
           G_STRFUNC,
	   uri);

  res = gnome_vfs_monitor_cancel (fm_data->handle);

  return (res == GNOME_VFS_OK);
}

static gboolean
fm_check_uri (const gchar  *uri,
	      EggFileEvent *event,
	      gpointer      user_data)
{
  FMData *fm_data = user_data;

  if (fm_data->uri_changed)
    {
      switch (fm_data->last_event)
        {
        case GNOME_VFS_MONITOR_EVENT_CREATED:
          *event = EGG_FILE_CREATED_EVENT;
	  break;
	case GNOME_VFS_MONITOR_EVENT_CHANGED:
	case GNOME_VFS_MONITOR_EVENT_METADATA_CHANGED:
	  *event = EGG_FILE_CHANGED_EVENT;
	  break;
	case GNOME_VFS_MONITOR_EVENT_DELETED:
	  *event = EGG_FILE_REMOVED_EVENT;
	  break;
	default:
	  *event = -1;
	  break;
	}

      /* reset the guard */
      fm_data->uri_changed = FALSE;
      fm_data->last_event = -1;

      return TRUE;
    }

  *event = -1;
  
  return FALSE;
}

static void
fm_error (const gchar  *uri,
	  const GError *error,
	  gpointer      user_data)
{
  g_warning ("Error while monitoring %s: %s",
	     uri,
	     error->message);
}

static EggFileMonitorHooks file_monitor_hooks =
{
  fm_add_monitor,
  fm_cancel_monitor,
  fm_check_uri,
  fm_error
};

int main (int argc, char *argv[])
{
  FMData *data;
  GMainLoop *main_loop;
  guint id;

  gnome_vfs_init ();
  
  main_loop = g_main_loop_new (NULL, FALSE);

  data = g_new0 (FMData, 1);
  egg_set_file_monitor_hooks (&file_monitor_hooks, data);
  
  id = egg_file_monitor_add (TEST_URI, file_monitor_cb, NULL);
  
  g_main_loop_run (main_loop);

  g_source_remove (id);
  g_free (data);

  gnome_vfs_shutdown ();
  
  return 0;
}
