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

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

static gboolean
dir_monitor_callback (GFileMonitor *monitor,
		      GFile *file,
		      GFile *other_file,
		      GFileMonitorEvent event_type,
		      gpointer user_data)
{
    fprintf(stderr, "************ Got callback\n");
    return TRUE;
}


static void doselect(void)
{
    fprintf(stderr, "\n");

    GMainContext *context = g_main_context_default ();

    int have_wfds = 0;
    fd_set all_rfds, all_wfds;
    FD_ZERO(&all_rfds);
    FD_ZERO(&all_wfds);

#define Nmax 128
    GPollFD  gfds_buf[Nmax];
    GPollFD* gfds = gfds_buf;

    int tmo_in_millisec;
    int n_gfds = g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec,
                                       gfds, Nmax);
    assert(Nmax >= n_gfds);

    int max_fds = -1;

    fprintf(stderr, "glib has %d fds\n", n_gfds);
    for (int i = 0; i < n_gfds; ++i)
    {
        fprintf(stderr, " glib fd %d\n", gfds[i].fd);

        if (gfds[i].events & G_IO_IN)
        {
            fprintf(stderr, "   glib fd %d read\n", gfds[i].fd);
            FD_SET (gfds[i].fd, &all_rfds);
            if (gfds[i].fd > max_fds) max_fds = gfds[i].fd;
        }
        if (gfds[i].events & G_IO_OUT)
        {
            fprintf(stderr, "   glib fd %d write\n", gfds[i].fd);
            FD_SET (gfds[i].fd, &all_wfds);
            if (gfds[i].fd > max_fds) max_fds = gfds[i].fd;
            have_wfds = 1;
        }
    }


    if (tmo_in_millisec >= 0)
        fprintf(stderr, "glib says there's a timeout: %d ms\n", tmo_in_millisec);


    struct timespec timeout = {.tv_sec = 5};
    fprintf(stderr, "pselecting... ");
    int nfds = pselect (max_fds + 1, &all_rfds, have_wfds ? &all_wfds : NULL,
                        NULL, &timeout, NULL);
    fprintf(stderr, "pselected\n");

    if (nfds < 0)
    {
        fprintf(stderr, "pselect failed!\n");
        exit(1);
    }

    if (nfds == 0)
        fprintf(stderr, "pselect returned 0 handles\n");
    else
    {
        for (int i = 0; i <= max_fds; ++i)
        {
            if (FD_ISSET (i, &all_rfds))
                fprintf(stderr, "fd %d ready for reading\n", i);

            if (have_wfds && FD_ISSET (i, &all_wfds))
                fprintf(stderr, "fd %d ready for writing\n", i);
        }
    }

    fprintf(stderr, "dispatching.... ");
    while (g_main_context_pending (context))
        g_main_context_dispatch (context);
    fprintf(stderr, "dispatched\n");
}

void main(void)
{
    GFile* gfile = g_file_new_for_path("/tmp/dat");
    GFileMonitor* monitor = g_file_monitor (gfile, G_FILE_MONITOR_NONE, NULL, NULL);
    if (! monitor)
    {
        fprintf(stderr, "Error!\n");
        return;
    }

    g_signal_connect (monitor, "changed",
                      (GCallback) dir_monitor_callback, NULL);


#if 1
    while(1)
        doselect();
#else
    gtk_main();
#endif
}

