
#include <glib.h>
#include <gio/gio.h>
#include <fontconfig/fontconfig.h>

void fontconfig_monitor_start (GVoidFunc notify_callback);
void fontconfig_monitor_stop  (void);

#define TIMEOUT_SECONDS 1

static void
stuff_changed (GFileMonitor *monitor,
	       GFile *file,
	       GFile *other_file,
	       GFileMonitorEvent event_type,
	       gpointer notify_callback);

static GPtrArray *
monitor_files (GPtrArray *monitors,
	       FcStrList *list,
	       GVoidFunc  notify_callback)
{
  const char *str;

  while ((str = (const char *) FcStrListNext (list)))
    {
      GFile *file;
      GFileMonitor *monitor;

      if (g_file_test (str, G_FILE_TEST_IS_DIR))
        continue;

      file = g_file_new_for_path (str);
      g_message ("monitoring %s", str);

      monitor = g_file_monitor_file      (file, G_FILE_MONITOR_NONE, NULL, NULL);

      g_signal_connect (monitor, "changed", G_CALLBACK (stuff_changed), notify_callback);

      g_ptr_array_add (monitors, monitor);

      g_object_unref (file);
    }

  FcStrListDone (list);

  return monitors;
}

GPtrArray *monitors;

static void
setup_monitors (GVoidFunc notify_callback)
{
  if (!monitors)
    monitors = g_ptr_array_new ();

  monitor_files (monitors, FcConfigGetConfigFiles (NULL), notify_callback);
}

static void
remove_monitors (void)
{
  if (!monitors)
    return;

  g_ptr_array_foreach (monitors, (GFunc) g_object_unref, NULL);
  g_ptr_array_set_size (monitors, 0);
}

guint timeout;

static gboolean
update (gpointer data)
{
  GVoidFunc notify_callback = (GVoidFunc) data;

  remove_monitors ();

  if (FcInitReinitialize () && notify_callback)
    notify_callback ();

  setup_monitors (notify_callback);

  timeout = 0;
  return FALSE;
}

static void
stuff_changed (GFileMonitor *monitor G_GNUC_UNUSED,
	       GFile *file G_GNUC_UNUSED,
	       GFile *other_file G_GNUC_UNUSED,
	       GFileMonitorEvent event_type G_GNUC_UNUSED,
	       gpointer notify_callback)
{
  /* wait for quiescence */
  if (timeout)
    g_source_remove (timeout);
  
  timeout = g_timeout_add_seconds (TIMEOUT_SECONDS, update, notify_callback);
}


void
fontconfig_monitor_start (GVoidFunc notify_callback)
{
  setup_monitors (notify_callback);
}

void
fontconfig_monitor_stop (void)
{
  if (timeout)
    g_source_remove (timeout);
  timeout = 0;

  remove_monitors ();
  g_ptr_array_free (monitors, TRUE);
  monitors = NULL;
}

static void
yay (void)
{
  g_message ("change detected");
}

int
main (void)
{
  GMainLoop *loop;

  g_type_init ();

  fontconfig_monitor_start (yay);

  loop = g_main_loop_new (NULL, TRUE);
  g_main_loop_run (loop);

  return 0;
}
