/*
 * Copyright (C) 2013-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:
 * 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. AND ITS 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 "PlatformMediaSessionManager.h"

#include "AudioSession.h"
#include "Document.h"
#include "Logging.h"
#include "PlatformMediaSession.h"

namespace WebCore {

#if ENABLE(VIDEO) || ENABLE(WEB_AUDIO)

static std::unique_ptr<PlatformMediaSessionManager>& sharedPlatformMediaSessionManager()
{
    static NeverDestroyed<std::unique_ptr<PlatformMediaSessionManager>> platformMediaSessionManager;
    return platformMediaSessionManager.get();
}

PlatformMediaSessionManager& PlatformMediaSessionManager::sharedManager()
{
    auto& manager = sharedPlatformMediaSessionManager();
    if (!manager) {
        manager = PlatformMediaSessionManager::create();
        manager->resetRestrictions();
    }
    return *manager;
}

PlatformMediaSessionManager* PlatformMediaSessionManager::sharedManagerIfExists()
{
    return sharedPlatformMediaSessionManager().get();
}

#if !PLATFORM(COCOA)
std::unique_ptr<PlatformMediaSessionManager> PlatformMediaSessionManager::create()
{
    return std::unique_ptr<PlatformMediaSessionManager>(new PlatformMediaSessionManager);
}
#endif // !PLATFORM(COCOA)

void PlatformMediaSessionManager::updateNowPlayingInfoIfNecessary()
{
    if (auto existingManager = PlatformMediaSessionManager::sharedManagerIfExists())
        existingManager->scheduleUpdateNowPlayingInfo();
}

PlatformMediaSessionManager::PlatformMediaSessionManager()
#if !RELEASE_LOG_DISABLED
    : m_logger(AggregateLogger::create(this))
#endif
{
}

static inline unsigned indexFromMediaType(PlatformMediaSession::MediaType type)
{
    return static_cast<unsigned>(type);
}

void PlatformMediaSessionManager::resetRestrictions()
{
    m_restrictions[indexFromMediaType(PlatformMediaSession::MediaType::Video)] = NoRestrictions;
    m_restrictions[indexFromMediaType(PlatformMediaSession::MediaType::Audio)] = NoRestrictions;
    m_restrictions[indexFromMediaType(PlatformMediaSession::MediaType::VideoAudio)] = NoRestrictions;
    m_restrictions[indexFromMediaType(PlatformMediaSession::MediaType::WebAudio)] = NoRestrictions;
}

bool PlatformMediaSessionManager::has(PlatformMediaSession::MediaType type) const
{
    return anyOfSessions([type] (auto& session) {
        return session.mediaType() == type;
    });
}

bool PlatformMediaSessionManager::activeAudioSessionRequired() const
{
    return anyOfSessions([] (auto& session) {
        return session.activeAudioSessionRequired();
    });
}

bool PlatformMediaSessionManager::canProduceAudio() const
{
    return anyOfSessions([] (auto& session) {
        return session.canProduceAudio();
    });
}

int PlatformMediaSessionManager::count(PlatformMediaSession::MediaType type) const
{
    int count = 0;
    for (const auto& session : m_sessions) {
        if (session->mediaType() == type)
            ++count;
    }

    return count;
}

int PlatformMediaSessionManager::countActiveAudioCaptureSources()
{
    int count = 0;
    for (const auto& source : m_audioCaptureSources) {
        if (source.isCapturingAudio())
            ++count;
    }
    return count;
}

void PlatformMediaSessionManager::beginInterruption(PlatformMediaSession::InterruptionType type)
{
    ALWAYS_LOG(LOGIDENTIFIER);

    m_interrupted = true;
    forEachSession([type] (auto& session) {
        session.beginInterruption(type);
    });
    updateSessionState();
}

void PlatformMediaSessionManager::endInterruption(PlatformMediaSession::EndInterruptionFlags flags)
{
    ALWAYS_LOG(LOGIDENTIFIER);

    m_interrupted = false;
    forEachSession([flags] (auto& session) {
        session.endInterruption(flags);
    });
}

void PlatformMediaSessionManager::addSession(PlatformMediaSession& session)
{
    ALWAYS_LOG(LOGIDENTIFIER, session.logIdentifier());
    m_sessions.append(makeWeakPtr(session));
    if (m_interrupted)
        session.setState(PlatformMediaSession::Interrupted);

#if !RELEASE_LOG_DISABLED
    m_logger->addLogger(session.logger());
#endif

    updateSessionState();
}

bool PlatformMediaSessionManager::hasNoSession() const
{
    return m_sessions.isEmpty() || std::all_of(m_sessions.begin(), m_sessions.end(), std::logical_not<void>());
}

void PlatformMediaSessionManager::removeSession(PlatformMediaSession& session)
{
    ALWAYS_LOG(LOGIDENTIFIER, session.logIdentifier());

    size_t index = m_sessions.find(&session);
    if (index == notFound)
        return;

    m_sessions.remove(index);

#if USE(AUDIO_SESSION)
    if (hasNoSession())
        maybeDeactivateAudioSession();
#endif

#if !RELEASE_LOG_DISABLED
    m_logger->removeLogger(session.logger());
#endif

    updateSessionState();
}

void PlatformMediaSessionManager::addRestriction(PlatformMediaSession::MediaType type, SessionRestrictions restriction)
{
    m_restrictions[indexFromMediaType(type)] |= restriction;
}

void PlatformMediaSessionManager::removeRestriction(PlatformMediaSession::MediaType type, SessionRestrictions restriction)
{
    m_restrictions[indexFromMediaType(type)] &= ~restriction;
}

PlatformMediaSessionManager::SessionRestrictions PlatformMediaSessionManager::restrictions(PlatformMediaSession::MediaType type)
{
    return m_restrictions[indexFromMediaType(type)];
}

bool PlatformMediaSessionManager::sessionWillBeginPlayback(PlatformMediaSession& session)
{
    setCurrentSession(session);

    auto sessionType = session.mediaType();
    auto restrictions = this->restrictions(sessionType);
    if (session.state() == PlatformMediaSession::Interrupted && restrictions & InterruptedPlaybackNotPermitted) {
        ALWAYS_LOG(LOGIDENTIFIER, session.logIdentifier(), " returning false because session.state() is Interrupted, and InterruptedPlaybackNotPermitted");
        return false;
    }

#if USE(AUDIO_SESSION)
    if (activeAudioSessionRequired()) {
        if (!AudioSession::sharedSession().tryToSetActive(true)) {
            ALWAYS_LOG(LOGIDENTIFIER, session.logIdentifier(), " returning false failed to set active AudioSession");
            return false;
        }

        ALWAYS_LOG(LOGIDENTIFIER, session.logIdentifier(), " sucessfully activated AudioSession");
        m_becameActive = true;
    }
#endif

    if (m_interrupted)
        endInterruption(PlatformMediaSession::NoFlags);

    if (restrictions & ConcurrentPlaybackNotPermitted) {
        forEachMatchingSession([&session, sessionType](auto& oneSession) {
            return &oneSession != &session
                && oneSession.mediaType() == sessionType
                && oneSession.state() == PlatformMediaSession::Playing
                && !oneSession.canPlayConcurrently(session);
        }, [](auto& oneSession) {
            oneSession.pauseSession();
        });
    }
    ALWAYS_LOG(LOGIDENTIFIER, session.logIdentifier(), " returning true");
    return true;
}
    
void PlatformMediaSessionManager::sessionWillEndPlayback(PlatformMediaSession& session, DelayCallingUpdateNowPlaying)
{
    ALWAYS_LOG(LOGIDENTIFIER, session.logIdentifier());

    if (m_sessions.size() < 2)
        return;
    
    size_t pausingSessionIndex = notFound;
    size_t lastPlayingSessionIndex = notFound;
    for (size_t i = 0, size = m_sessions.size(); i < size; ++i) {
        const auto& oneSession = *m_sessions[i];
        if (&oneSession == &session)
            pausingSessionIndex = i;
        else if (oneSession.state() == PlatformMediaSession::Playing)
            lastPlayingSessionIndex = i;
        else
            break;
    }

    if (lastPlayingSessionIndex == notFound || pausingSessionIndex == notFound)
        return;

    if (pausingSessionIndex > lastPlayingSessionIndex)
        return;

    m_sessions.remove(pausingSessionIndex);
    m_sessions.append(makeWeakPtr(session));

    ALWAYS_LOG(LOGIDENTIFIER, "session moved from index ", pausingSessionIndex, " to ", lastPlayingSessionIndex);
}

void PlatformMediaSessionManager::sessionStateChanged(PlatformMediaSession&)
{
    updateSessionState();
}

void PlatformMediaSessionManager::setCurrentSession(PlatformMediaSession& session)
{
    ALWAYS_LOG(LOGIDENTIFIER, session.logIdentifier());
    
    if (m_sessions.size() < 2)
        return;
    
    size_t index = m_sessions.find(&session);
    ASSERT(index != notFound);
    if (!index || index == notFound)
        return;

    m_sessions.remove(index);
    m_sessions.insert(0, makeWeakPtr(session));
    
    ALWAYS_LOG(LOGIDENTIFIER, "session moved from index ", index, " to 0");
}
    
PlatformMediaSession* PlatformMediaSessionManager::currentSession() const
{
    if (!m_sessions.size())
        return nullptr;

    return m_sessions[0].get();
}

void PlatformMediaSessionManager::applicationWillBecomeInactive()
{
    ALWAYS_LOG(LOGIDENTIFIER);

    forEachMatchingSession([&](auto& session) {
        return restrictions(session.mediaType()) & InactiveProcessPlaybackRestricted;
    }, [](auto& session) {
        session.beginInterruption(PlatformMediaSession::ProcessInactive);
    });
}

void PlatformMediaSessionManager::applicationDidBecomeActive()
{
    ALWAYS_LOG(LOGIDENTIFIER);

    forEachMatchingSession([&](auto& session) {
        return restrictions(session.mediaType()) & InactiveProcessPlaybackRestricted;
    }, [](auto& session) {
        session.endInterruption(PlatformMediaSession::MayResumePlaying);
    });
}

void PlatformMediaSessionManager::applicationDidEnterBackground(bool suspendedUnderLock)
{
    ALWAYS_LOG(LOGIDENTIFIER, "suspendedUnderLock: ", suspendedUnderLock);

    if (m_isApplicationInBackground)
        return;

    m_isApplicationInBackground = true;

    forEachSession([&] (auto& session) {
        if (suspendedUnderLock && restrictions(session.mediaType()) & SuspendedUnderLockPlaybackRestricted)
            session.beginInterruption(PlatformMediaSession::SuspendedUnderLock);
        else if (restrictions(session.mediaType()) & BackgroundProcessPlaybackRestricted)
            session.beginInterruption(PlatformMediaSession::EnteringBackground);
    });
}

void PlatformMediaSessionManager::applicationWillEnterForeground(bool suspendedUnderLock)
{
    ALWAYS_LOG(LOGIDENTIFIER, "suspendedUnderLock: ", suspendedUnderLock);

    if (!m_isApplicationInBackground)
        return;

    m_isApplicationInBackground = false;

    forEachMatchingSession([&](auto& session) {
        return (suspendedUnderLock && restrictions(session.mediaType()) & SuspendedUnderLockPlaybackRestricted) || restrictions(session.mediaType()) & BackgroundProcessPlaybackRestricted;
    }, [](auto& session) {
        session.endInterruption(PlatformMediaSession::MayResumePlaying);
    });
}

void PlatformMediaSessionManager::processWillSuspend()
{
    if (m_processIsSuspended)
        return;
    m_processIsSuspended = true;

    ALWAYS_LOG(LOGIDENTIFIER);

    forEachSession([&] (auto& session) {
        session.client().processIsSuspendedChanged();
    });

#if USE(AUDIO_SESSION)
    maybeDeactivateAudioSession();
#endif
}

void PlatformMediaSessionManager::processDidResume()
{
    if (!m_processIsSuspended)
        return;
    m_processIsSuspended = false;

    forEachSession([&] (auto& session) {
        session.client().processIsSuspendedChanged();
    });

#if USE(AUDIO_SESSION)
    if (!m_becameActive && activeAudioSessionRequired()) {
        m_becameActive = AudioSession::sharedSession().tryToSetActive(true);
        ALWAYS_LOG(LOGIDENTIFIER, "tried to set active AudioSession, ", m_becameActive ? "succeeded" : "failed");
    }
#endif
}

void PlatformMediaSessionManager::setIsPlayingToAutomotiveHeadUnit(bool isPlayingToAutomotiveHeadUnit)
{
    if (isPlayingToAutomotiveHeadUnit == m_isPlayingToAutomotiveHeadUnit)
        return;

    ALWAYS_LOG(LOGIDENTIFIER, isPlayingToAutomotiveHeadUnit);
    m_isPlayingToAutomotiveHeadUnit = isPlayingToAutomotiveHeadUnit;
}

void PlatformMediaSessionManager::sessionIsPlayingToWirelessPlaybackTargetChanged(PlatformMediaSession& session)
{
    if (!m_isApplicationInBackground || !(restrictions(session.mediaType()) & BackgroundProcessPlaybackRestricted))
        return;

    if (session.state() != PlatformMediaSession::Interrupted)
        session.beginInterruption(PlatformMediaSession::EnteringBackground);
}

void PlatformMediaSessionManager::sessionCanProduceAudioChanged()
{
    updateSessionState();
}

void PlatformMediaSessionManager::processDidReceiveRemoteControlCommand(PlatformMediaSession::RemoteControlCommandType command, const PlatformMediaSession::RemoteCommandArgument* argument)
{
    PlatformMediaSession* activeSession = currentSession();
    if (!activeSession || !activeSession->canReceiveRemoteControlCommands())
        return;
    activeSession->didReceiveRemoteControlCommand(command, argument);
}

bool PlatformMediaSessionManager::computeSupportsSeeking() const
{
    PlatformMediaSession* activeSession = currentSession();
    if (!activeSession)
        return false;
    return activeSession->supportsSeeking();
}

void PlatformMediaSessionManager::processSystemWillSleep()
{
    if (m_interrupted)
        return;

    forEachSession([] (auto& session) {
        session.beginInterruption(PlatformMediaSession::SystemSleep);
    });
}

void PlatformMediaSessionManager::processSystemDidWake()
{
    if (m_interrupted)
        return;

    forEachSession([] (auto& session) {
        session.endInterruption(PlatformMediaSession::MayResumePlaying);
    });
}

void PlatformMediaSessionManager::stopAllMediaPlaybackForDocument(DocumentIdentifier documentIdentifier)
{
    forEachDocumentSession(documentIdentifier, [](auto& session) {
        session.pauseSession();
    });
}

void PlatformMediaSessionManager::stopAllMediaPlaybackForProcess()
{
    forEachSession([] (auto& session) {
        session.stopSession();
    });
}

void PlatformMediaSessionManager::suspendAllMediaPlaybackForDocument(DocumentIdentifier documentIdentifier)
{
    forEachDocumentSession(documentIdentifier, [](auto& session) {
        session.beginInterruption(PlatformMediaSession::PlaybackSuspended);
    });
}

void PlatformMediaSessionManager::resumeAllMediaPlaybackForDocument(DocumentIdentifier documentIdentifier)
{
    forEachDocumentSession(documentIdentifier, [](auto& session) {
        session.endInterruption(PlatformMediaSession::MayResumePlaying);
    });
}

void PlatformMediaSessionManager::suspendAllMediaBufferingForDocument(DocumentIdentifier documentIdentifier)
{
    forEachDocumentSession(documentIdentifier, [](auto& session) {
        session.suspendBuffering();
    });
}

void PlatformMediaSessionManager::resumeAllMediaBufferingForDocument(DocumentIdentifier documentIdentifier)
{
    forEachDocumentSession(documentIdentifier, [](auto& session) {
        session.resumeBuffering();
    });
}

Vector<WeakPtr<PlatformMediaSession>> PlatformMediaSessionManager::sessionsMatching(const Function<bool(const PlatformMediaSession&)>& filter) const
{
    Vector<WeakPtr<PlatformMediaSession>> matchingSessions;
    for (auto& session : m_sessions) {
        if (filter(*session))
            matchingSessions.append(session);
    }
    return matchingSessions;
}

void PlatformMediaSessionManager::forEachMatchingSession(const Function<bool(const PlatformMediaSession&)>& predicate, const Function<void(PlatformMediaSession&)>& callback)
{
    for (auto& session : sessionsMatching(predicate)) {
        ASSERT(session);
        if (session)
            callback(*session);
    }
}

void PlatformMediaSessionManager::forEachDocumentSession(DocumentIdentifier documentIdentifier, const Function<void(PlatformMediaSession&)>& callback)
{
    forEachMatchingSession([documentIdentifier](auto& session) {
        return session.client().hostingDocumentIdentifier() == documentIdentifier;
    }, [&callback](auto& session) {
        callback(session);
    });
}

void PlatformMediaSessionManager::forEachSession(const Function<void(PlatformMediaSession&)>& callback)
{
    auto sessions = m_sessions;
    for (auto& session : sessions) {
        ASSERT(session);
        if (session)
            callback(*session);
    }
}

bool PlatformMediaSessionManager::anyOfSessions(const Function<bool(const PlatformMediaSession&)>& predicate) const
{
    return WTF::anyOf(m_sessions, [&predicate](const auto& session) {
        return predicate(*session);
    });
}

void PlatformMediaSessionManager::addAudioCaptureSource(PlatformMediaSession::AudioCaptureSource& source)
{
    ASSERT(!m_audioCaptureSources.contains(source));
    m_audioCaptureSources.add(source);
    updateSessionState();
}


void PlatformMediaSessionManager::removeAudioCaptureSource(PlatformMediaSession::AudioCaptureSource& source)
{
    ASSERT(m_audioCaptureSources.contains(source));
    m_audioCaptureSources.remove(source);
    updateSessionState();
}

#if USE(AUDIO_SESSION)
void PlatformMediaSessionManager::maybeDeactivateAudioSession()
{
    if (!m_becameActive || !shouldDeactivateAudioSession())
        return;

    ALWAYS_LOG(LOGIDENTIFIER, "tried to set inactive AudioSession");
    AudioSession::sharedSession().tryToSetActive(false);
    m_becameActive = false;
}
#endif

static bool& deactivateAudioSession()
{
    static bool deactivate;
    return deactivate;
}

bool PlatformMediaSessionManager::shouldDeactivateAudioSession()
{
    return deactivateAudioSession();
}

void PlatformMediaSessionManager::setShouldDeactivateAudioSession(bool deactivate)
{
    deactivateAudioSession() = deactivate;
}

#else // ENABLE(VIDEO) || ENABLE(WEB_AUDIO)

void PlatformMediaSessionManager::updateNowPlayingInfoIfNecessary()
{

}

#endif // ENABLE(VIDEO) || ENABLE(WEB_AUDIO)

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

} // namespace WebCore
