/*
 * Copyright (C) 2011 Google Inc. All rights reserved.
 * Copyright (C) 2011, 2012 Ericsson AB. 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 "modules/mediastream/MediaStream.h"

#include "bindings/core/v8/ExceptionState.h"
#include "core/dom/ExceptionCode.h"
#include "core/frame/Deprecation.h"
#include "modules/mediastream/MediaStreamRegistry.h"
#include "modules/mediastream/MediaStreamTrackEvent.h"
#include "platform/mediastream/MediaStreamCenter.h"
#include "platform/mediastream/MediaStreamSource.h"

namespace blink {

static bool containsSource(MediaStreamTrackVector& trackVector,
                           MediaStreamSource* source) {
  for (size_t i = 0; i < trackVector.size(); ++i) {
    if (source->id() == trackVector[i]->component()->source()->id())
      return true;
  }
  return false;
}

static void processTrack(MediaStreamTrack* track,
                         MediaStreamTrackVector& trackVector) {
  if (track->ended())
    return;

  MediaStreamSource* source = track->component()->source();
  if (!containsSource(trackVector, source))
    trackVector.append(track);
}

MediaStream* MediaStream::create(ExecutionContext* context) {
  MediaStreamTrackVector audioTracks;
  MediaStreamTrackVector videoTracks;

  return new MediaStream(context, audioTracks, videoTracks);
}

MediaStream* MediaStream::create(ExecutionContext* context,
                                 MediaStream* stream) {
  DCHECK(stream);

  MediaStreamTrackVector audioTracks;
  MediaStreamTrackVector videoTracks;

  for (size_t i = 0; i < stream->m_audioTracks.size(); ++i)
    processTrack(stream->m_audioTracks[i].get(), audioTracks);

  for (size_t i = 0; i < stream->m_videoTracks.size(); ++i)
    processTrack(stream->m_videoTracks[i].get(), videoTracks);

  return new MediaStream(context, audioTracks, videoTracks);
}

MediaStream* MediaStream::create(ExecutionContext* context,
                                 const MediaStreamTrackVector& tracks) {
  MediaStreamTrackVector audioTracks;
  MediaStreamTrackVector videoTracks;

  for (size_t i = 0; i < tracks.size(); ++i)
    processTrack(tracks[i].get(),
                 tracks[i]->kind() == "audio" ? audioTracks : videoTracks);

  return new MediaStream(context, audioTracks, videoTracks);
}

MediaStream* MediaStream::create(ExecutionContext* context,
                                 MediaStreamDescriptor* streamDescriptor) {
  return new MediaStream(context, streamDescriptor);
}

MediaStream::MediaStream(ExecutionContext* context,
                         MediaStreamDescriptor* streamDescriptor)
    : ContextLifecycleObserver(context),
      m_stopped(false),
      m_descriptor(streamDescriptor),
      m_scheduledEventTimer(this, &MediaStream::scheduledEventTimerFired) {
  m_descriptor->setClient(this);

  size_t numberOfAudioTracks = m_descriptor->numberOfAudioComponents();
  m_audioTracks.reserveCapacity(numberOfAudioTracks);
  for (size_t i = 0; i < numberOfAudioTracks; i++) {
    MediaStreamTrack* newTrack =
        MediaStreamTrack::create(context, m_descriptor->audioComponent(i));
    newTrack->registerMediaStream(this);
    m_audioTracks.append(newTrack);
  }

  size_t numberOfVideoTracks = m_descriptor->numberOfVideoComponents();
  m_videoTracks.reserveCapacity(numberOfVideoTracks);
  for (size_t i = 0; i < numberOfVideoTracks; i++) {
    MediaStreamTrack* newTrack =
        MediaStreamTrack::create(context, m_descriptor->videoComponent(i));
    newTrack->registerMediaStream(this);
    m_videoTracks.append(newTrack);
  }

  if (emptyOrOnlyEndedTracks()) {
    m_descriptor->setActive(false);
  }
}

MediaStream::MediaStream(ExecutionContext* context,
                         const MediaStreamTrackVector& audioTracks,
                         const MediaStreamTrackVector& videoTracks)
    : ContextLifecycleObserver(context),
      m_stopped(false),
      m_scheduledEventTimer(this, &MediaStream::scheduledEventTimerFired) {
  MediaStreamComponentVector audioComponents;
  MediaStreamComponentVector videoComponents;

  MediaStreamTrackVector::const_iterator iter;
  for (iter = audioTracks.begin(); iter != audioTracks.end(); ++iter) {
    (*iter)->registerMediaStream(this);
    audioComponents.append((*iter)->component());
  }
  for (iter = videoTracks.begin(); iter != videoTracks.end(); ++iter) {
    (*iter)->registerMediaStream(this);
    videoComponents.append((*iter)->component());
  }

  m_descriptor =
      MediaStreamDescriptor::create(audioComponents, videoComponents);
  m_descriptor->setClient(this);
  MediaStreamCenter::instance().didCreateMediaStream(m_descriptor);

  m_audioTracks = audioTracks;
  m_videoTracks = videoTracks;
  if (emptyOrOnlyEndedTracks()) {
    m_descriptor->setActive(false);
  }
}

MediaStream::~MediaStream() {}

bool MediaStream::emptyOrOnlyEndedTracks() {
  if (!m_audioTracks.size() && !m_videoTracks.size()) {
    return true;
  }
  for (MediaStreamTrackVector::iterator iter = m_audioTracks.begin();
       iter != m_audioTracks.end(); ++iter) {
    if (!iter->get()->ended())
      return false;
  }
  for (MediaStreamTrackVector::iterator iter = m_videoTracks.begin();
       iter != m_videoTracks.end(); ++iter) {
    if (!iter->get()->ended())
      return false;
  }
  return true;
}

MediaStreamTrackVector MediaStream::getTracks() {
  MediaStreamTrackVector tracks;
  for (MediaStreamTrackVector::iterator iter = m_audioTracks.begin();
       iter != m_audioTracks.end(); ++iter)
    tracks.append(iter->get());
  for (MediaStreamTrackVector::iterator iter = m_videoTracks.begin();
       iter != m_videoTracks.end(); ++iter)
    tracks.append(iter->get());
  return tracks;
}

void MediaStream::addTrack(MediaStreamTrack* track,
                           ExceptionState& exceptionState) {
  if (!track) {
    exceptionState.throwDOMException(
        TypeMismatchError, "The MediaStreamTrack provided is invalid.");
    return;
  }

  if (getTrackById(track->id()))
    return;

  switch (track->component()->source()->type()) {
    case MediaStreamSource::TypeAudio:
      m_audioTracks.append(track);
      break;
    case MediaStreamSource::TypeVideo:
      m_videoTracks.append(track);
      break;
  }
  track->registerMediaStream(this);
  m_descriptor->addComponent(track->component());

  if (!active() && !track->ended()) {
    m_descriptor->setActive(true);
    scheduleDispatchEvent(Event::create(EventTypeNames::active));
  }

  MediaStreamCenter::instance().didAddMediaStreamTrack(m_descriptor,
                                                       track->component());
}

void MediaStream::removeTrack(MediaStreamTrack* track,
                              ExceptionState& exceptionState) {
  if (!track) {
    exceptionState.throwDOMException(
        TypeMismatchError, "The MediaStreamTrack provided is invalid.");
    return;
  }

  size_t pos = kNotFound;
  switch (track->component()->source()->type()) {
    case MediaStreamSource::TypeAudio:
      pos = m_audioTracks.find(track);
      if (pos != kNotFound)
        m_audioTracks.remove(pos);
      break;
    case MediaStreamSource::TypeVideo:
      pos = m_videoTracks.find(track);
      if (pos != kNotFound)
        m_videoTracks.remove(pos);
      break;
  }

  if (pos == kNotFound)
    return;
  track->unregisterMediaStream(this);
  m_descriptor->removeComponent(track->component());

  if (active() && emptyOrOnlyEndedTracks()) {
    m_descriptor->setActive(false);
    scheduleDispatchEvent(Event::create(EventTypeNames::inactive));
  }

  MediaStreamCenter::instance().didRemoveMediaStreamTrack(m_descriptor,
                                                          track->component());
}

MediaStreamTrack* MediaStream::getTrackById(String id) {
  for (MediaStreamTrackVector::iterator iter = m_audioTracks.begin();
       iter != m_audioTracks.end(); ++iter) {
    if ((*iter)->id() == id)
      return iter->get();
  }

  for (MediaStreamTrackVector::iterator iter = m_videoTracks.begin();
       iter != m_videoTracks.end(); ++iter) {
    if ((*iter)->id() == id)
      return iter->get();
  }

  return 0;
}

MediaStream* MediaStream::clone(ExecutionContext* context) {
  MediaStreamTrackVector tracks;
  for (MediaStreamTrackVector::iterator iter = m_audioTracks.begin();
       iter != m_audioTracks.end(); ++iter)
    tracks.append((*iter)->clone(context));
  for (MediaStreamTrackVector::iterator iter = m_videoTracks.begin();
       iter != m_videoTracks.end(); ++iter)
    tracks.append((*iter)->clone(context));
  return MediaStream::create(context, tracks);
}

void MediaStream::trackEnded() {
  for (MediaStreamTrackVector::iterator iter = m_audioTracks.begin();
       iter != m_audioTracks.end(); ++iter) {
    if (!(*iter)->ended())
      return;
  }

  for (MediaStreamTrackVector::iterator iter = m_videoTracks.begin();
       iter != m_videoTracks.end(); ++iter) {
    if (!(*iter)->ended())
      return;
  }

  streamEnded();
}

void MediaStream::streamEnded() {
  if (m_stopped)
    return;

  if (active()) {
    m_descriptor->setActive(false);
    scheduleDispatchEvent(Event::create(EventTypeNames::inactive));
  }
}

bool MediaStream::addEventListenerInternal(
    const AtomicString& eventType,
    EventListener* listener,
    const AddEventListenerOptionsResolved& options) {
  if (eventType == EventTypeNames::active)
    UseCounter::count(getExecutionContext(), UseCounter::MediaStreamOnActive);
  else if (eventType == EventTypeNames::inactive)
    UseCounter::count(getExecutionContext(), UseCounter::MediaStreamOnInactive);

  return EventTargetWithInlineData::addEventListenerInternal(eventType,
                                                             listener, options);
}

void MediaStream::contextDestroyed() {
  ContextLifecycleObserver::contextDestroyed();
  m_stopped = true;
}

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

ExecutionContext* MediaStream::getExecutionContext() const {
  return ContextLifecycleObserver::getExecutionContext();
}

void MediaStream::addRemoteTrack(MediaStreamComponent* component) {
  DCHECK(component);
  if (m_stopped)
    return;

  MediaStreamTrack* track =
      MediaStreamTrack::create(getExecutionContext(), component);
  switch (component->source()->type()) {
    case MediaStreamSource::TypeAudio:
      m_audioTracks.append(track);
      break;
    case MediaStreamSource::TypeVideo:
      m_videoTracks.append(track);
      break;
  }
  track->registerMediaStream(this);
  m_descriptor->addComponent(component);

  scheduleDispatchEvent(
      MediaStreamTrackEvent::create(EventTypeNames::addtrack, track));

  if (!active() && !track->ended()) {
    m_descriptor->setActive(true);
    scheduleDispatchEvent(Event::create(EventTypeNames::active));
  }
}

void MediaStream::removeRemoteTrack(MediaStreamComponent* component) {
  DCHECK(component);
  if (m_stopped)
    return;

  MediaStreamTrackVector* tracks = 0;
  switch (component->source()->type()) {
    case MediaStreamSource::TypeAudio:
      tracks = &m_audioTracks;
      break;
    case MediaStreamSource::TypeVideo:
      tracks = &m_videoTracks;
      break;
  }

  size_t index = kNotFound;
  for (size_t i = 0; i < tracks->size(); ++i) {
    if ((*tracks)[i]->component() == component) {
      index = i;
      break;
    }
  }
  if (index == kNotFound)
    return;

  m_descriptor->removeComponent(component);

  MediaStreamTrack* track = (*tracks)[index];
  track->unregisterMediaStream(this);
  tracks->remove(index);
  scheduleDispatchEvent(
      MediaStreamTrackEvent::create(EventTypeNames::removetrack, track));

  if (active() && emptyOrOnlyEndedTracks()) {
    m_descriptor->setActive(false);
    scheduleDispatchEvent(Event::create(EventTypeNames::inactive));
  }
}

void MediaStream::scheduleDispatchEvent(Event* event) {
  m_scheduledEvents.append(event);

  if (!m_scheduledEventTimer.isActive())
    m_scheduledEventTimer.startOneShot(0, BLINK_FROM_HERE);
}

void MediaStream::scheduledEventTimerFired(TimerBase*) {
  if (m_stopped)
    return;

  HeapVector<Member<Event>> events;
  events.swap(m_scheduledEvents);

  HeapVector<Member<Event>>::iterator it = events.begin();
  for (; it != events.end(); ++it)
    dispatchEvent((*it).release());

  events.clear();
}

URLRegistry& MediaStream::registry() const {
  return MediaStreamRegistry::registry();
}

DEFINE_TRACE(MediaStream) {
  visitor->trace(m_audioTracks);
  visitor->trace(m_videoTracks);
  visitor->trace(m_descriptor);
  visitor->trace(m_scheduledEvents);
  EventTargetWithInlineData::trace(visitor);
  ContextLifecycleObserver::trace(visitor);
  MediaStreamDescriptorClient::trace(visitor);
}

MediaStream* toMediaStream(MediaStreamDescriptor* descriptor) {
  return static_cast<MediaStream*>(descriptor->client());
}

}  // namespace blink
