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

#if ENABLE(MEDIA_SESSION)

#include "DOMWindow.h"
#include "EventNames.h"
#include "HTMLMediaElement.h"
#include "JSDOMPromiseDeferred.h"
#include "JSMediaPositionState.h"
#include "JSMediaSessionAction.h"
#include "JSMediaSessionPlaybackState.h"
#include "Logging.h"
#include "MediaMetadata.h"
#include "MediaSessionCoordinator.h"
#include "Navigator.h"
#include "Page.h"
#include "PlatformMediaSessionManager.h"
#include <wtf/JSONValues.h>

namespace WebCore {

static const void* nextLogIdentifier()
{
    static uint64_t logIdentifier = cryptographicallyRandomNumber();
    return reinterpret_cast<const void*>(++logIdentifier);
}

#if !RELEASE_LOG_DISABLED
static WTFLogChannel& logChannel()
{
    return LogMedia;
}

static const char* logClassName()
{
    return "MediaSession";
}
#endif

static PlatformMediaSession::RemoteControlCommandType platformCommandForMediaSessionAction(MediaSessionAction action)
{
    static const auto commandMap = makeNeverDestroyed([] {
        using ActionToCommandMap = HashMap<MediaSessionAction, PlatformMediaSession::RemoteControlCommandType, IntHash<MediaSessionAction>, WTF::StrongEnumHashTraits<MediaSessionAction>>;

        return ActionToCommandMap {
            { MediaSessionAction::Play, PlatformMediaSession::PlayCommand },
            { MediaSessionAction::Pause, PlatformMediaSession::PauseCommand },
            { MediaSessionAction::Seekforward, PlatformMediaSession::SkipForwardCommand },
            { MediaSessionAction::Seekbackward, PlatformMediaSession::SkipBackwardCommand },
            { MediaSessionAction::Previoustrack, PlatformMediaSession::PreviousTrackCommand },
            { MediaSessionAction::Nexttrack, PlatformMediaSession::NextTrackCommand },
            { MediaSessionAction::Stop, PlatformMediaSession::StopCommand },
            { MediaSessionAction::Seekto, PlatformMediaSession::SeekToPlaybackPositionCommand },
            { MediaSessionAction::Skipad, PlatformMediaSession::NextTrackCommand },
        };
    }());

    auto it = commandMap.get().find(action);
    if (it != commandMap.get().end())
        return it->value;

    return PlatformMediaSession::NoCommand;
}

static std::optional<std::pair<PlatformMediaSession::RemoteControlCommandType, PlatformMediaSession::RemoteCommandArgument>> platformCommandForMediaSessionAction(const MediaSessionActionDetails& actionDetails)
{
    PlatformMediaSession::RemoteControlCommandType command = PlatformMediaSession::NoCommand;
    PlatformMediaSession::RemoteCommandArgument argument;

    switch (actionDetails.action) {
    case MediaSessionAction::Play:
        command = PlatformMediaSession::PlayCommand;
        break;
    case MediaSessionAction::Pause:
        command = PlatformMediaSession::PauseCommand;
        break;
    case MediaSessionAction::Seekbackward:
        command = PlatformMediaSession::SkipBackwardCommand;
        argument.time = actionDetails.seekOffset;
        break;
    case MediaSessionAction::Seekforward:
        command = PlatformMediaSession::SkipForwardCommand;
        argument.time = actionDetails.seekOffset;
        break;
    case MediaSessionAction::Previoustrack:
        command = PlatformMediaSession::PreviousTrackCommand;
        break;
    case MediaSessionAction::Nexttrack:
        command = PlatformMediaSession::NextTrackCommand;
        break;
    case MediaSessionAction::Skipad:
        // Not supported at present.
        break;
    case MediaSessionAction::Stop:
        command = PlatformMediaSession::StopCommand;
        break;
    case MediaSessionAction::Seekto:
        command = PlatformMediaSession::SeekToPlaybackPositionCommand;
        argument.time = actionDetails.seekTime;
        argument.fastSeek = actionDetails.fastSeek;
        break;
    case MediaSessionAction::Settrack:
        // Not supported at present.
        break;
    }
    if (command == PlatformMediaSession::NoCommand)
        return { };

    return std::make_pair(command, argument);
}

Ref<MediaSession> MediaSession::create(Navigator& navigator)
{
    auto session = adoptRef(*new MediaSession(navigator));
    session->suspendIfNeeded();
    return session;
}

MediaSession::MediaSession(Navigator& navigator)
    : ActiveDOMObject(navigator.scriptExecutionContext())
    , m_navigator(navigator)
#if ENABLE(MEDIA_SESSION_COORDINATOR)
    , m_coordinator(MediaSessionCoordinator::create(navigator.scriptExecutionContext()))
#endif
{
    m_logger = &Document::sharedLogger();
    m_logIdentifier = nextLogIdentifier();

#if ENABLE(MEDIA_SESSION_COORDINATOR)
    auto* frame = navigator.frame();
    auto* page = frame ? frame->page() : nullptr;
    if (page && page->mediaSessionCoordinator())
        m_coordinator->setMediaSessionCoordinatorPrivate(*page->mediaSessionCoordinator());
    m_coordinator->setMediaSession(this);
#endif

    ALWAYS_LOG(LOGIDENTIFIER);
}

MediaSession::~MediaSession() = default;

void MediaSession::suspend(ReasonForSuspension reason)
{
#if ENABLE(MEDIA_SESSION_COORDINATOR)
    if (reason == ReasonForSuspension::BackForwardCache)
        m_coordinator->leave();
#else
    UNUSED_PARAM(reason);
#endif
}

void MediaSession::stop()
{
#if ENABLE(MEDIA_SESSION_COORDINATOR)
    m_coordinator->close();
#endif
}

void MediaSession::setMetadata(RefPtr<MediaMetadata>&& metadata)
{
    ALWAYS_LOG(LOGIDENTIFIER);
    if (m_metadata)
        m_metadata->resetMediaSession();
    m_metadata = WTFMove(metadata);
    if (m_metadata)
        m_metadata->setMediaSession(*this);
    notifyMetadataObservers();
}

#if ENABLE(MEDIA_SESSION_COORDINATOR)
void MediaSession::setReadyState(MediaSessionReadyState state)
{
    if (m_readyState == state)
        return;

    ALWAYS_LOG(LOGIDENTIFIER, state);

    m_readyState = state;
    notifyReadyStateObservers();
}
#endif

#if ENABLE(MEDIA_SESSION_PLAYLIST)
ExceptionOr<void> MediaSession::setPlaylist(ScriptExecutionContext& context, Vector<RefPtr<MediaMetadata>>&& playlist)
{
    ALWAYS_LOG(LOGIDENTIFIER);

    Vector<Ref<MediaMetadata>> resolvedPlaylist;
    resolvedPlaylist.reserveInitialCapacity(playlist.size());

    for (auto& entry : playlist) {
        auto resolvedEntry = MediaMetadata::create(context, { entry->metadata() });
        if (resolvedEntry.hasException())
            return resolvedEntry.releaseException();
        
        resolvedPlaylist.uncheckedAppend(resolvedEntry.releaseReturnValue());
    }

    m_playlist = WTFMove(resolvedPlaylist);

    return { };
}
#endif

void MediaSession::setPlaybackState(MediaSessionPlaybackState state)
{
    if (m_playbackState == state)
        return;

    ALWAYS_LOG(LOGIDENTIFIER, state);

    auto currentPosition = this->currentPosition();
    if (m_positionState && currentPosition) {
        m_positionState->position = *currentPosition;
        m_timeAtLastPositionUpdate = MonotonicTime::now();
    }
    m_playbackState = state;
    notifyPlaybackStateObservers();
}

void MediaSession::setActionHandler(MediaSessionAction action, RefPtr<MediaSessionActionHandler>&& handler)
{
    if (handler) {
        ALWAYS_LOG(LOGIDENTIFIER, "adding ", action);
        m_actionHandlers.set(action, handler);
        auto platformCommand = platformCommandForMediaSessionAction(action);
        if (platformCommand != PlatformMediaSession::NoCommand)
            PlatformMediaSessionManager::sharedManager().addSupportedCommand(platformCommand);
    } else {
        if (m_actionHandlers.contains(action)) {
            ALWAYS_LOG(LOGIDENTIFIER, "removing ", action);
            m_actionHandlers.remove(action);
        }
        PlatformMediaSessionManager::sharedManager().removeSupportedCommand(platformCommandForMediaSessionAction(action));
    }

    notifyActionHandlerObservers();
}

void MediaSession::callActionHandler(const MediaSessionActionDetails& actionDetails, DOMPromiseDeferred<void>&& promise)
{
    ALWAYS_LOG(LOGIDENTIFIER);

    if (!callActionHandler(actionDetails, TriggerGestureIndicator::No)) {
        promise.reject(InvalidStateError);
        return;
    }

    promise.resolve();
}

bool MediaSession::callActionHandler(const MediaSessionActionDetails& actionDetails, TriggerGestureIndicator triggerGestureIndicator)
{
    if (auto handler = m_actionHandlers.get(actionDetails.action)) {
        std::optional<UserGestureIndicator> maybeGestureIndicator;
        if (triggerGestureIndicator == TriggerGestureIndicator::Yes)
            maybeGestureIndicator.emplace(ProcessingUserGesture, document());
        handler->handleEvent(actionDetails);
        return true;
    }
    auto element = activeMediaElement();
    if (!element)
        return false;

    auto platformCommand = platformCommandForMediaSessionAction(actionDetails);
    if (!platformCommand)
        return false;
    element->didReceiveRemoteControlCommand(platformCommand->first, platformCommand->second);
    return true;
}

ExceptionOr<void> MediaSession::setPositionState(std::optional<MediaPositionState>&& state)
{
    if (state)
        ALWAYS_LOG(LOGIDENTIFIER, state.value());
    else
        ALWAYS_LOG(LOGIDENTIFIER, "{ }");

    if (!state) {
        m_positionState = std::nullopt;
        notifyPositionStateObservers();
        return { };
    }

    if (!(state->duration >= 0
        && state->position >= 0
        && state->position <= state->duration
        && std::isfinite(state->playbackRate)
        && state->playbackRate))
        return Exception { TypeError };

    m_positionState = WTFMove(state);
    m_lastReportedPosition = m_positionState->position;
    m_timeAtLastPositionUpdate = MonotonicTime::now();
    notifyPositionStateObservers();

    return { };
}

std::optional<double> MediaSession::currentPosition() const
{
    if (!m_positionState || !m_lastReportedPosition)
        return std::nullopt;

    auto actualPlaybackRate = m_playbackState == MediaSessionPlaybackState::Playing ? m_positionState->playbackRate : 0;

    auto elapsedTime = (MonotonicTime::now() - m_timeAtLastPositionUpdate) * actualPlaybackRate;

    return std::max(0., std::min(*m_lastReportedPosition + elapsedTime.value(), m_positionState->duration));
}

Document* MediaSession::document() const
{
    if (!m_navigator || !m_navigator->window())
        return nullptr;
    return m_navigator->window()->document();
}

void MediaSession::metadataUpdated()
{
    notifyMetadataObservers();
}

void MediaSession::addObserver(Observer& observer)
{
    ASSERT(isMainThread());
    m_observers.add(observer);
}

void MediaSession::removeObserver(Observer& observer)
{
    ASSERT(isMainThread());
    m_observers.remove(observer);
}

void MediaSession::forEachObserver(const Function<void(Observer&)>& apply)
{
    ASSERT(isMainThread());
    Ref protectedThis { *this };
    m_observers.forEach(apply);
}

void MediaSession::notifyMetadataObservers()
{
    forEachObserver([this](auto& observer) {
        observer.metadataChanged(m_metadata);
    });
}

void MediaSession::notifyPositionStateObservers()
{
    forEachObserver([this](auto& observer) {
        observer.positionStateChanged(m_positionState);
    });
}

void MediaSession::notifyPlaybackStateObservers()
{
    forEachObserver([this](auto& observer) {
        observer.playbackStateChanged(m_playbackState);
    });
}

void MediaSession::notifyActionHandlerObservers()
{
    forEachObserver([](auto& observer) {
        observer.actionHandlersChanged();
    });
}

RefPtr<HTMLMediaElement> MediaSession::activeMediaElement() const
{
    auto* doc = document();
    if (!doc)
        return nullptr;

    return HTMLMediaElement::bestMediaElementForRemoteControls(MediaElementSession::PlaybackControlsPurpose::MediaSession, doc);
}

#if ENABLE(MEDIA_SESSION_COORDINATOR)
void MediaSession::notifyReadyStateObservers()
{
    forEachObserver([this](auto& observer) {
        observer.readyStateChanged(m_readyState);
    });
}
#endif

String MediaPositionState::toJSONString() const
{
    auto object = JSON::Object::create();

    object->setDouble("duration"_s, duration);
    object->setDouble("playbackRate"_s, playbackRate);
    object->setDouble("position"_s, position);

    return object->toJSONString();
}

}

#endif // ENABLE(MEDIA_SESSION)
