/*
 * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
 *
 * 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 APPLE INC. ``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
 * 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 "MockSourceBufferPrivate.h"

#if ENABLE(MEDIA_SOURCE)

#include "MediaDescription.h"
#include "MediaPlayer.h"
#include "MediaSample.h"
#include "MockBox.h"
#include "MockMediaPlayerMediaSource.h"
#include "MockMediaSourcePrivate.h"
#include "MockTracks.h"
#include "SourceBufferPrivateClient.h"
#include <JavaScriptCore/ArrayBuffer.h>
#include <wtf/StringPrintStream.h>

namespace WebCore {

class MockMediaSample final : public MediaSample {
public:
    static Ref<MockMediaSample> create(const MockSampleBox& box) { return adoptRef(*new MockMediaSample(box)); }
    virtual ~MockMediaSample() = default;

private:
    MockMediaSample(const MockSampleBox& box)
        : m_box(box)
        , m_id(String::format("%d", box.trackID()))
    {
    }

    MediaTime presentationTime() const override { return m_box.presentationTimestamp(); }
    MediaTime decodeTime() const override { return m_box.decodeTimestamp(); }
    MediaTime duration() const override { return m_box.duration(); }
    AtomicString trackID() const override { return m_id; }
    void setTrackID(const String& id) override { m_id = id; }
    size_t sizeInBytes() const override { return sizeof(m_box); }
    SampleFlags flags() const override;
    PlatformSample platformSample() override;
    FloatSize presentationSize() const override { return FloatSize(); }
    void dump(PrintStream&) const override;
    void offsetTimestampsBy(const MediaTime& offset) override { m_box.offsetTimestampsBy(offset); }
    void setTimestamps(const MediaTime& presentationTimestamp, const MediaTime& decodeTimestamp) override { m_box.setTimestamps(presentationTimestamp, decodeTimestamp); }
    bool isDivisable() const override { return false; }
    std::pair<RefPtr<MediaSample>, RefPtr<MediaSample>> divide(const MediaTime&) override { return {nullptr, nullptr}; }
    Ref<MediaSample> createNonDisplayingCopy() const override;

    unsigned generation() const { return m_box.generation(); }

    MockSampleBox m_box;
    AtomicString m_id;
};

MediaSample::SampleFlags MockMediaSample::flags() const
{
    unsigned flags = None;
    if (m_box.isSync())
        flags |= IsSync;
    if (m_box.isNonDisplaying())
        flags |= IsNonDisplaying;
    return SampleFlags(flags);
}

PlatformSample MockMediaSample::platformSample()
{
    PlatformSample sample = { PlatformSample::MockSampleBoxType, { &m_box } };
    return sample;
}

void MockMediaSample::dump(PrintStream& out) const
{
    out.print("{PTS(", presentationTime(), "), DTS(", decodeTime(), "), duration(", duration(), "), flags(", (int)flags(), "), generation(", generation(), ")}");
}

Ref<MediaSample> MockMediaSample::createNonDisplayingCopy() const
{
    auto copy = MockMediaSample::create(m_box);
    copy->m_box.setFlag(MockSampleBox::IsNonDisplaying);
    return WTFMove(copy);
}

class MockMediaDescription final : public MediaDescription {
public:
    static RefPtr<MockMediaDescription> create(const MockTrackBox& box) { return adoptRef(new MockMediaDescription(box)); }
    virtual ~MockMediaDescription() = default;

    AtomicString codec() const override { return m_box.codec(); }
    bool isVideo() const override { return m_box.kind() == MockTrackBox::Video; }
    bool isAudio() const override { return m_box.kind() == MockTrackBox::Audio; }
    bool isText() const override { return m_box.kind() == MockTrackBox::Text; }

protected:
    MockMediaDescription(const MockTrackBox& box) : m_box(box) { }
    MockTrackBox m_box;
};

RefPtr<MockSourceBufferPrivate> MockSourceBufferPrivate::create(MockMediaSourcePrivate* parent)
{
    return adoptRef(new MockSourceBufferPrivate(parent));
}

MockSourceBufferPrivate::MockSourceBufferPrivate(MockMediaSourcePrivate* parent)
    : m_mediaSource(parent)
    , m_client(0)
{
}

MockSourceBufferPrivate::~MockSourceBufferPrivate() = default;

void MockSourceBufferPrivate::setClient(SourceBufferPrivateClient* client)
{
    m_client = client;
}

void MockSourceBufferPrivate::append(Vector<unsigned char>&& data)
{
    m_inputBuffer.appendVector(data);
    SourceBufferPrivateClient::AppendResult result = SourceBufferPrivateClient::AppendSucceeded;

    while (m_inputBuffer.size() && result == SourceBufferPrivateClient::AppendSucceeded) {
        RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(m_inputBuffer.data(), m_inputBuffer.size());
        size_t boxLength = MockBox::peekLength(buffer.get());
        if (boxLength > buffer->byteLength())
            break;

        String type = MockBox::peekType(buffer.get());
        if (type == MockInitializationBox::type()) {
            MockInitializationBox initBox = MockInitializationBox(buffer.get());
            didReceiveInitializationSegment(initBox);
        } else if (type == MockSampleBox::type()) {
            MockSampleBox sampleBox = MockSampleBox(buffer.get());
            didReceiveSample(sampleBox);
        } else
            result = SourceBufferPrivateClient::ParsingFailed;

        m_inputBuffer.remove(0, boxLength);
    }

    if (m_client)
        m_client->sourceBufferPrivateAppendComplete(result);
}

void MockSourceBufferPrivate::didReceiveInitializationSegment(const MockInitializationBox& initBox)
{
    if (!m_client)
        return;

    SourceBufferPrivateClient::InitializationSegment segment;
    segment.duration = initBox.duration();

    for (auto it = initBox.tracks().begin(); it != initBox.tracks().end(); ++it) {
        const MockTrackBox& trackBox = *it;
        if (trackBox.kind() == MockTrackBox::Video) {
            SourceBufferPrivateClient::InitializationSegment::VideoTrackInformation info;
            info.track = MockVideoTrackPrivate::create(trackBox);
            info.description = MockMediaDescription::create(trackBox);
            segment.videoTracks.append(info);
        } else if (trackBox.kind() == MockTrackBox::Audio) {
            SourceBufferPrivateClient::InitializationSegment::AudioTrackInformation info;
            info.track = MockAudioTrackPrivate::create(trackBox);
            info.description = MockMediaDescription::create(trackBox);
            segment.audioTracks.append(info);
        } else if (trackBox.kind() == MockTrackBox::Text) {
            SourceBufferPrivateClient::InitializationSegment::TextTrackInformation info;
            info.track = MockTextTrackPrivate::create(trackBox);
            info.description = MockMediaDescription::create(trackBox);
            segment.textTracks.append(info);
        }
    }

    m_client->sourceBufferPrivateDidReceiveInitializationSegment(segment);
}


void MockSourceBufferPrivate::didReceiveSample(const MockSampleBox& sampleBox)
{
    if (!m_client)
        return;

    m_client->sourceBufferPrivateDidReceiveSample(MockMediaSample::create(sampleBox));
}

void MockSourceBufferPrivate::abort()
{
}

void MockSourceBufferPrivate::resetParserState()
{
}

void MockSourceBufferPrivate::removedFromMediaSource()
{
    if (m_mediaSource)
        m_mediaSource->removeSourceBuffer(this);
}

MediaPlayer::ReadyState MockSourceBufferPrivate::readyState() const
{
    return m_mediaSource ? m_mediaSource->player()->readyState() : MediaPlayer::HaveNothing;
}

void MockSourceBufferPrivate::setReadyState(MediaPlayer::ReadyState readyState)
{
    if (m_mediaSource)
        m_mediaSource->player()->setReadyState(readyState);
}

void MockSourceBufferPrivate::setActive(bool isActive)
{
    if (m_mediaSource)
        m_mediaSource->sourceBufferPrivateDidChangeActiveState(this, isActive);
}

Vector<String> MockSourceBufferPrivate::enqueuedSamplesForTrackID(const AtomicString&)
{
    return m_enqueuedSamples;
}

void MockSourceBufferPrivate::enqueueSample(Ref<MediaSample>&& sample, const AtomicString&)
{
    if (!m_mediaSource)
        return;

    PlatformSample platformSample = sample->platformSample();
    if (platformSample.type != PlatformSample::MockSampleBoxType)
        return;

    auto* box = platformSample.sample.mockSampleBox;
    if (!box)
        return;

    m_mediaSource->incrementTotalVideoFrames();
    if (box->isCorrupted())
        m_mediaSource->incrementCorruptedFrames();
    if (box->isDropped())
        m_mediaSource->incrementDroppedFrames();
    if (box->isDelayed())
        m_mediaSource->incrementTotalFrameDelayBy(MediaTime(1, 1));

    m_enqueuedSamples.append(toString(sample.get()));
}

bool MockSourceBufferPrivate::hasVideo() const
{
    return m_client && m_client->sourceBufferPrivateHasVideo();
}

bool MockSourceBufferPrivate::hasAudio() const
{
    return m_client && m_client->sourceBufferPrivateHasAudio();
}

MediaTime MockSourceBufferPrivate::fastSeekTimeForMediaTime(const MediaTime& time, const MediaTime& negativeThreshold, const MediaTime& positiveThreshold)
{
    if (m_client)
        return m_client->sourceBufferPrivateFastSeekTimeForMediaTime(time, negativeThreshold, positiveThreshold);
    return time;
}

void MockSourceBufferPrivate::seekToTime(const MediaTime& time)
{
    if (m_client)
        m_client->sourceBufferPrivateSeekToTime(time);
}

}

#endif

