/*
 * Copyright (C) 2011 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 COMPUTER, 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 COMPUTER, 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 "core/html/MediaController.h"

#include "bindings/v8/ExceptionMessages.h"
#include "bindings/v8/ExceptionState.h"
#include "bindings/v8/ExceptionStatePlaceholder.h"
#include "core/dom/ExceptionCode.h"
#include "core/html/HTMLMediaElement.h"
#include "core/html/TimeRanges.h"
#include "platform/Clock.h"
#include "wtf/CurrentTime.h"
#include "wtf/StdLibExtras.h"
#include "wtf/text/AtomicString.h"

using namespace WebCore;
using namespace std;

PassRefPtr<MediaController> MediaController::create(ExecutionContext* context)
{
    return adoptRef(new MediaController(context));
}

MediaController::MediaController(ExecutionContext* context)
    : m_paused(false)
    , m_defaultPlaybackRate(1)
    , m_volume(1)
    , m_position(MediaPlayer::invalidTime())
    , m_muted(false)
    , m_readyState(HAVE_NOTHING)
    , m_playbackState(WAITING)
    , m_asyncEventTimer(this, &MediaController::asyncEventTimerFired)
    , m_clearPositionTimer(this, &MediaController::clearPositionTimerFired)
    , m_closedCaptionsVisible(false)
    , m_clock(Clock::create())
    , m_executionContext(context)
    , m_timeupdateTimer(this, &MediaController::timeupdateTimerFired)
    , m_previousTimeupdateTime(0)
{
    ScriptWrappable::init(this);
}

MediaController::~MediaController()
{
}

void MediaController::addMediaElement(HTMLMediaElement* element)
{
    ASSERT(element);
    ASSERT(!m_mediaElements.contains(element));

    m_mediaElements.append(element);
    bringElementUpToSpeed(element);
}

void MediaController::removeMediaElement(HTMLMediaElement* element)
{
    ASSERT(element);
    ASSERT(m_mediaElements.contains(element));
    m_mediaElements.remove(m_mediaElements.find(element));
}

bool MediaController::containsMediaElement(HTMLMediaElement* element) const
{
    return m_mediaElements.contains(element);
}

PassRefPtr<TimeRanges> MediaController::buffered() const
{
    if (m_mediaElements.isEmpty())
        return TimeRanges::create();

    // The buffered attribute must return a new static normalized TimeRanges object that represents
    // the intersection of the ranges of the media resources of the slaved media elements that the
    // user agent has buffered, at the time the attribute is evaluated.
    RefPtr<TimeRanges> bufferedRanges = m_mediaElements.first()->buffered();
    for (size_t index = 1; index < m_mediaElements.size(); ++index)
        bufferedRanges->intersectWith(m_mediaElements[index]->buffered().get());
    return bufferedRanges;
}

PassRefPtr<TimeRanges> MediaController::seekable() const
{
    if (m_mediaElements.isEmpty())
        return TimeRanges::create();

    // The seekable attribute must return a new static normalized TimeRanges object that represents
    // the intersection of the ranges of the media resources of the slaved media elements that the
    // user agent is able to seek to, at the time the attribute is evaluated.
    RefPtr<TimeRanges> seekableRanges = m_mediaElements.first()->seekable();
    for (size_t index = 1; index < m_mediaElements.size(); ++index)
        seekableRanges->intersectWith(m_mediaElements[index]->seekable().get());
    return seekableRanges;
}

PassRefPtr<TimeRanges> MediaController::played()
{
    if (m_mediaElements.isEmpty())
        return TimeRanges::create();

    // The played attribute must return a new static normalized TimeRanges object that represents
    // the union of the ranges of the media resources of the slaved media elements that the
    // user agent has so far rendered, at the time the attribute is evaluated.
    RefPtr<TimeRanges> playedRanges = m_mediaElements.first()->played();
    for (size_t index = 1; index < m_mediaElements.size(); ++index)
        playedRanges->unionWith(m_mediaElements[index]->played().get());
    return playedRanges;
}

double MediaController::duration() const
{
    // FIXME: Investigate caching the maximum duration and only updating the cached value
    // when the slaved media elements' durations change.
    double maxDuration = 0;
    for (size_t index = 0; index < m_mediaElements.size(); ++index) {
        double duration = m_mediaElements[index]->duration();
        if (std::isnan(duration))
            continue;
        maxDuration = max(maxDuration, duration);
    }
    return maxDuration;
}

double MediaController::currentTime() const
{
    if (m_mediaElements.isEmpty())
        return 0;

    if (m_position == MediaPlayer::invalidTime()) {
        // Some clocks may return times outside the range of [0..duration].
        m_position = max(0.0, min(duration(), m_clock->currentTime()));
        m_clearPositionTimer.startOneShot(0);
    }

    return m_position;
}

void MediaController::setCurrentTime(double time, ExceptionState& exceptionState)
{
    // When the user agent is to seek the media controller to a particular new playback position,
    // it must follow these steps:
    // If the new playback position is less than zero, then set it to zero.
    time = max(0.0, time);

    // If the new playback position is greater than the media controller duration, then set it
    // to the media controller duration.
    time = min(time, duration());

    // Set the media controller position to the new playback position.
    m_clock->setCurrentTime(time);

    // Seek each slaved media element to the new playback position relative to the media element timeline.
    for (size_t index = 0; index < m_mediaElements.size(); ++index)
        m_mediaElements[index]->seek(time, exceptionState);

    scheduleTimeupdateEvent();
}

void MediaController::unpause()
{
    // When the unpause() method is invoked, if the MediaController is a paused media controller,
    if (!m_paused)
        return;

    // the user agent must change the MediaController into a playing media controller,
    m_paused = false;
    // queue a task to fire a simple event named play at the MediaController,
    scheduleEvent(EventTypeNames::play);
    // and then report the controller state of the MediaController.
    reportControllerState();
}

void MediaController::play()
{
    // When the play() method is invoked, the user agent must invoke the play method of each
    // slaved media element in turn,
    for (size_t index = 0; index < m_mediaElements.size(); ++index)
        m_mediaElements[index]->play();

    // and then invoke the unpause method of the MediaController.
    unpause();
}

void MediaController::pause()
{
    // When the pause() method is invoked, if the MediaController is a playing media controller,
    if (m_paused)
        return;

    // then the user agent must change the MediaController into a paused media controller,
    m_paused = true;
    // queue a task to fire a simple event named pause at the MediaController,
    scheduleEvent(EventTypeNames::pause);
    // and then report the controller state of the MediaController.
    reportControllerState();
}

void MediaController::setDefaultPlaybackRate(double rate)
{
    if (m_defaultPlaybackRate == rate)
        return;

    // The defaultPlaybackRate attribute, on setting, must set the MediaController's media controller
    // default playback rate to the new value,
    m_defaultPlaybackRate = rate;

    // then queue a task to fire a simple event named ratechange at the MediaController.
    scheduleEvent(EventTypeNames::ratechange);
}

double MediaController::playbackRate() const
{
    return m_clock->playRate();
}

void MediaController::setPlaybackRate(double rate)
{
    if (m_clock->playRate() == rate)
        return;

    // The playbackRate attribute, on setting, must set the MediaController's media controller
    // playback rate to the new value,
    m_clock->setPlayRate(rate);

    for (size_t index = 0; index < m_mediaElements.size(); ++index)
        m_mediaElements[index]->updatePlaybackRate();

    // then queue a task to fire a simple event named ratechange at the MediaController.
    scheduleEvent(EventTypeNames::ratechange);
}

void MediaController::setVolume(double level, ExceptionState& exceptionState)
{
    if (m_volume == level)
        return;

    // If the new value is outside the range 0.0 to 1.0 inclusive, then, on setting, an
    // IndexSizeError exception must be raised instead.
    if (level < 0 || level > 1) {
        exceptionState.throwDOMException(IndexSizeError, ExceptionMessages::failedToSet("volume", "MediaController", "The value provided (" + String::number(level) + ") is not in the range [0.0, 1.0]."));
        return;
    }

    // The volume attribute, on setting, if the new value is in the range 0.0 to 1.0 inclusive,
    // must set the MediaController's media controller volume multiplier to the new value
    m_volume = level;

    // and queue a task to fire a simple event named volumechange at the MediaController.
    scheduleEvent(EventTypeNames::volumechange);

    for (size_t index = 0; index < m_mediaElements.size(); ++index)
        m_mediaElements[index]->updateVolume();
}

void MediaController::setMuted(bool flag)
{
    if (m_muted == flag)
        return;

    // The muted attribute, on setting, must set the MediaController's media controller mute override
    // to the new value
    m_muted = flag;

    // and queue a task to fire a simple event named volumechange at the MediaController.
    scheduleEvent(EventTypeNames::volumechange);

    for (size_t index = 0; index < m_mediaElements.size(); ++index)
        m_mediaElements[index]->updateVolume();
}

static const AtomicString& playbackStateWaiting()
{
    DEFINE_STATIC_LOCAL(AtomicString, waiting, ("waiting", AtomicString::ConstructFromLiteral));
    return waiting;
}

static const AtomicString& playbackStatePlaying()
{
    DEFINE_STATIC_LOCAL(AtomicString, playing, ("playing", AtomicString::ConstructFromLiteral));
    return playing;
}

static const AtomicString& playbackStateEnded()
{
    DEFINE_STATIC_LOCAL(AtomicString, ended, ("ended", AtomicString::ConstructFromLiteral));
    return ended;
}

const AtomicString& MediaController::playbackState() const
{
    switch (m_playbackState) {
    case WAITING:
        return playbackStateWaiting();
    case PLAYING:
        return playbackStatePlaying();
    case ENDED:
        return playbackStateEnded();
    default:
        ASSERT_NOT_REACHED();
        return nullAtom;
    }
}

void MediaController::reportControllerState()
{
    updateReadyState();
    updatePlaybackState();
}

static AtomicString eventNameForReadyState(MediaControllerInterface::ReadyState state)
{
    switch (state) {
    case MediaControllerInterface::HAVE_NOTHING:
        return EventTypeNames::emptied;
    case MediaControllerInterface::HAVE_METADATA:
        return EventTypeNames::loadedmetadata;
    case MediaControllerInterface::HAVE_CURRENT_DATA:
        return EventTypeNames::loadeddata;
    case MediaControllerInterface::HAVE_FUTURE_DATA:
        return EventTypeNames::canplay;
    case MediaControllerInterface::HAVE_ENOUGH_DATA:
        return EventTypeNames::canplaythrough;
    default:
        ASSERT_NOT_REACHED();
        return nullAtom;
    }
}

void MediaController::updateReadyState()
{
    ReadyState oldReadyState = m_readyState;
    ReadyState newReadyState;

    if (m_mediaElements.isEmpty()) {
        // If the MediaController has no slaved media elements, let new readiness state be 0.
        newReadyState = HAVE_NOTHING;
    } else {
        // Otherwise, let it have the lowest value of the readyState IDL attributes of all of its
        // slaved media elements.
        newReadyState = m_mediaElements.first()->readyState();
        for (size_t index = 1; index < m_mediaElements.size(); ++index)
            newReadyState = min(newReadyState, m_mediaElements[index]->readyState());
    }

    if (newReadyState == oldReadyState)
        return;

    // If the MediaController's most recently reported readiness state is greater than new readiness
    // state then queue a task to fire a simple event at the MediaController object, whose name is the
    // event name corresponding to the value of new readiness state given in the table below. [omitted]
    if (oldReadyState > newReadyState) {
        scheduleEvent(eventNameForReadyState(newReadyState));
        return;
    }

    // If the MediaController's most recently reported readiness state is less than the new readiness
    // state, then run these substeps:
    // 1. Let next state be the MediaController's most recently reported readiness state.
    ReadyState nextState = oldReadyState;
    do {
        // 2. Loop: Increment next state by one.
        nextState = static_cast<ReadyState>(nextState + 1);
        // 3. Queue a task to fire a simple event at the MediaController object, whose name is the
        // event name corresponding to the value of next state given in the table below. [omitted]
        scheduleEvent(eventNameForReadyState(nextState));
        // If next state is less than new readiness state, then return to the step labeled loop
    } while (nextState < newReadyState);

    // Let the MediaController's most recently reported readiness state be new readiness state.
    m_readyState = newReadyState;
}

void MediaController::updatePlaybackState()
{
    PlaybackState oldPlaybackState = m_playbackState;
    PlaybackState newPlaybackState;

    // Initialize new playback state by setting it to the state given for the first matching
    // condition from the following list:
    if (m_mediaElements.isEmpty()) {
        // If the MediaController has no slaved media elements
        // Let new playback state be waiting.
        newPlaybackState = WAITING;
    } else if (hasEnded()) {
        // If all of the MediaController's slaved media elements have ended playback and the media
        // controller playback rate is positive or zero
        // Let new playback state be ended.
        newPlaybackState = ENDED;
    } else if (isBlocked()) {
        // If the MediaController is a blocked media controller
        // Let new playback state be waiting.
        newPlaybackState = WAITING;
    } else {
        // Otherwise
        // Let new playback state be playing.
        newPlaybackState = PLAYING;
    }

    // If the MediaController's most recently reported playback state is not equal to new playback state
    if (newPlaybackState == oldPlaybackState)
        return;

    // and the new playback state is ended,
    if (newPlaybackState == ENDED) {
        // then queue a task that, if the MediaController object is a playing media controller, and
        // all of the MediaController's slaved media elements have still ended playback, and the
        // media controller playback rate is still positive or zero,
        if (!m_paused && hasEnded()) {
            // changes the MediaController object to a paused media controller
            m_paused = true;

            // and then fires a simple event named pause at the MediaController object.
            scheduleEvent(EventTypeNames::pause);
        }
    }

    // If the MediaController's most recently reported playback state is not equal to new playback state
    // then queue a task to fire a simple event at the MediaController object, whose name is playing
    // if new playback state is playing, ended if new playback state is ended, and waiting otherwise.
    AtomicString eventName;
    switch (newPlaybackState) {
    case WAITING:
        eventName = EventTypeNames::waiting;
        m_clock->stop();
        m_timeupdateTimer.stop();
        break;
    case ENDED:
        eventName = EventTypeNames::ended;
        m_clock->stop();
        m_timeupdateTimer.stop();
        break;
    case PLAYING:
        eventName = EventTypeNames::playing;
        m_clock->start();
        startTimeupdateTimer();
        break;
    default:
        ASSERT_NOT_REACHED();
    }
    scheduleEvent(eventName);

    // Let the MediaController's most recently reported playback state be new playback state.
    m_playbackState = newPlaybackState;

    updateMediaElements();
}

void MediaController::updateMediaElements()
{
    for (size_t index = 0; index < m_mediaElements.size(); ++index)
        m_mediaElements[index]->updatePlayState();
}

void MediaController::bringElementUpToSpeed(HTMLMediaElement* element)
{
    ASSERT(element);
    ASSERT(m_mediaElements.contains(element));

    // When the user agent is to bring a media element up to speed with its new media controller,
    // it must seek that media element to the MediaController's media controller position relative
    // to the media element's timeline.
    element->seek(currentTime(), IGNORE_EXCEPTION);
}

bool MediaController::isBlocked() const
{
    // A MediaController is a blocked media controller if the MediaController is a paused media
    // controller,
    if (m_paused)
        return true;

    if (m_mediaElements.isEmpty())
        return false;

    bool allPaused = true;
    for (size_t index = 0; index < m_mediaElements.size(); ++index) {
        HTMLMediaElement* element = m_mediaElements[index];
        //  or if any of its slaved media elements are blocked media elements,
        if (element->isBlocked())
            return true;

        // or if any of its slaved media elements whose autoplaying flag is true still have their
        // paused attribute set to true,
        if (element->isAutoplaying() && element->paused())
            return true;

        if (!element->paused())
            allPaused = false;
    }

    // or if all of its slaved media elements have their paused attribute set to true.
    return allPaused;
}

bool MediaController::hasEnded() const
{
    // If the ... media controller playback rate is positive or zero
    if (m_clock->playRate() < 0)
        return false;

    // [and] all of the MediaController's slaved media elements have ended playback ... let new
    // playback state be ended.
    if (m_mediaElements.isEmpty())
        return false;

    bool allHaveEnded = true;
    for (size_t index = 0; index < m_mediaElements.size(); ++index) {
        if (!m_mediaElements[index]->ended())
            allHaveEnded = false;
    }
    return allHaveEnded;
}

void MediaController::scheduleEvent(const AtomicString& eventName)
{
    m_pendingEvents.append(Event::createCancelable(eventName));
    if (!m_asyncEventTimer.isActive())
        m_asyncEventTimer.startOneShot(0);
}

void MediaController::asyncEventTimerFired(Timer<MediaController>*)
{
    Vector<RefPtr<Event> > pendingEvents;

    m_pendingEvents.swap(pendingEvents);
    size_t count = pendingEvents.size();
    for (size_t index = 0; index < count; ++index)
        dispatchEvent(pendingEvents[index].release(), IGNORE_EXCEPTION);
}

void MediaController::clearPositionTimerFired(Timer<MediaController>*)
{
    m_position = MediaPlayer::invalidTime();
}

bool MediaController::hasAudio() const
{
    for (size_t index = 0; index < m_mediaElements.size(); ++index) {
        if (m_mediaElements[index]->hasAudio())
            return true;
    }
    return false;
}

bool MediaController::hasVideo() const
{
    for (size_t index = 0; index < m_mediaElements.size(); ++index) {
        if (m_mediaElements[index]->hasVideo())
            return true;
    }
    return false;
}

bool MediaController::hasClosedCaptions() const
{
    for (size_t index = 0; index < m_mediaElements.size(); ++index) {
        if (m_mediaElements[index]->hasClosedCaptions())
            return true;
    }
    return false;
}

void MediaController::setClosedCaptionsVisible(bool visible)
{
    m_closedCaptionsVisible = visible;
    for (size_t index = 0; index < m_mediaElements.size(); ++index)
        m_mediaElements[index]->setClosedCaptionsVisible(visible);
}

void MediaController::beginScrubbing()
{
    for (size_t index = 0; index < m_mediaElements.size(); ++index)
        m_mediaElements[index]->beginScrubbing();
    if (m_playbackState == PLAYING)
        m_clock->stop();
}

void MediaController::endScrubbing()
{
    for (size_t index = 0; index < m_mediaElements.size(); ++index)
        m_mediaElements[index]->endScrubbing();
    if (m_playbackState == PLAYING)
        m_clock->start();
}

bool MediaController::canPlay() const
{
    if (m_paused)
        return true;

    for (size_t index = 0; index < m_mediaElements.size(); ++index) {
        if (!m_mediaElements[index]->canPlay())
            return false;
    }
    return true;
}

bool MediaController::hasCurrentSrc() const
{
    for (size_t index = 0; index < m_mediaElements.size(); ++index) {
        if (!m_mediaElements[index]->hasCurrentSrc())
            return false;
    }
    return true;
}

const AtomicString& MediaController::interfaceName() const
{
    return EventTargetNames::MediaController;
}

// The spec says to fire periodic timeupdate events (those sent while playing) every
// "15 to 250ms", we choose the slowest frequency
static const double maxTimeupdateEventFrequency = 0.25;

void MediaController::startTimeupdateTimer()
{
    if (m_timeupdateTimer.isActive())
        return;

    m_timeupdateTimer.startRepeating(maxTimeupdateEventFrequency);
}

void MediaController::timeupdateTimerFired(Timer<MediaController>*)
{
    scheduleTimeupdateEvent();
}

void MediaController::scheduleTimeupdateEvent()
{
    double now = WTF::currentTime();
    double timedelta = now - m_previousTimeupdateTime;

    if (timedelta < maxTimeupdateEventFrequency)
        return;

    scheduleEvent(EventTypeNames::timeupdate);
    m_previousTimeupdateTime = now;
}
