/*
 * Copyright (C) 2011, 2012 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"

#if ENABLE(VIDEO_TRACK)

#include "TrackListBase.h"

#include "EventNames.h"
#include "HTMLMediaElement.h"
#include "ScriptExecutionContext.h"
#include "TrackEvent.h"
#include <wtf/IsoMallocInlines.h>

namespace WebCore {

WTF_MAKE_ISO_ALLOCATED_IMPL(TrackListBase);

TrackListBase::TrackListBase(HTMLMediaElement* element, ScriptExecutionContext* context)
    : ActiveDOMObject(context)
    , m_element(element)
    , m_asyncEventQueue(MainThreadGenericEventQueue::create(*this))
{
    ASSERT(!context || is<Document>(context));
    suspendIfNeeded();
}

TrackListBase::~TrackListBase()
{
    clearElement();
}

void TrackListBase::clearElement()
{
    m_element = nullptr;
    for (auto& track : m_inbandTracks) {
        track->setMediaElement(nullptr);
        track->clearClient();
    }
}

Element* TrackListBase::element() const
{
    return m_element;
}

unsigned TrackListBase::length() const
{
    return m_inbandTracks.size();
}

void TrackListBase::remove(TrackBase& track, bool scheduleEvent)
{
    size_t index = m_inbandTracks.find(&track);
    if (index == notFound)
        return;

    if (track.mediaElement()) {
        ASSERT(track.mediaElement() == m_element);
        track.setMediaElement(nullptr);
    }

    Ref<TrackBase> trackRef = *m_inbandTracks[index];

    m_inbandTracks.remove(index);

    if (scheduleEvent)
        scheduleRemoveTrackEvent(WTFMove(trackRef));
}

bool TrackListBase::contains(TrackBase& track) const
{
    return m_inbandTracks.find(&track) != notFound;
}

void TrackListBase::scheduleTrackEvent(const AtomString& eventName, Ref<TrackBase>&& track)
{
    m_asyncEventQueue->enqueueEvent(TrackEvent::create(eventName, Event::CanBubble::No, Event::IsCancelable::No, WTFMove(track)));
}

void TrackListBase::scheduleAddTrackEvent(Ref<TrackBase>&& track)
{
    // 4.8.10.5 Loading the media resource
    // ...
    // Fire a trusted event with the name addtrack, that does not bubble and is
    // not cancelable, and that uses the TrackEvent interface, with the track
    // attribute initialized to the new AudioTrack object, at this
    // AudioTrackList object.
    // ...
    // Fire a trusted event with the name addtrack, that does not bubble and is
    // not cancelable, and that uses the TrackEvent interface, with the track
    // attribute initialized to the new VideoTrack object, at this
    // VideoTrackList object.

    // 4.8.10.12.3 Sourcing out-of-band text tracks
    // 4.8.10.12.4 Text track API
    // ... then queue a task to fire an event with the name addtrack, that does not
    // bubble and is not cancelable, and that uses the TrackEvent interface, with
    // the track attribute initialized to the text track's TextTrack object, at
    // the media element's textTracks attribute's TextTrackList object.
    scheduleTrackEvent(eventNames().addtrackEvent, WTFMove(track));
}

void TrackListBase::scheduleRemoveTrackEvent(Ref<TrackBase>&& track)
{
    // 4.8.10.6 Offsets into the media resource
    // If at any time the user agent learns that an audio or video track has
    // ended and all media data relating to that track corresponds to parts of
    // the media timeline that are before the earliest possible position, the
    // user agent may queue a task to remove the track from the audioTracks
    // attribute's AudioTrackList object or the videoTracks attribute's
    // VideoTrackList object as appropriate and then fire a trusted event
    // with the name removetrack, that does not bubble and is not cancelable,
    // and that uses the TrackEvent interface, with the track attribute
    // initialized to the AudioTrack or VideoTrack object representing the
    // track, at the media element's aforementioned AudioTrackList or
    // VideoTrackList object.

    // 4.8.10.12.3 Sourcing out-of-band text tracks
    // When a track element's parent element changes and the old parent was a
    // media element, then the user agent must remove the track element's
    // corresponding text track from the media element's list of text tracks,
    // and then queue a task to fire a trusted event with the name removetrack,
    // that does not bubble and is not cancelable, and that uses the TrackEvent
    // interface, with the track attribute initialized to the text track's
    // TextTrack object, at the media element's textTracks attribute's
    // TextTrackList object.
    scheduleTrackEvent(eventNames().removetrackEvent, WTFMove(track));
}

void TrackListBase::scheduleChangeEvent()
{
    // 4.8.10.6 Offsets into the media resource
    // Whenever an audio track in an AudioTrackList is enabled or disabled, the
    // user agent must queue a task to fire a simple event named change at the
    // AudioTrackList object.
    // ...
    // Whenever a track in a VideoTrackList that was previously not selected is
    // selected, the user agent must queue a task to fire a simple event named
    // change at the VideoTrackList object.
    m_asyncEventQueue->enqueueEvent(Event::create(eventNames().changeEvent, Event::CanBubble::No, Event::IsCancelable::No));
}

bool TrackListBase::isChangeEventScheduled() const
{
    return m_asyncEventQueue->hasPendingEventsOfType(eventNames().changeEvent);
}

bool TrackListBase::isAnyTrackEnabled() const
{
    for (auto& track : m_inbandTracks) {
        if (track->enabled())
            return true;
    }
    return false;
}

} // namespace WebCore

#endif
