#include <gst/gst.h>
#include <gst/base/gstadapter.h>

#define fail_unless(a) g_assert(a)


int main(int argc, char *argv[])
{
  GstAdapter *adapter = NULL;
  GstBuffer *buffer = NULL;
  guint avail;
  GstClockTime timestamp;
  guint64 dist = 0;

  /* Initialize GStreamer */
  gst_init (&argc, &argv);

  adapter = gst_adapter_new ();

  buffer = gst_buffer_new_and_alloc (100);

  /* push the buffer without timestamp in the adapter */
  gst_adapter_push (adapter, buffer);
  avail = gst_adapter_available (adapter);
  fail_unless (avail == 100);

  /* timestamp is now undefined */
  timestamp = gst_adapter_prev_pts_at_offset (adapter, 0, &dist);
  fail_unless (timestamp == GST_CLOCK_TIME_NONE);
  fail_unless (dist == 0);

  gst_adapter_flush (adapter, 50);
  avail = gst_adapter_available (adapter);
  fail_unless (avail == 50);

  /* still undefined, dist changed, though */
  timestamp = gst_adapter_prev_pts_at_offset (adapter, 0, &dist);
  fail_unless (timestamp == GST_CLOCK_TIME_NONE);
  fail_unless (dist == 50);

  /* Clearing to start a new test */
  gst_adapter_clear (adapter);

  /* alloc first buffer */
  buffer = gst_buffer_new_and_alloc (100);
  GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;

  /* push in the adapter */
  gst_adapter_push (adapter, buffer);
  avail = gst_adapter_available (adapter);
  fail_unless (avail == 100);

  /* alloc second buffer */
  buffer = gst_buffer_new_and_alloc (100);
  GST_BUFFER_TIMESTAMP (buffer) = 2 * GST_SECOND;

  /* push in the adapter */
  gst_adapter_push (adapter, buffer);
  avail = gst_adapter_available (adapter);
  fail_unless (avail == 200);

  /* alloc third buffer */
  buffer = gst_buffer_new_and_alloc (100);
  GST_BUFFER_TIMESTAMP (buffer) = 3 * GST_SECOND;

  /* push in the adapter */
  gst_adapter_push (adapter, buffer);
  avail = gst_adapter_available (adapter);
  fail_unless (avail == 300);

  /* alloc fourth buffer */
  buffer = gst_buffer_new_and_alloc (100);
  GST_BUFFER_TIMESTAMP (buffer) = 4 * GST_SECOND;

  /* push in the adapter */
  gst_adapter_push (adapter, buffer);
  avail = gst_adapter_available (adapter);
  fail_unless (avail == 400);

  timestamp = gst_adapter_prev_pts_at_offset (adapter, 0, &dist);
  fail_unless (timestamp == 1 * GST_SECOND);
  fail_unless (dist == 0);

  timestamp = gst_adapter_prev_pts_at_offset (adapter, 100, &dist);
  fail_unless (timestamp == 1 * GST_SECOND);
  fail_unless (dist == 100);

  timestamp = gst_adapter_prev_pts_at_offset (adapter, 200, &dist);
  fail_unless (timestamp == 2 * GST_SECOND);
  fail_unless (dist == 100);

  timestamp = gst_adapter_prev_pts_at_offset (adapter, 300, &dist);
  fail_unless (timestamp == 3 * GST_SECOND);
  fail_unless (dist == 100);

  timestamp = gst_adapter_prev_pts_at_offset (adapter, 400, &dist);
  fail_unless (timestamp == 4 * GST_SECOND);
  fail_unless (dist == 100);

  gst_adapter_flush (adapter, 50);
  avail = gst_adapter_available (adapter);
  fail_unless (avail == 350);

  /* We flushed 50 bytes, we are still on the first buffer */
  timestamp = gst_adapter_prev_pts_at_offset (adapter, 0, &dist);
  fail_unless (timestamp == 1 * GST_SECOND);
  fail_unless (dist == 50);

  /* As we flushed 50 bytes, offset 100 is on the second buffer */
  timestamp = gst_adapter_prev_pts_at_offset (adapter, 100, &dist);
  fail_unless (timestamp == 2 * GST_SECOND);
  fail_unless (dist == 50);

  /* Third buffer */
  timestamp = gst_adapter_prev_pts_at_offset (adapter, 200, &dist);
  fail_unless (timestamp == 3 * GST_SECOND);
  fail_unless (dist == 50);

  /* Fourth buffer */
  timestamp = gst_adapter_prev_pts_at_offset (adapter, 300, &dist);
  fail_unless (timestamp == 4 * GST_SECOND);
  fail_unless (dist == 50);


  gst_object_unref (adapter);

  return 0;
}
