/*
 * Copyright (C) 2011, 2015 Ericsson AB. All rights reserved.
 * Copyright (C) 2013 Google Inc. All rights reserved.
 * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies).
 * Copyright (C) 2015-2019 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * 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 THE COPYRIGHT
 * OWNER 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 "MediaStreamPrivate.h"

#if ENABLE(MEDIA_STREAM)

#include "GraphicsContext.h"
#include "IntRect.h"
#include "Logging.h"
#include <wtf/MainThread.h>
#include <wtf/RefCounted.h>
#include <wtf/Vector.h>

namespace WebCore {

Ref<MediaStreamPrivate> MediaStreamPrivate::create(Ref<const Logger>&& logger, Ref<RealtimeMediaSource>&& source)
{
    auto loggerCopy = logger.copyRef();
    return MediaStreamPrivate::create(WTFMove(logger), MediaStreamTrackPrivateVector::from(MediaStreamTrackPrivate::create(WTFMove(loggerCopy), WTFMove(source))));
}

Ref<MediaStreamPrivate> MediaStreamPrivate::create(Ref<const Logger>&& logger, const Vector<Ref<RealtimeMediaSource>>& audioSources, const Vector<Ref<RealtimeMediaSource>>& videoSources)
{
    MediaStreamTrackPrivateVector tracks;
    tracks.reserveInitialCapacity(audioSources.size() + videoSources.size());

    for (auto& source : audioSources)
        tracks.uncheckedAppend(MediaStreamTrackPrivate::create(logger.copyRef(), source.copyRef()));

    for (auto& source : videoSources)
        tracks.uncheckedAppend(MediaStreamTrackPrivate::create(logger.copyRef(), source.copyRef()));

    return MediaStreamPrivate::create(WTFMove(logger), tracks);
}

MediaStreamPrivate::MediaStreamPrivate(Ref<const Logger>&& logger, const MediaStreamTrackPrivateVector& tracks, String&& id)
    : m_id(WTFMove(id))
#if !RELEASE_LOG_DISABLED
    , m_logger(WTFMove(logger))
    , m_logIdentifier(uniqueLogIdentifier())
#endif
{
    UNUSED_PARAM(logger);
    ASSERT(!m_id.isEmpty());

    for (auto& track : tracks) {
        track->addObserver(*this);
        m_trackSet.add(track->id(), track);
    }

    updateActiveState(NotifyClientOption::DontNotify);
}

MediaStreamPrivate::~MediaStreamPrivate()
{
    for (auto& track : m_trackSet.values())
        track->removeObserver(*this);
}

void MediaStreamPrivate::addObserver(MediaStreamPrivate::Observer& observer)
{
    RELEASE_ASSERT(isMainThread());
    m_observers.add(&observer);
}

void MediaStreamPrivate::removeObserver(MediaStreamPrivate::Observer& observer)
{
    RELEASE_ASSERT(isMainThread());
    m_observers.remove(&observer);
}

void MediaStreamPrivate::forEachObserver(const WTF::Function<void(Observer&)>& apply) const
{
    RELEASE_ASSERT(isMainThread());
    for (auto* observer : copyToVector(m_observers)) {
        if (!m_observers.contains(observer))
            continue;
        apply(*observer);
    }
}

MediaStreamTrackPrivateVector MediaStreamPrivate::tracks() const
{
    return copyToVector(m_trackSet.values());
}

void MediaStreamPrivate::updateActiveState(NotifyClientOption notifyClientOption)
{
    bool newActiveState = false;
    for (auto& track : m_trackSet.values()) {
        if (!track->ended()) {
            newActiveState = true;
            break;
        }
    }

    updateActiveVideoTrack();

    // A stream is active if it has at least one un-ended track.
    if (newActiveState == m_isActive)
        return;

    m_isActive = newActiveState;

    if (notifyClientOption == NotifyClientOption::Notify) {
        forEachObserver([](auto& observer) {
            observer.activeStatusChanged();
        });
    }
}

void MediaStreamPrivate::addTrack(RefPtr<MediaStreamTrackPrivate>&& track, NotifyClientOption notifyClientOption)
{
    if (m_trackSet.contains(track->id()))
        return;

    ALWAYS_LOG(LOGIDENTIFIER, track->logIdentifier());

    track->addObserver(*this);
    m_trackSet.add(track->id(), track);

    if (notifyClientOption == NotifyClientOption::Notify) {
        forEachObserver([&track](auto& observer) {
            observer.didAddTrack(*track.get());
        });
    }

    updateActiveState(notifyClientOption);
    characteristicsChanged();
}

void MediaStreamPrivate::removeTrack(MediaStreamTrackPrivate& track, NotifyClientOption notifyClientOption)
{
    if (!m_trackSet.remove(track.id()))
        return;

    ALWAYS_LOG(LOGIDENTIFIER, track.logIdentifier());
    track.removeObserver(*this);

    if (notifyClientOption == NotifyClientOption::Notify) {
        forEachObserver([&track](auto& observer) {
            observer.didRemoveTrack(track);
        });
    }

    updateActiveState(NotifyClientOption::Notify);
    characteristicsChanged();
}

void MediaStreamPrivate::startProducingData()
{
    ALWAYS_LOG(LOGIDENTIFIER);
    for (auto& track : m_trackSet.values())
        track->startProducingData();
}

void MediaStreamPrivate::stopProducingData()
{
    ALWAYS_LOG(LOGIDENTIFIER);
    for (auto& track : m_trackSet.values())
        track->stopProducingData();
}

bool MediaStreamPrivate::isProducingData() const
{
    for (auto& track : m_trackSet.values()) {
        if (track->isProducingData())
            return true;
    }
    return false;
}

bool MediaStreamPrivate::hasVideo() const
{
    for (auto& track : m_trackSet.values()) {
        if (track->type() == RealtimeMediaSource::Type::Video && track->isActive())
            return true;
    }
    return false;
}

bool MediaStreamPrivate::hasAudio() const
{
    for (auto& track : m_trackSet.values()) {
        if (track->type() == RealtimeMediaSource::Type::Audio && track->isActive())
            return true;
    }
    return false;
}

bool MediaStreamPrivate::muted() const
{
    for (auto& track : m_trackSet.values()) {
        if (!track->muted() && !track->ended())
            return false;
    }
    return true;
}

FloatSize MediaStreamPrivate::intrinsicSize() const
{
    FloatSize size;

    if (m_activeVideoTrack) {
        const RealtimeMediaSourceSettings& setting = m_activeVideoTrack->settings();
        size.setWidth(setting.width());
        size.setHeight(setting.height());
    }

    return size;
}

void MediaStreamPrivate::updateActiveVideoTrack()
{
    m_activeVideoTrack = nullptr;
    for (auto& track : m_trackSet.values()) {
        if (!track->ended() && track->type() == RealtimeMediaSource::Type::Video) {
            m_activeVideoTrack = track.get();
            break;
        }
    }
}

void MediaStreamPrivate::characteristicsChanged()
{
    forEachObserver([](auto& observer) {
        observer.characteristicsChanged();
    });
}

void MediaStreamPrivate::trackMutedChanged(MediaStreamTrackPrivate& track)
{
#if RELEASE_LOG_DISABLED
    UNUSED_PARAM(track);
#endif

    ALWAYS_LOG(LOGIDENTIFIER, track.logIdentifier(), " ", track.muted());
    characteristicsChanged();
}

void MediaStreamPrivate::trackSettingsChanged(MediaStreamTrackPrivate&)
{
    characteristicsChanged();
}

void MediaStreamPrivate::trackEnabledChanged(MediaStreamTrackPrivate& track)
{
#if RELEASE_LOG_DISABLED
    UNUSED_PARAM(track);
#endif

    ALWAYS_LOG(LOGIDENTIFIER, track.logIdentifier(), " ", track.enabled());
    updateActiveVideoTrack();

    characteristicsChanged();
}

void MediaStreamPrivate::trackStarted(MediaStreamTrackPrivate& track)
{
#if RELEASE_LOG_DISABLED
    UNUSED_PARAM(track);
#endif

    ALWAYS_LOG(LOGIDENTIFIER, track.logIdentifier());
    characteristicsChanged();
}

void MediaStreamPrivate::trackEnded(MediaStreamTrackPrivate& track)
{
#if RELEASE_LOG_DISABLED
    UNUSED_PARAM(track);
#endif

    ALWAYS_LOG(LOGIDENTIFIER, track.logIdentifier());
    updateActiveState(NotifyClientOption::Notify);
    characteristicsChanged();
}

void MediaStreamPrivate::monitorOrientation(OrientationNotifier& notifier)
{
    for (auto& track : m_trackSet.values()) {
        if (track->source().isCaptureSource() && track->type() == RealtimeMediaSource::Type::Video)
            track->source().monitorOrientation(notifier);
    }
}

#if !RELEASE_LOG_DISABLED
WTFLogChannel& MediaStreamPrivate::logChannel() const
{
    return LogWebRTC;
}
#endif

} // namespace WebCore

#endif // ENABLE(MEDIA_STREAM)
