/*
 * Copyright (C) 2010 Ole André Vadla Ravnås <oleavr@soundrop.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "coremediactx.h"

#include <gst/gst.h>

typedef struct _GstApiProvider GstApiProvider;

typedef gpointer (*GstApiProviderObtainFunc) (GError ** error);

struct _GstApiProvider
{
  GstCoreMediaApi api;
  GstApiProviderObtainFunc obtain;
  guint offset;
};

#define API_PROVIDER(AN, a_n) \
  { GST_API_##AN, (GstApiProviderObtainFunc) gst_##a_n##_api_obtain, \
    G_STRUCT_OFFSET (GstCoreMediaCtx, a_n) }

static const GstApiProvider api_provider[] = {
  API_PROVIDER (CORE_VIDEO, cv),
  API_PROVIDER (CORE_MEDIA, cm),
#ifdef HAVE_IOS
#if 0
  API_PROVIDER (MEDIA_TOOLBOX, mt),
  API_PROVIDER (CELESTIAL, cel)
#endif
#else
  API_PROVIDER (MIO, mio),
#endif
};

G_DEFINE_TYPE (GstCoreMediaCtx, gst_core_media_ctx, G_TYPE_OBJECT);

static void
gst_core_media_ctx_init (GstCoreMediaCtx * self)
{
}

static void
gst_core_media_ctx_dispose (GObject * object)
{
  GstCoreMediaCtx *self = GST_CORE_MEDIA_CTX_CAST (object);
  guint i;

  for (i = 0; i != G_N_ELEMENTS (api_provider); i++) {
    const GstApiProvider *ap = &api_provider[i];
    gpointer *api_ptr = (gpointer *) ((guint8 *) self + ap->offset);

    if (*api_ptr != NULL) {
      g_object_unref (*api_ptr);
      *api_ptr = NULL;
    }
  }

  G_OBJECT_CLASS (gst_core_media_ctx_parent_class)->dispose (object);
}

static void
gst_core_media_ctx_class_init (GstCoreMediaCtxClass * klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);

  gobject_class->dispose = gst_core_media_ctx_dispose;
}

GstCoreMediaCtx *
gst_core_media_ctx_new (GstCoreMediaApi required_apis, GError ** error)
{
  GstCoreMediaCtx *ctx;
  GArray *error_messages;
  guint i;

  ctx = g_object_new (GST_TYPE_CORE_MEDIA_CTX, NULL);

  error_messages = g_array_new (TRUE, FALSE, sizeof (gchar *));

  for (i = 0; i != G_N_ELEMENTS (api_provider); i++) {
    const GstApiProvider *ap = &api_provider[i];

    if ((required_apis & ap->api) != 0) {
      gpointer *api_ptr = (gpointer *) ((guint8 *) ctx + ap->offset);
      GError *tmp_error = NULL;

      *api_ptr = ap->obtain (&tmp_error);
      if (tmp_error != NULL) {
        gchar *message_copy = g_strdup (tmp_error->message);
        g_array_append_val (error_messages, message_copy);
        g_clear_error (&tmp_error);
      }
    }
  }

  if (error_messages->len != 0) {
    gchar *errors_joined;

    errors_joined = g_strjoinv ("\n\t* ", (gchar **) error_messages->data);
    g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_FAILED,
        "Could not obtain required API%s:%s%s",
        (error_messages->len == 1) ? "" : "s",
        (error_messages->len == 1) ? " " : "\n\t* ", errors_joined);
    g_free (errors_joined);

    g_object_unref (ctx);
    ctx = NULL;
  }

  for (i = 0; i != error_messages->len; i++)
    g_free (g_array_index (error_messages, gchar *, i));
  g_array_free (error_messages, TRUE);

  return ctx;
}
