/*
 * 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, G_IO_ERROR, G_IO_ERROR_FAILED, "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_test_add_func ("/filter-stream/input", test);
  g_test_add_func ("/filter-stream/async", asynch);

  return g_test_run();
}
