/*
 * Copyright (C) 2015 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 "MediaSession.h"

#if ENABLE(MEDIA_SESSION)

#include "Chrome.h"
#include "ChromeClient.h"
#include "Event.h"
#include "EventNames.h"
#include "HTMLMediaElement.h"
#include "MediaSessionManager.h"
#include "Page.h"

namespace WebCore {

MediaSession::MediaSession(Document& document, Kind kind)
    : m_document(document)
    , m_kind(kind)
{
    // 4. Media Sessions
    // 3. If media session's current media session type is "content", then create a new media remote controller for media
    //    session. (Otherwise media session has no media remote controller.)
    if (m_kind == Kind::Content)
        m_controls = MediaRemoteControls::create(document, this);

    MediaSessionManager::singleton().addMediaSession(*this);
}

MediaSession::~MediaSession()
{
    MediaSessionManager::singleton().removeMediaSession(*this);

    if (m_controls)
        m_controls->clearSession();
}

MediaRemoteControls* MediaSession::controls()
{
    return m_controls.get();
}

void MediaSession::addMediaElement(HTMLMediaElement& element)
{
    ASSERT(!m_participatingElements.contains(&element));
    m_participatingElements.add(&element);
}

void MediaSession::removeMediaElement(HTMLMediaElement& element)
{
    ASSERT(m_participatingElements.contains(&element));
    m_participatingElements.remove(&element);

    changeActiveMediaElements([&]() {
        m_activeParticipatingElements.remove(&element);
    });

    if (m_iteratedActiveParticipatingElements)
        m_iteratedActiveParticipatingElements->remove(&element);
}

void MediaSession::changeActiveMediaElements(const WTF::Function<void(void)>& worker)
{
    if (Page *page = m_document.page()) {
        bool hadActiveMediaElements = MediaSessionManager::singleton().hasActiveMediaElements();

        worker();

        bool hasActiveMediaElements = MediaSessionManager::singleton().hasActiveMediaElements();
        if (hadActiveMediaElements != hasActiveMediaElements)
            page->chrome().client().hasMediaSessionWithActiveMediaElementsDidChange(hasActiveMediaElements);
    } else
        worker();
}

void MediaSession::addActiveMediaElement(HTMLMediaElement& element)
{
    changeActiveMediaElements([&]() {
        m_activeParticipatingElements.add(&element);
    });
}

bool MediaSession::isMediaElementActive(HTMLMediaElement& element)
{
    return m_activeParticipatingElements.contains(&element);
}

bool MediaSession::hasActiveMediaElements() const
{
    return !m_activeParticipatingElements.isEmpty();
}

void MediaSession::setMetadata(const std::optional<Metadata>& optionalMetadata)
{
    if (!optionalMetadata)
        m_metadata = { };
    else {
        auto& metadata = optionalMetadata.value();
        m_metadata = { metadata.title, metadata.artist, metadata.album, m_document.completeURL(metadata.artwork) };
    }

    if (auto* page = m_document.page())
        page->chrome().client().mediaSessionMetadataDidChange(m_metadata);
}

void MediaSession::deactivate()
{
    // 5.1.2. Object members
    // When the deactivate() method is invoked, the user agent must run the following steps:
    // 1. Let media session be the current media session.
    // 2. Indefinitely pause all of media session’s audio-producing participants.
    // 3. Set media session's resume list to an empty list.
    // 4. Set media session's audio-producing participants to an empty list.
    changeActiveMediaElements([&]() {
        while (!m_activeParticipatingElements.isEmpty())
            m_activeParticipatingElements.takeAny()->pause();
    });

    // 5. Run the media session deactivation algorithm for media session.
    releaseInternal();
}

void MediaSession::releaseInternal()
{
    // 6.5. Releasing a media session
    // 1. If current media session's current state is idle, then terminate these steps.
    if (m_currentState == State::Idle)
        return;

    // 2. If current media session still has one or more active participating media elements, then terminate these steps.
    if (!m_activeParticipatingElements.isEmpty())
        return;

    // 3. Optionally, based on platform conventions, the user agent must release any currently held platform media focus
    //    for current media session.
    // 4. Optionally, based on platform conventions, the user agent must remove any previously established ongoing media
    //    interface in the underlying platform’s notifications area and any ongoing media interface in the underlying
    //    platform's lock screen area for current media session, if any.
    // 5. Optionally, based on platform conventions, the user agent must prevent any hardware and/or software media keys
    //    from controlling playback of current media session's active participating media elements.
    // 6. Set current media session's current state to idle.
    m_currentState = State::Idle;
}

bool MediaSession::invoke()
{
    // 4.4 Activating a media session
    // 1. If we're already ACTIVE then return success.
    if (m_currentState == State::Active)
        return true;

    // 2. Optionally, based on platform conventions, request the most appropriate platform-level media focus for media
    //    session based on its current media session type.

    // 3. Run these substeps...

    // 4. Set our current state to ACTIVE and return success.
    m_currentState = State::Active;
    return true;
}

void MediaSession::handleDuckInterruption()
{
    for (auto* element : m_activeParticipatingElements)
        element->setShouldDuck(true);

    m_currentState = State::Interrupted;
}

void MediaSession::handleUnduckInterruption()
{
    for (auto* element : m_activeParticipatingElements)
        element->setShouldDuck(false);

    m_currentState = State::Active;
}

void MediaSession::handleIndefinitePauseInterruption()
{
    safelyIterateActiveMediaElements([](HTMLMediaElement* element) {
        element->pause();
    });

    m_activeParticipatingElements.clear();
    m_currentState = State::Idle;
}

void MediaSession::handlePauseInterruption()
{
    m_currentState = State::Interrupted;

    safelyIterateActiveMediaElements([](HTMLMediaElement* element) {
        element->pause();
    });
}

void MediaSession::handleUnpauseInterruption()
{
    m_currentState = State::Active;

    safelyIterateActiveMediaElements([](HTMLMediaElement* element) {
        element->play();
    });
}

void MediaSession::togglePlayback()
{
    safelyIterateActiveMediaElements([](HTMLMediaElement* element) {
        if (element->paused())
            element->play();
        else
            element->pause();
    });
}

void MediaSession::safelyIterateActiveMediaElements(const WTF::Function<void(HTMLMediaElement*)>& handler)
{
    ASSERT(!m_iteratedActiveParticipatingElements);

    HashSet<HTMLMediaElement*> activeParticipatingElementsCopy = m_activeParticipatingElements;
    m_iteratedActiveParticipatingElements = &activeParticipatingElementsCopy;

    while (!activeParticipatingElementsCopy.isEmpty())
        handler(activeParticipatingElementsCopy.takeAny());

    m_iteratedActiveParticipatingElements = nullptr;
}

void MediaSession::skipToNextTrack()
{
    if (m_controls && m_controls->nextTrackEnabled())
        m_controls->dispatchEvent(Event::create(eventNames().nexttrackEvent, false, false));
}

void MediaSession::skipToPreviousTrack()
{
    if (m_controls && m_controls->previousTrackEnabled())
        m_controls->dispatchEvent(Event::create(eventNames().previoustrackEvent, false, false));
}

void MediaSession::controlIsEnabledDidChange()
{
    // Media remote controls are only allowed on Content media sessions.
    ASSERT(m_kind == Kind::Content);

    // Media elements belonging to Content media sessions have mutually-exclusive playback.
    ASSERT(m_activeParticipatingElements.size() <= 1);

    if (m_activeParticipatingElements.isEmpty())
        return;

    HTMLMediaElement* element = *m_activeParticipatingElements.begin();
    m_document.updateIsPlayingMedia(element->elementID());
}

}

#endif /* ENABLE(MEDIA_SESSION) */
