/* gcc seek.c $(pkg-config --cflags --libs gio-2.0 glib-2.0) */

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

static void
test (const gchar *uri)
{
  GError *error;
  GFile *file = NULL;
  GFileInfo *info = NULL;
  GFileInputStream *stream = NULL;
  goffset pos;
  goffset size;
  gsize nread;
  guint8 buffer[4];

  g_message ("uri: %s", uri);
  file = g_file_new_for_uri (uri);

  error = NULL;
  info = g_file_query_info (file, "*", G_FILE_QUERY_INFO_NONE, NULL, &error);
  if (error != NULL)
    {
      g_warning ("g_file_query_info: %s", error->message);
      g_error_free (error);
      goto out;
    }

  size = g_file_info_get_size (info);
  g_message ("size: %" G_GOFFSET_FORMAT, size);

  error = NULL;
  stream = g_file_read (file, NULL, &error);
  if (error != NULL)
    {
      g_warning ("g_file_read: %s", error->message);
      g_error_free (error);
      goto out;
    }

  g_message ("can seek: %d", g_seekable_can_seek (G_SEEKABLE (stream)));

  pos = g_seekable_tell (G_SEEKABLE (stream));
  g_message ("tell: %" G_GOFFSET_FORMAT, pos);

  /* first pass */

  error = NULL;
  g_input_stream_read_all (G_INPUT_STREAM (stream),
                           buffer,
                           sizeof (buffer) / sizeof (buffer[0]),
                           &nread,
                           NULL,
                           &error);
  if (error != NULL)
    {
      g_warning ("g_input_stream_read_all: %s", error->message);
      g_error_free (error);
      goto out;
    }

  g_message ("nread: %" G_GSIZE_FORMAT, nread);
  g_message ("read bytes: %d, %d, %d, %d", (gint) buffer[0], (gint) buffer[1], (gint) buffer[2], (gint) buffer[3]);

  /* set position to 200 from the start */

  error = NULL;
  g_seekable_seek (G_SEEKABLE (stream), 200, G_SEEK_SET, NULL, &error);
  if (error != NULL)
    {
      g_warning ("g_seekable_seek: %s", error->message);
      g_error_free (error);
      goto out;
    }

  pos = g_seekable_tell (G_SEEKABLE (stream));
  g_message ("tell: %" G_GOFFSET_FORMAT, pos);

  /* second pass */

  error = NULL;
  g_input_stream_read_all (G_INPUT_STREAM (stream),
                           buffer,
                           sizeof (buffer) / sizeof (buffer[0]),
                           &nread,
                           NULL,
                           &error);
  if (error != NULL)
    {
      g_warning ("g_input_stream_read_all: %s", error->message);
      g_error_free (error);
      goto out;
    }

  g_message ("nread: %" G_GSIZE_FORMAT, nread);
  g_message ("read bytes: %d, %d, %d, %d", (gint) buffer[0], (gint) buffer[1], (gint) buffer[2], (gint) buffer[3]);

  /* set position to -100 from the end */

  error = NULL;
  g_seekable_seek (G_SEEKABLE (stream), -100, G_SEEK_END, NULL, &error);
  if (error != NULL)
    {
      g_warning ("g_seekable_seek: %s", error->message);
      g_error_free (error);
      goto out;
    }

  pos = g_seekable_tell (G_SEEKABLE (stream));
  g_message ("tell: %" G_GOFFSET_FORMAT, pos);

  /* third pass */

  error = NULL;
  g_input_stream_read_all (G_INPUT_STREAM (stream),
                           buffer,
                           sizeof (buffer) / sizeof (buffer[0]),
                           &nread,
                           NULL,
                           &error);
  if (error != NULL)
    {
      g_warning ("g_input_stream_read_all: %s", error->message);
      g_error_free (error);
      goto out;
    }

  g_message ("nread: %" G_GSIZE_FORMAT, nread);
  g_message ("read bytes: %d, %d, %d, %d", (gint) buffer[0], (gint) buffer[1], (gint) buffer[2], (gint) buffer[3]);

 out:
  g_message ("--");
  g_clear_object (&stream);
  g_clear_object (&info);
  g_clear_object (&file);
}

gint
main (gint argc, gchar ** argv)
{
  test ("file:///home/rishi/Documents/flock-2014-accommodation.odt");
  test ("davs://rishi@cloud.gnome.org/remote.php/webdav/flock-2014-accommodation.odt");
  test ("google-drive://debarshi.ray@gmail.com/0B9J_DkaiBDRFajM2NmJiWHBrclU/flock-2014-accommodation.odt");
  return 0;
}
