/*
 * Copyright © 2009 Codethink Limited
 *
 * This program 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 licence or (at
 * your option) any later version.
 *
 * See the included COPYING file for more information.
 *
 * Author: Ryan Lortie <desrt@desrt.ca>
 */

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

#define MAX_PIECE_SIZE  100
#define MAX_PIECES       60

static gchar *
cook_piece (void)
{
  char buffer[MAX_PIECE_SIZE * 2];
  gint symbols, i = 0;

  symbols = g_test_rand_int_range (1, MAX_PIECE_SIZE + 1);

  while (symbols--)
    {
      gint c = g_test_rand_int_range (0, 30);

      switch (c)
        {
         case 26:
          buffer[i++] = '\n';
         case 27:
          buffer[i++] = '\r';
          break;

         case 28:
          buffer[i++] = '\r';
         case 29:
          buffer[i++] = '\n';
          break;

         default:
          buffer[i++] = c + 'a';
          break;
        }

      g_assert_cmpint (i, <=, sizeof buffer);
    }

  return g_strndup (buffer, i);
}

static gchar **
cook_pieces (void)
{
  gchar **array;
  gint pieces;

  pieces = g_test_rand_int_range (0, MAX_PIECES + 1);
  array = g_new (char *, pieces + 1);
  array[pieces] = NULL;

  while (pieces--)
    array[pieces] = cook_piece ();

  return array;
}

typedef struct
{
  GInputStream parent_instance;

  gboolean built_to_fail;
  gchar **pieces;
  gint index;

  const gchar *current;
} SleepyStream;

typedef GInputStreamClass SleepyStreamClass;

GType sleepy_stream_get_type (void);

G_DEFINE_TYPE (SleepyStream, sleepy_stream, G_TYPE_INPUT_STREAM)

static gssize
sleepy_stream_read (GInputStream  *stream,
                    void          *buffer,
                    gsize          length,
                    GCancellable  *cancellable,
                    GError       **error)
{
  SleepyStream *sleepy = (SleepyStream *) stream;

  if (sleepy->pieces[sleepy->index] == NULL)
    {
      if (sleepy->built_to_fail)
        {
          g_set_error (error, 0, 0, "fail");
          return -1;
        }
      else
        return 0;
    }
  else
    {
      if (!sleepy->current)
        sleepy->current = sleepy->pieces[sleepy->index++];

      length = MIN (strlen (sleepy->current), length);
      memcpy (buffer, sleepy->current, length);

      sleepy->current += length;
      if (*sleepy->current == '\0')
        sleepy->current = NULL;

      return length;
    }
}

static void
sleepy_stream_init (SleepyStream *sleepy)
{
  sleepy->pieces = cook_pieces ();
  sleepy->built_to_fail = FALSE;
  sleepy->index = 0;
}

static void
sleepy_stream_finalize (GObject *object)
{
  SleepyStream *sleepy = (SleepyStream *) object;

  g_strfreev (sleepy->pieces);
  G_OBJECT_CLASS (sleepy_stream_parent_class)
    ->finalize (object);
}

static void
sleepy_stream_class_init (SleepyStreamClass *class)
{
  G_OBJECT_CLASS (class)->finalize = sleepy_stream_finalize;
  class->read_fn = sleepy_stream_read;

  /* no read_async implementation.
   * main thread will sleep while read runs in a worker.
   */
}

static SleepyStream *
sleepy_stream_new (void)
{
  return g_object_new (sleepy_stream_get_type (), NULL);
}

static gboolean
read_line (GDataInputStream  *stream,
           GString           *string,
           const gchar       *eol,
           GError           **error)
{
  gsize length;
  char *str;

  str = g_data_input_stream_read_line (stream, &length, NULL, error);

  if (str == NULL)
    return FALSE;

  g_assert (strstr (str, eol) == NULL);
  g_assert (strlen (str) == length);

  g_string_append (string, str);
  g_string_append (string, eol);
  g_free (str);

  return TRUE;
}

static void
build_comparison (GString      *str,
                  SleepyStream *stream)
{
  /* build this for comparison */
  gint i;

  for (i = 0; stream->pieces[i]; i++)
    g_string_append (str, stream->pieces[i]);

  if (str->len && str->str[str->len - 1] != '\n')
    g_string_append_c (str, '\n');
}


static void
test (void)
{
  SleepyStream *stream = sleepy_stream_new ();
  GDataInputStream *data;
  GError *error = NULL;
  GString *one;
  GString *two;

  one = g_string_new (NULL);
  two = g_string_new (NULL);

  data = g_data_input_stream_new (G_INPUT_STREAM (stream));
  g_data_input_stream_set_newline_type (data, G_DATA_STREAM_NEWLINE_TYPE_LF);
  build_comparison (one, stream);

  while (read_line (data, two, "\n", &error));

  g_assert_cmpstr (one->str, ==, two->str);
  g_string_free (one, TRUE);
  g_string_free (two, TRUE);
  g_object_unref (stream);
  g_object_unref (data);
}

static GDataInputStream *data;
static GString *one, *two;
static GMainLoop *loop;
static const gchar *eol;

static void
asynch_ready (GObject      *object,
              GAsyncResult *result,
              gpointer      user_data)
{
  GError *error = NULL;
  gsize length;
  gchar *str;

  g_assert (data == G_DATA_INPUT_STREAM (object));

  str = g_data_input_stream_read_line_finish (data, result, &length, &error);

  if (str == NULL)
    {
      g_main_loop_quit (loop);
      if (error)
        g_error_free (error);
    }
  else
    {
      g_assert (length == strlen (str));
      g_string_append (two, str);
      g_string_append (two, eol);
      g_free (str);

      /* MOAR!! */
      g_data_input_stream_read_line_async (data, 0, NULL, asynch_ready, NULL);
    }
}


static void
asynch (void)
{
  SleepyStream *sleepy = sleepy_stream_new ();

  data = g_data_input_stream_new (G_INPUT_STREAM (sleepy));
  one = g_string_new (NULL);
  two = g_string_new (NULL);
  eol = "\n";

  build_comparison (one, sleepy);
  g_data_input_stream_read_line_async (data, 0, NULL, asynch_ready, NULL);
  g_main_loop_run (loop = g_main_loop_new (NULL, FALSE));

  g_assert_cmpstr (one->str, ==, two->str);
  g_string_free (one, TRUE);
  g_string_free (two, TRUE);
  g_object_unref (sleepy);
  g_object_unref (data);
}

int
main (int argc, char **argv)
{
  g_test_init (&argc, &argv, NULL);
  g_test_bug_base ("http://bugzilla.gnome.org/");

  g_type_init ();
  g_test_add_func ("/filter-stream/input", test);
  g_test_add_func ("/filter-stream/async", asynch);

  return g_test_run();
}
