/*
 * Copyright (C) 2013 Cable Television Laboratories, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "TextCombinerGStreamer.h"

#if ENABLE(VIDEO) && USE(GSTREAMER)

#include "GStreamerCommon.h"

static GstStaticPadTemplate sinkTemplate =
    GST_STATIC_PAD_TEMPLATE("sink_%u", GST_PAD_SINK, GST_PAD_REQUEST,
        GST_STATIC_CAPS_ANY);

static GstStaticPadTemplate srcTemplate =
    GST_STATIC_PAD_TEMPLATE("src", GST_PAD_SRC, GST_PAD_ALWAYS,
        GST_STATIC_CAPS_ANY);

GST_DEBUG_CATEGORY_STATIC(webkitTextCombinerDebug);
#define GST_CAT_DEFAULT webkitTextCombinerDebug

#define webkit_text_combiner_parent_class parent_class
G_DEFINE_TYPE_WITH_CODE(WebKitTextCombiner, webkit_text_combiner, GST_TYPE_BIN,
    GST_DEBUG_CATEGORY_INIT(webkitTextCombinerDebug, "webkittextcombiner", 0,
        "webkit text combiner"));

enum {
    PROP_PAD_0,
    PROP_PAD_TAGS
};

#define WEBKIT_TYPE_TEXT_COMBINER_PAD webkit_text_combiner_pad_get_type()

#define WEBKIT_TEXT_COMBINER_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_TEXT_COMBINER_PAD, WebKitTextCombinerPad))
#define WEBKIT_TEXT_COMBINER_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_TEXT_COMBINER_PAD, WebKitTextCombinerPadClass))
#define WEBKIT_IS_TEXT_COMBINER_PAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_TEXT_COMBINER_PAD))
#define WEBKIT_IS_TEXT_COMBINER_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_TEXT_COMBINER_PAD))
#define WEBKIT_TEXT_COMBINER_PAD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_TEXT_COMBINER_PAD, WebKitTextCombinerPadClass))

typedef struct _WebKitTextCombinerPad WebKitTextCombinerPad;
typedef struct _WebKitTextCombinerPadClass WebKitTextCombinerPadClass;

struct _WebKitTextCombinerPad {
    GstGhostPad parent;

    GstTagList* tags;
    GstPad* funnelPad;
};

struct _WebKitTextCombinerPadClass {
    GstGhostPadClass parent;
};

G_DEFINE_TYPE(WebKitTextCombinerPad, webkit_text_combiner_pad, GST_TYPE_GHOST_PAD);

static GType webVTTEncType;

static gboolean webkitTextCombinerPadEvent(GstPad*, GstObject* parent, GstEvent*);

static void webkit_text_combiner_init(WebKitTextCombiner* combiner)
{
    combiner->funnel = gst_element_factory_make("funnel", nullptr);
    ASSERT(combiner->funnel);

    gboolean ret = gst_bin_add(GST_BIN(combiner), combiner->funnel);
    UNUSED_PARAM(ret);
    ASSERT(ret);

    GRefPtr<GstPad> pad = adoptGRef(gst_element_get_static_pad(combiner->funnel, "src"));
    ASSERT(pad);

    ret = gst_element_add_pad(GST_ELEMENT(combiner), gst_ghost_pad_new("src", pad.get()));
    ASSERT(ret);
}

static void webkit_text_combiner_pad_init(WebKitTextCombinerPad* pad)
{
    gst_pad_set_event_function(GST_PAD(pad), webkitTextCombinerPadEvent);
}

static void webkitTextCombinerPadDispose(GObject* object)
{
    WebKitTextCombinerPad* combinerPad = WEBKIT_TEXT_COMBINER_PAD(object);
    g_clear_pointer(&combinerPad->tags, gst_tag_list_unref);
    g_clear_pointer(&combinerPad->funnelPad, gst_object_unref);
    G_OBJECT_CLASS(webkit_text_combiner_pad_parent_class)->dispose(object);
}

static void webkitTextCombinerPadGetProperty(GObject* object, guint propertyId, GValue* value, GParamSpec* pspec)
{
    WebKitTextCombinerPad* pad = WEBKIT_TEXT_COMBINER_PAD(object);
    switch (propertyId) {
    case PROP_PAD_TAGS:
        GST_OBJECT_LOCK(object);
        if (pad->tags)
            g_value_take_boxed(value, gst_tag_list_copy(pad->tags));
        GST_OBJECT_UNLOCK(object);
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyId, pspec);
        break;
    }
}

static gboolean webkitTextCombinerPadEvent(GstPad* pad, GstObject* parent, GstEvent* event)
{
    gboolean ret;
    UNUSED_PARAM(ret);
    WebKitTextCombiner* combiner = WEBKIT_TEXT_COMBINER(parent);
    WebKitTextCombinerPad* combinerPad = WEBKIT_TEXT_COMBINER_PAD(pad);
    ASSERT(combiner);

    switch (GST_EVENT_TYPE(event)) {
    case GST_EVENT_CAPS: {
        GstCaps* caps;
        gst_event_parse_caps(event, &caps);
        ASSERT(caps);

        GRefPtr<GstPad> target = adoptGRef(gst_ghost_pad_get_target(GST_GHOST_PAD(pad)));
        GRefPtr<GstElement> targetParent = target ? adoptGRef(gst_pad_get_parent_element(target.get())) : nullptr;

        GRefPtr<GstCaps> textCaps = adoptGRef(gst_caps_new_empty_simple("text/x-raw"));
        if (gst_caps_can_intersect(textCaps.get(), caps)) {
            // Caps are plain text, we want a WebVTT encoder between the ghostpad and the funnel.
            if (!target || G_TYPE_FROM_INSTANCE(targetParent.get()) != webVTTEncType) {
                // Setup a WebVTT encoder.
                GstElement* encoder = gst_element_factory_make("webvttenc", nullptr);
                ASSERT(encoder);

                ret = gst_bin_add(GST_BIN(combiner), encoder);
                ASSERT(ret);

                ret = gst_element_sync_state_with_parent(encoder);
                ASSERT(ret);

                // Switch the ghostpad to target the WebVTT encoder.
                GRefPtr<GstPad> sinkPad = adoptGRef(gst_element_get_static_pad(encoder, "sink"));
                ASSERT(sinkPad);

                ret = gst_ghost_pad_set_target(GST_GHOST_PAD(pad), sinkPad.get());
                ASSERT(ret);

                // Connect the WebVTT encoder to the funnel.
                GRefPtr<GstPad> srcPad = adoptGRef(gst_element_get_static_pad(encoder, "src"));
                ASSERT(srcPad);

                ret = GST_PAD_LINK_SUCCESSFUL(gst_pad_link(srcPad.get(), combinerPad->funnelPad));
                ASSERT(ret);
            } // Else: pipeline is already correct.
        } else {
            // Caps are not plain text, we assume it's WebVTT.

            // Remove the WebVTT encoder if present.
            if (target && G_TYPE_FROM_INSTANCE(targetParent.get()) == webVTTEncType) {
                ret = gst_bin_remove(GST_BIN(combiner), targetParent.get());
                ASSERT(ret);

                target = nullptr;
                targetParent = nullptr;
            }

            // Link the pad to the funnel.
            if (!target) {
                ret = gst_ghost_pad_set_target(GST_GHOST_PAD(pad), combinerPad->funnelPad);
                ASSERT(ret);
            } // Else: pipeline is already correct.
        }
        break;
    }
    case GST_EVENT_TAG: {
        GstTagList* tags;
        gst_event_parse_tag(event, &tags);
        ASSERT(tags);

        GST_OBJECT_LOCK(pad);
        if (!combinerPad->tags)
            combinerPad->tags = gst_tag_list_copy(tags);
        else
            gst_tag_list_insert(combinerPad->tags, tags, GST_TAG_MERGE_REPLACE);
        GST_OBJECT_UNLOCK(pad);

        g_object_notify(G_OBJECT(pad), "tags");
        break;
    }
    default:
        break;
    }
    return gst_pad_event_default(pad, parent, event);
}

static GstPad* webkitTextCombinerRequestNewPad(GstElement * element,
    GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
{
    gboolean ret;
    UNUSED_PARAM(ret);
    ASSERT(templ);

    WebKitTextCombiner* combiner = WEBKIT_TEXT_COMBINER(element);
    ASSERT(combiner);

    GstPad* ghostPad = GST_PAD(g_object_new(WEBKIT_TYPE_TEXT_COMBINER_PAD, "direction", GST_PAD_SINK, nullptr));
    ASSERT(ghostPad);

    ret = gst_ghost_pad_construct(GST_GHOST_PAD(ghostPad));
    ASSERT(ret);

    WebKitTextCombinerPad* combinerPad = WEBKIT_TEXT_COMBINER_PAD(ghostPad);
    combinerPad->funnelPad = gst_element_request_pad(combiner->funnel, templ, name, caps);
    ASSERT(combinerPad->funnelPad);

    ret = gst_pad_set_active(ghostPad, true);
    ASSERT(ret);

    ret = gst_element_add_pad(GST_ELEMENT(combiner), ghostPad);
    ASSERT(ret);
    return ghostPad;
}

static void webkitTextCombinerReleasePad(GstElement *element, GstPad *pad)
{
    WebKitTextCombiner* combiner = WEBKIT_TEXT_COMBINER(element);
    WebKitTextCombinerPad* combinerPad = WEBKIT_TEXT_COMBINER_PAD(pad);

    if (GRefPtr<GstPad> target = adoptGRef(gst_ghost_pad_get_target(GST_GHOST_PAD(pad)))) {
        GRefPtr<GstElement> parent = adoptGRef(gst_pad_get_parent_element(target.get()));
        ASSERT(parent);
        if (G_TYPE_FROM_INSTANCE(parent.get()) == webVTTEncType) {
            gst_element_set_state(parent.get(), GST_STATE_NULL);
            gst_bin_remove(GST_BIN(combiner), parent.get());
        }
    }

    gst_element_release_request_pad(combiner->funnel, combinerPad->funnelPad);
    gst_element_remove_pad(element, pad);
}

static void webkit_text_combiner_class_init(WebKitTextCombinerClass* klass)
{
    GstElementClass* elementClass = GST_ELEMENT_CLASS(klass);

    gst_element_class_add_pad_template(elementClass, gst_static_pad_template_get(&sinkTemplate));
    gst_element_class_add_pad_template(elementClass, gst_static_pad_template_get(&srcTemplate));

    gst_element_class_set_metadata(elementClass, "WebKit text combiner", "Generic",
        "A funnel that accepts any caps, but converts plain text to WebVTT",
        "Brendan Long <b.long@cablelabs.com>");

    elementClass->request_new_pad =
        GST_DEBUG_FUNCPTR(webkitTextCombinerRequestNewPad);
    elementClass->release_pad =
        GST_DEBUG_FUNCPTR(webkitTextCombinerReleasePad);

    GRefPtr<GstElementFactory> webVTTEncFactory = adoptGRef(gst_element_factory_find("webvttenc"));
    ASSERT(webVTTEncFactory);
    gst_object_unref(gst_plugin_feature_load(GST_PLUGIN_FEATURE(webVTTEncFactory.get())));
    webVTTEncType = gst_element_factory_get_element_type(webVTTEncFactory.get());
    ASSERT(webVTTEncType);
}

static void webkit_text_combiner_pad_class_init(WebKitTextCombinerPadClass* klass)
{
    GObjectClass* gobjectClass = G_OBJECT_CLASS(klass);

    gobjectClass->dispose = GST_DEBUG_FUNCPTR(webkitTextCombinerPadDispose);
    gobjectClass->get_property = GST_DEBUG_FUNCPTR(webkitTextCombinerPadGetProperty);

    g_object_class_install_property(gobjectClass, PROP_PAD_TAGS,
        g_param_spec_boxed("tags", "Tags", "The currently active tags on the pad", GST_TYPE_TAG_LIST,
            static_cast<GParamFlags>(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
}

GstElement* webkitTextCombinerNew()
{
    // The combiner relies on webvttenc, fail early if it's not there.
    if (!WebCore::isGStreamerPluginAvailable("subenc")) {
        WTFLogAlways("WebKit wasn't able to find a WebVTT encoder. Not continuing without platform support for subtitles.");
        return nullptr;
    }

    return GST_ELEMENT(g_object_new(WEBKIT_TYPE_TEXT_COMBINER, nullptr));
}

#endif // ENABLE(VIDEO) && USE(GSTREAMER)
