/*
 * test-plugin-pushsrc.cc
 *
 *  Created on: Aug 1, 2013
 *      Author: m.kolny
 */

#include <gtest/gtest.h>
#include <gstreamermm.h>
#include <string>
#include <gstreamermm/appsink.h>
#include <gstreamermm/private/pushsrc_p.h>

using namespace Gst;
using Glib::RefPtr;

class FooSrc : public Gst::PushSrc
{
  int count_left;

public:
    static const int COUNT = 5;
    static void base_init(Gst::ElementClass<FooSrc> *klass)
    {
        klass->set_metadata("foosrc_longname",
                "foosrc_classification", "foosrc_detail_description", "foosrc_detail_author");

        klass->add_pad_template(Gst::PadTemplate::create("src", Gst::PAD_SRC, Gst::PAD_ALWAYS,
                                                     Gst::Caps::create_from_string("x-application/x-foo1")));
    }

    explicit FooSrc(GstPushSrc *gobj)
        : Gst::PushSrc(gobj),
          count_left(COUNT)
    {
        set_format(Gst::FORMAT_TIME);
    }

    Gst::FlowReturn create_vfunc(guint64 /* offset */, guint /* size */, Glib::RefPtr<Gst::Buffer>& buffer)
    {
        if (count_left-- <= 0)
            return Gst::FLOW_EOS;

        std::string s = std::to_string(COUNT - count_left);
        buffer = Gst::Buffer::create(s.size());

        RefPtr<MapInfo> info(new MapInfo());
        buffer->map(info, MAP_WRITE);

        std::copy(s.begin(), s.end(), info->get_data());
        return Gst::FLOW_OK;
    }

    virtual bool negotiate_vfunc()
    {
        return true;
    }
    virtual bool start_vfunc()
    {
        count_left = COUNT;
        return true;
    }
};

bool register_foo(Glib::RefPtr<Gst::Plugin> plugin)
{
    Gst::ElementFactory::register_element(plugin, "foosrcmm", 10, Gst::register_mm_type<FooSrc>("foosrcmm"));
    return true;

}

class PushSrcPluginTest : public ::testing::Test
{
protected:
    virtual void SetUp()
    {
        Plugin::register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR, "foo",
              "foo is example of C++ element", sigc::ptr_fun(register_foo), "0.123",
              "LGPL", "source?", "package?", "http://example.com");
    }

    RefPtr<Pipeline> CreatePipeline()
    {
        RefPtr<Pipeline> pipeline = Pipeline::create("my-pipeline");

        EXPECT_TRUE(pipeline);

        RefPtr<Element> source = ElementFactory::create_element("foosrcmm", "src");
        RefPtr<AppSink> sink = AppSink::create("sink");

        EXPECT_TRUE(source);
        EXPECT_TRUE(sink);

        pipeline->add(source)->add(sink);
        source->link(sink);

        return pipeline;
    }
};

TEST_F(PushSrcPluginTest, CreateRegisteredElement)
{
    Glib::RefPtr<Gst::Element> source = Gst::ElementFactory::create_element("foosrcmm", "src");

    ASSERT_TRUE(source);
}

TEST_F(PushSrcPluginTest, DISABLED_CreatePipelineWithRegisteredElement)
{
    CreatePipeline();
}
