#include <gio/gio.h>
#include <gstdio.h>

typedef struct
{
  gchar *tmp_dir;
} Fixture;

static void
setup (Fixture       *fixture,
       gconstpointer  user_data)
{
  GError *error = NULL;

  fixture->tmp_dir = g_dir_make_tmp ("gio-test-file-monitor_XXXXXX", &error);
  g_assert_no_error (error);

  g_test_message ("Using temporary directory: %s", fixture->tmp_dir);
}

static void
teardown (Fixture       *fixture,
          gconstpointer  user_data)
{
  g_assert_cmpint (g_rmdir (fixture->tmp_dir), ==, 0);
  g_clear_pointer (&fixture->tmp_dir, g_free);
}

typedef struct {
  GFile *file;
  GOutputStream *stream;
  GMainLoop *loop;
  gint state;
} MonitorData;

static gboolean
create_file_idle (gpointer data)
{
  MonitorData *d = data;
  GError *error = NULL;

  g_assert (d->state == 0);

  d->stream = (GOutputStream*)g_file_create (d->file, 0, NULL, &error);
  g_assert_no_error (error);

  d->state = 1;

  return G_SOURCE_REMOVE;
}

static gboolean
write_file_idle (gpointer data)
{
  MonitorData *d = data;
  GError *error = NULL;

  g_assert (d->state == 2);

  g_output_stream_write (d->stream, "abcd", 4, NULL, &error);
  g_assert_no_error (error);
  g_object_unref (d->stream);
  d->stream = NULL;

  d->state = 3;


  return G_SOURCE_REMOVE;
}

static gboolean
delete_file_idle (gpointer data)
{
  MonitorData *d = data;
  GError *error = NULL;

  g_assert (d->state == 4);

  g_file_delete (d->file, NULL, &error);
  g_assert_no_error (error);

  d->state = 5;

  return G_SOURCE_REMOVE;
}

static gboolean
stop_loop_idle (gpointer data)
{
  MonitorData *d = data;

  g_assert (d->state == 6);

  if (d->loop)
    g_main_loop_quit (d->loop);

  return G_SOURCE_REMOVE;
}

static void
changed_cb (GFileMonitor      *monitor,
            GFile             *file,
            GFile             *other_file,
            GFileMonitorEvent  event,
            gpointer           data)
{
  MonitorData *d = data;

  switch (d->state)
    {
    case 1:
      g_assert (event == G_FILE_MONITOR_EVENT_CREATED);
      d->state = 2;
      g_idle_add (write_file_idle, data);
      break;
    case 3:
      g_assert (event == G_FILE_MONITOR_EVENT_CHANGED ||
                event == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT);
      if (event == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT)
        {
          d->state = 4;
          g_idle_add (delete_file_idle, data);
        }
      break;
    case 5:
      g_assert (event == G_FILE_MONITOR_EVENT_DELETED);
      d->state = 6;
      g_idle_add (stop_loop_idle, data);
      break;
    default:
      g_assert_not_reached ();
      break;
    }
}

static void
file_changed_cb (GFileMonitor      *monitor,
                 GFile             *file,
                 GFile             *other_file,
                 GFileMonitorEvent  event,
                 gpointer           data)
{
  gint *state = data;

  switch (*state)
    {
    case 0:
      g_assert (event == G_FILE_MONITOR_EVENT_CREATED);
      *state = 1;
      break;
    case 1:
      g_assert (event == G_FILE_MONITOR_EVENT_CHANGED ||
                event == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT);
      if (event == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT)
        *state = 2;
      break;
    case 2:
      g_assert (event == G_FILE_MONITOR_EVENT_DELETED);
      *state = 3;
      break;
    default:
      g_assert_not_reached ();
      break;
    }
}

static void
test_directory_monitor (Fixture       *fixture,
                        gconstpointer  user_data)
{
  GFile *file;
  GFile *child;
  GFileMonitor *dir_monitor;
  GFileMonitor *file_monitor;
  GError *error = NULL;
  MonitorData data;
  gint state;
  GMainLoop *loop;

  file = g_file_new_for_path (fixture->tmp_dir);
  dir_monitor = g_file_monitor_directory (file, 0, NULL, &error);
  g_assert_no_error (error);

  child = g_file_get_child (file, "test-file");
  file_monitor = g_file_monitor_file (child, 0, NULL, &error);
  g_assert_no_error (error);

  loop = g_main_loop_new (NULL, FALSE);

  g_signal_connect (dir_monitor, "changed", G_CALLBACK (changed_cb), &data);
  g_signal_connect (file_monitor, "changed", G_CALLBACK (file_changed_cb), &state);

  data.loop = loop;
  data.file = child;
  data.state = 0;
  state = 0;

  g_idle_add (create_file_idle, &data);

  g_main_loop_run (loop);

  g_assert_cmpint (data.state, ==, 6);
  g_assert_cmpint (state, ==, 3);

  g_main_loop_unref (loop);
  g_object_unref (dir_monitor);
  g_object_unref (file_monitor);
  g_object_unref (child);
  g_object_unref (file);
}

int
main (int argc, char *argv[])
{
  g_test_init (&argc, &argv, NULL);

  g_test_add ("/monitor/directory", Fixture, NULL, setup, test_directory_monitor, teardown);

  return g_test_run ();
}
