/*
 * Copyright © 2015 Canonical Limited
 *
 * This library 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 of the License, or (at your option) any later version.
 *
 * This library 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 library; if not, see <http://www.gnu.org/licenses/>.
 *
 * Author: Ryan Lortie <desrt@desrt.ca>
 */

#include "config.h"

#include <gio/glocalfilemonitor.h>
#include <gio/giomodule.h>
#include "glib-private.h"
#include <glib-unix.h>
#include <fam.h>

static GMutex         fam_lock;
static gboolean       fam_initialised;
static FAMConnection  fam_connection;
static GSource       *fam_source;

#define G_TYPE_FAM_FILE_MONITOR      (g_fam_file_monitor_get_type ())
#define G_FAM_FILE_MONITOR(inst)     (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
                                      G_TYPE_FAM_FILE_MONITOR, GFamFileMonitor))

typedef GLocalFileMonitorClass GFamFileMonitorClass;

typedef struct
{
  GLocalFileMonitor parent_instance;

  FAMRequest request;
} GFamFileMonitor;

static GType g_fam_file_monitor_get_type (void);
G_DEFINE_DYNAMIC_TYPE (GFamFileMonitor, g_fam_file_monitor, G_TYPE_LOCAL_FILE_MONITOR)

static gboolean
g_fam_file_monitor_callback (gint         fd,
                             GIOCondition condition,
                             gpointer     user_data)
{
  gint64 now = g_source_get_time (fam_source);

  g_mutex_lock (&fam_lock);

  while (FAMPending (&fam_connection))
    {
      const gchar *child;
      FAMEvent ev;

      if (FAMNextEvent (&fam_connection, &ev) != 1)
        {
          /* The daemon died.  We're in a really bad situation now
           * because we potentially have a bunch of request structures
           * outstanding which no longer make any sense to anyone.
           *
           * The best thing that we can do is do nothing.  Notification
           * won't work anymore for this process.
           */
          g_mutex_unlock (&fam_lock);

          g_warning ("Lost connection to FAM (file monitoring) service.  Expect no further file monitor events.");

          return FALSE;
        }

      /* We expect ev.filename to be a relative path for children in a
       * monitored directory, and an absolute path for a monitored file
       * or the directory itself.
       */
      if (ev.filename[0] != '/')
        child = ev.filename;
      else
        child = NULL;

      switch (ev.code)
        {
        case FAMAcknowledge:
          g_source_unref (ev.userdata);
          break;

        case FAMChanged:
          g_file_monitor_source_handle_event (ev.userdata, G_FILE_MONITOR_EVENT_CHANGED, child, NULL, NULL, now);
          break;

        case FAMDeleted:
          g_file_monitor_source_handle_event (ev.userdata, G_FILE_MONITOR_EVENT_DELETED, child, NULL, NULL, now);
          break;

        case FAMCreated:
          g_file_monitor_source_handle_event (ev.userdata, G_FILE_MONITOR_EVENT_CREATED, child, NULL, NULL, now);
          break;

        default:
          /* unknown type */
          break;
        }
    }

  g_mutex_unlock (&fam_lock);

  return TRUE;
}

static gboolean
g_fam_file_monitor_is_supported (void)
{
  g_mutex_lock (&fam_lock);

  if (!fam_initialised)
    {
      fam_initialised = FAMOpen2 (&fam_connection, "GLib GIO") == 0;

      if (fam_initialised)
        {
#ifdef HAVE_FAM_NO_EXISTS
          /* This is a gamin extension that avoids sending all the
           * Exists event for dir monitors
           */
          FAMNoExists (&fam_connection);
#endif

          fam_source = g_unix_fd_source_new (FAMCONNECTION_GETFD (&fam_connection), G_IO_IN);
          g_source_set_callback (fam_source, (GSourceFunc) g_fam_file_monitor_callback, NULL, NULL);
          g_source_attach (fam_source, GLIB_PRIVATE_CALL(g_get_worker_context) ());
        }
    }

  g_mutex_unlock (&fam_lock);

  g_print ("II %d\n", fam_initialised);

  return fam_initialised;
}

static gboolean
g_fam_file_monitor_cancel (GFileMonitor *monitor)
{
  GFamFileMonitor *gffm = G_FAM_FILE_MONITOR (monitor);

  g_mutex_lock (&fam_lock);

  g_assert (fam_initialised);

  FAMCancelMonitor (&fam_connection, &gffm->request);

  g_mutex_unlock (&fam_lock);

  return TRUE;
}

static void
g_fam_file_monitor_start (GLocalFileMonitor  *local_monitor,
                          const gchar        *dirname,
                          const gchar        *basename,
                          const gchar        *filename,
                          GFileMonitorSource *source)
{
  GFamFileMonitor *gffm = G_FAM_FILE_MONITOR (local_monitor);

  g_mutex_lock (&fam_lock);

  g_assert (fam_initialised);

  g_source_ref ((GSource *) source);

  if (dirname)
    FAMMonitorDirectory (&fam_connection, dirname, &gffm->request, source);
  else
    FAMMonitorFile (&fam_connection, filename, &gffm->request, source);

  g_mutex_unlock (&fam_lock);
}

static void
g_fam_file_monitor_init (GFamFileMonitor* monitor)
{
}

static void
g_fam_file_monitor_class_init (GFamFileMonitorClass *class)
{
  GFileMonitorClass *file_monitor_class = G_FILE_MONITOR_CLASS (class);

  class->is_supported = g_fam_file_monitor_is_supported;
  class->start = g_fam_file_monitor_start;
  file_monitor_class->cancel = g_fam_file_monitor_cancel;
}

static void
g_fam_file_monitor_class_finalize (GFamFileMonitorClass *class)
{
}

void
g_io_module_load (GIOModule *module)
{
  g_type_module_use (G_TYPE_MODULE (module));

  g_fam_file_monitor_register_type (G_TYPE_MODULE (module));

  g_io_extension_point_implement (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME,
                                 G_TYPE_FAM_FILE_MONITOR, "fam", 10);

  g_io_extension_point_implement (G_NFS_FILE_MONITOR_EXTENSION_POINT_NAME,
                                 G_TYPE_FAM_FILE_MONITOR, "fam", 10);
}

void
g_io_module_unload (GIOModule *module)
{
  g_assert_not_reached ();
}

char **
g_io_module_query (void)
{
  char *eps[] = {
    G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME,
    G_NFS_FILE_MONITOR_EXTENSION_POINT_NAME,
    NULL
  };

  return g_strdupv (eps);
}
