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

#if ENABLE(WIRELESS_PLAYBACK_TARGET)

#include "Event.h"
#include "EventNames.h"
#include "HTMLMediaElement.h"
#include "JSDOMPromiseDeferred.h"
#include "Logging.h"
#include "MediaElementSession.h"
#include "MediaPlaybackTarget.h"
#include "RemotePlaybackAvailabilityCallback.h"
#include <wtf/IsoMallocInlines.h>

namespace WebCore {

WTF_MAKE_ISO_ALLOCATED_IMPL(RemotePlayback);

Ref<RemotePlayback> RemotePlayback::create(HTMLMediaElement& element)
{
    return adoptRef(*new RemotePlayback(element));
}

RemotePlayback::RemotePlayback(HTMLMediaElement& element)
    : WebCore::ActiveDOMObject(element.scriptExecutionContext())
    , m_mediaElement(makeWeakPtr(element))
    , m_eventQueue(MainThreadGenericEventQueue::create(*this))
{
    suspendIfNeeded();
}

RemotePlayback::~RemotePlayback()
{
}

void RemotePlayback::watchAvailability(Ref<RemotePlaybackAvailabilityCallback>&& callback, Ref<DeferredPromise>&& promise)
{
    // 6.2.1.3 Getting the remote playback devices availability information
    // https://w3c.github.io/remote-playback/#monitoring-the-list-of-available-remote-playback-devices
    // W3C Editor's Draft 15 July 2016

    // 1. Let promise be a new promise->
    // 2. Return promise, and run the following steps below:
    
    m_taskQueue.enqueueTask([this, callback = WTFMove(callback), promise = WTFMove(promise)] () mutable {
        // 3. If the disableRemotePlayback attribute is present for the media element, reject the promise with
        //    InvalidStateError and abort all the remaining steps.
        if (!m_mediaElement
            || m_mediaElement->hasAttributeWithoutSynchronization(HTMLNames::webkitwirelessvideoplaybackdisabledAttr)
            || m_mediaElement->hasAttributeWithoutSynchronization(HTMLNames::disableremoteplaybackAttr)) {
            WTFLogAlways("RemotePlayback::watchAvailability()::task - promise rejected");
            promise->reject(InvalidStateError);
            return;
        }

        // 4. If the user agent is unable to monitor the list of available remote playback devices for the entire
        //    lifetime of the browsing context (for instance, because the user has disabled this feature), then run
        //    the following steps in parallel:
        // 5. If the user agent is unable to continuously monitor the list of available remote playback devices but
        //    can do it for a short period of time when initiating remote playback, then:
        // NOTE: Unimplemented; all current ports can support continuous device monitoring

        // 6. Let callbackId be a number unique to the media element that will identify the callback.
        int32_t callbackId = ++m_nextId;

        // 7. Create a tuple (callbackId, callback) and add it to the set of availability callbacks for this media element.
        ASSERT(!m_callbackMap.contains(callbackId));
        m_callbackMap.add(callbackId, WTFMove(callback));

        // 8. Fulfill promise with the callbackId and run the following steps in parallel:
        promise->whenSettled([this, protectedThis = makeRefPtr(this), callbackId] {
            // 8.1 Queue a task to invoke the callback with the current availability for the media element.
            m_taskQueue.enqueueTask([this, callbackId] {
                auto foundCallback = m_callbackMap.find(callbackId);
                if (foundCallback == m_callbackMap.end())
                    return;

                if (updateAvailability() == UpdateResults::Unchanged)
                    foundCallback->value->handleEvent(m_available);
            });

            // 8.2 Run the algorithm to monitor the list of available remote playback devices.
            m_mediaElement->remoteHasAvailabilityCallbacksChanged();
        });
        promise->resolve<IDLLong>(callbackId);
    });
}

void RemotePlayback::cancelWatchAvailability(Optional<int32_t> id, Ref<DeferredPromise>&& promise)
{
    // 6.2.1.5 Stop observing remote playback devices availability
    // https://w3c.github.io/remote-playback/#stop-observing-remote-playback-devices-availability
    // W3C Editor's Draft 15 July 2016

    // 1. Let promise be a new promise->
    // 2. Return promise, and run the following steps below:

    m_taskQueue.enqueueTask([this, id = WTFMove(id), promise = WTFMove(promise)] {
        // 3. If the disableRemotePlayback attribute is present for the media element, reject promise with
        //    InvalidStateError and abort all the remaining steps.
        if (!m_mediaElement
            || m_mediaElement->hasAttributeWithoutSynchronization(HTMLNames::webkitwirelessvideoplaybackdisabledAttr)
            || m_mediaElement->hasAttributeWithoutSynchronization(HTMLNames::disableremoteplaybackAttr)) {
            promise->reject(InvalidStateError);
            return;
        }

        // 4. If the parameter id is undefined, clear the set of availability callbacks.
        if (!id)
            m_callbackMap.clear();
        else {
            // 5. Otherwise, if id matches the callbackId for any entry in the set of availability callbacks,
            //    remove the entry from the set.
            if (auto it = m_callbackMap.find(id.value()) != m_callbackMap.end())
                m_callbackMap.remove(it);
            // 6. Otherwise, reject promise with NotFoundError and abort all the remaining steps.
            else {
                promise->reject(NotFoundError);
                return;
            }
        }
        // 7. If the set of availability callbacks is now empty and there is no pending request to initiate remote
        //    playback, cancel any pending task to monitor the list of available remote playback devices for power
        //    saving purposes.
        m_mediaElement->remoteHasAvailabilityCallbacksChanged();

        // 8. Fulfill promise.
        promise->resolve();
    });
}

void RemotePlayback::prompt(Ref<DeferredPromise>&& promise)
{
    // 6.2.2 Prompt user for changing remote playback statee
    // https://w3c.github.io/remote-playback/#stop-observing-remote-playback-devices-availability
    // W3C Editor's Draft 15 July 2016

    // 1. Let promise be a new promise->
    // 2. Return promise, and run the following steps below:

    m_taskQueue.enqueueTask([this, promise = WTFMove(promise), processingUserGesture = UserGestureIndicator::processingUserGesture()] () mutable {
        // 3. If the disableRemotePlayback attribute is present for the media element, reject the promise with
        //    InvalidStateError and abort all the remaining steps.
        if (!m_mediaElement
            || m_mediaElement->hasAttributeWithoutSynchronization(HTMLNames::webkitwirelessvideoplaybackdisabledAttr)
            || m_mediaElement->hasAttributeWithoutSynchronization(HTMLNames::disableremoteplaybackAttr)) {
            promise->reject(InvalidStateError);
            return;
        }

        // 4. If there is already an unsettled promise from a previous call to prompt for the same media element
        //     or even for the same browsing context, the user agent may reject promise with an OperationError
        //     exception and abort all remaining steps.
        // NOTE: consider implementing

        // 5. OPTIONALLY, if the user agent knows a priori that showing the UI for this particular media element
        //    is not feasible, reject promise with a NotSupportedError and abort all remaining steps.
#if !PLATFORM(IOS)
        if (m_mediaElement->readyState() < HTMLMediaElementEnums::HAVE_METADATA) {
            promise->reject(NotSupportedError);
            return;
        }
#endif

        // 6. If the algorithm isn't allowed to show a popup, reject promise with an InvalidAccessError exception
        //    and abort these steps.
        if (!processingUserGesture) {
            promise->reject(InvalidAccessError);
            return;
        }

        // 7. If the user agent needs to show the list of available remote playback devices and is not monitoring
        //    the list of available remote playback devices, run the steps to monitor the list of available remote
        //    playback devices in parallel.
        // NOTE: Monitoring enabled by adding to m_promptPromises and calling remoteHasAvailabilityCallbacksChanged().
        //       Meanwhile, just update availability for step 9.
        updateAvailability();

        // 8. If the list of available remote playback devices is empty and will remain so before the request for
        //    user permission is completed, reject promise with a NotFoundError exception and abort all remaining steps.
        // NOTE: consider implementing (no network?)

        // 9. If the state is disconnected and availability for the media element is false, reject promise with a
        //    NotSupportedError exception and abort all remaining steps.
        if (m_state == State::Disconnected && !m_available) {
            promise->reject(NotSupportedError);
            return;
        }

        m_promptPromises.append(WTFMove(promise));
        m_mediaElement->remoteHasAvailabilityCallbacksChanged();
        m_mediaElement->webkitShowPlaybackTargetPicker();

        // NOTE: Steps 10-12 are implemented in the following methods:
    });
}

void RemotePlayback::shouldPlayToRemoteTargetChanged(bool shouldPlayToRemoteTarget)
{
    // 6.2.2 Prompt user for changing remote playback state [Ctd]
    // https://w3c.github.io/remote-playback/#prompt-user-for-changing-remote-playback-statee
    // W3C Editor's Draft 15 July 2016

    LOG(Media, "RemotePlayback::shouldPlayToRemoteTargetChanged(%p), shouldPlay(%d), promise count(%lu)", this, shouldPlayToRemoteTarget, m_promptPromises.size());

    // 10. If the user picked a remote playback device device to initiate remote playback with, the user agent
    //     must run the following steps:
    if (shouldPlayToRemoteTarget) {
        // 10.1 Set the state of the remote object to connecting.
        // 10.3 Queue a task to fire a simple event with the name connecting at the remote property of the media element.
        //      The event must not bubble, must not be cancelable, and has no default action.
        setState(State::Connecting);
    }

    for (auto& promise : std::exchange(m_promptPromises, { })) {
        // 10.2 Fulfill promise.
        // 10.4 Establish a connection with the remote playback device device for the media element.
        // NOTE: Implemented in establishConnection().

        // 11. Otherwise, if the user chose to disconnect from the remote playback device device, the user agent
        //     must run the following steps:
        // 11.1. Fulfill promise.
        // 11.2. Run the disconnect from remote playback device algorithm for the device.
        // NOTE: Implemented in disconnect().

        promise->resolve();
    }

    if (shouldPlayToRemoteTarget)
        establishConnection();
    else
        disconnect();

    m_mediaElement->remoteHasAvailabilityCallbacksChanged();
}

void RemotePlayback::setState(State state)
{
    if (m_state == state)
        return;

    m_state = state;

    switch (m_state) {
    case State::Connected:
        m_eventQueue->enqueueEvent(Event::create(eventNames().connectEvent, Event::CanBubble::No, Event::IsCancelable::No));
        break;
    case State::Connecting:
        m_eventQueue->enqueueEvent(Event::create(eventNames().connectingEvent, Event::CanBubble::No, Event::IsCancelable::No));
        break;
    case State::Disconnected:
        m_eventQueue->enqueueEvent(Event::create(eventNames().disconnectEvent, Event::CanBubble::No, Event::IsCancelable::No));
        break;
    }
}

void RemotePlayback::establishConnection()
{
    // 6.2.4 Establishing a connection with a remote playback device
    // https://w3c.github.io/remote-playback/#establishing-a-connection-with-a-remote-playback-device
    // W3C Editor's Draft 15 July 2016

    // 1. If the state of remote is not equal to connecting, abort all the remaining steps.
    if (m_state != State::Connecting)
        return;

    // 2. Request connection of remote to device. The implementation of this step is specific to the user agent.
    // NOTE: Handled in MediaPlayer.

    // NOTE: Continued in isPlayingToRemoteTargetChanged()
}

void RemotePlayback::disconnect()
{
    // 6.2.6 Disconnecting from remote playback device
    // https://w3c.github.io/remote-playback/#dfn-disconnect-from-remote-playback-device
    // W3C Editor's Draft 15 July 2016

    // 1. If the state of remote is disconnected, abort all remaining steps.
    if (m_state == State::Disconnected)
        return;

    // 2. Queue a task to run the following steps:
    m_taskQueue.enqueueTask([this] {
        // 2.1 Request disconnection of remote from the device. Implementation is user agent specific.
        // NOTE: Implemented by MediaPlayer::setWirelessPlaybackTarget()
        // 2.2 Change the remote's state to disconnected.
        // 2.3 Fire an event with the name disconnect at remote.
        setState(State::Disconnected);

        // 2.4 Synchronize the current media element state with the local playback state. Implementation is
        //     specific to user agent.
        // NOTE: Handled by the MediaPlayer
    });
}

RemotePlayback::UpdateResults RemotePlayback::updateAvailability()
{
    bool available = m_mediaElement ? m_mediaElement->mediaSession().hasWirelessPlaybackTargets() : false;
    if (available == m_available)
        return UpdateResults::Unchanged;

    availabilityChanged(available);
    return UpdateResults::Changed;
}

void RemotePlayback::playbackTargetPickerWasDismissed()
{
    // 6.2.2 Prompt user for changing remote playback state [Ctd]
    // https://w3c.github.io/remote-playback/#stop-observing-remote-playback-devices-availability
    // W3C Editor's Draft 15 July 2016

    // 12. Otherwise, the user is considered to deny permission to use the device, so reject promise with NotAllowedError
    // exception and hide the UI shown by the user agent
    ASSERT(!m_promptPromises.isEmpty());

    for (auto& promise : std::exchange(m_promptPromises, { }))
        promise->reject(NotAllowedError);
    m_mediaElement->remoteHasAvailabilityCallbacksChanged();
}

void RemotePlayback::isPlayingToRemoteTargetChanged(bool isPlayingToTarget)
{
    // 6.2.4 Establishing a connection with a remote playback device [Ctd]
    // https://w3c.github.io/remote-playback/#establishing-a-connection-with-a-remote-playback-device
    // W3C Editor's Draft 15 July 2016

    // 3. If connection completes successfully, queue a task to run the following steps:
    if (isPlayingToTarget) {
        // 3.1. Set the state of remote to connected.
        // 3.2. Fire a simple event named connect at remote.
        setState(State::Connected);

        // 3.3 Synchronize the current media element state with the remote playback state. Implementation is
        //     specific to user agent.
        // NOTE: Implemented by MediaPlayer.
        return;
    }

    // 4. If connection fails, queue a task to run the following steps:
    // 4.1. Set the remote playback state of remote to disconnected.
    // 4.2. Fire a simple event named disconnect at remote.
    setState(State::Disconnected);
}

bool RemotePlayback::hasAvailabilityCallbacks() const
{
    return !m_callbackMap.isEmpty() || !m_promptPromises.isEmpty();
}

void RemotePlayback::availabilityChanged(bool available)
{
    if (available == m_available)
        return;
    m_available = available;

    m_taskQueue.enqueueTask([this] {
        // Protect m_callbackMap against mutation while it's being iterated over.
        Vector<Ref<RemotePlaybackAvailabilityCallback>> callbacks;
        callbacks.reserveInitialCapacity(m_callbackMap.size());

        // Can't use copyValuesToVector() here because Ref<> has a deleted assignment operator.
        for (auto& callback : m_callbackMap.values())
            callbacks.uncheckedAppend(callback.copyRef());
        for (auto& callback : callbacks)
            callback->handleEvent(m_available);
    });
}

void RemotePlayback::invalidate()
{
    m_mediaElement = nullptr;
}

const char* RemotePlayback::activeDOMObjectName() const
{
    return "RemotePlayback";
}

void RemotePlayback::stop()
{
    m_taskQueue.close();
    m_eventQueue->close();
}

}

#endif // ENABLE(WIRELESS_PLAYBACK_TARGET)
