/*
 * libjingle
 * Copyright 2012 Google Inc.
 *
 * 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.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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 "talk/app/webrtc/mediastreamhandler.h"

#include "talk/app/webrtc/localaudiosource.h"
#include "talk/app/webrtc/videosource.h"
#include "talk/app/webrtc/videosourceinterface.h"

namespace webrtc {

TrackHandler::TrackHandler(MediaStreamTrackInterface* track, uint32 ssrc)
    : track_(track),
      ssrc_(ssrc),
      state_(track->state()),
      enabled_(track->enabled()) {
  track_->RegisterObserver(this);
}

TrackHandler::~TrackHandler() {
  track_->UnregisterObserver(this);
}

void TrackHandler::OnChanged() {
  if (state_ != track_->state()) {
    state_ = track_->state();
    OnStateChanged();
  }
  if (enabled_ != track_->enabled()) {
    enabled_ = track_->enabled();
    OnEnabledChanged();
  }
}

LocalAudioSinkAdapter::LocalAudioSinkAdapter() : sink_(NULL) {}

LocalAudioSinkAdapter::~LocalAudioSinkAdapter() {
  rtc::CritScope lock(&lock_);
  if (sink_)
    sink_->OnClose();
}

void LocalAudioSinkAdapter::OnData(const void* audio_data,
                                   int bits_per_sample,
                                   int sample_rate,
                                   int number_of_channels,
                                   int number_of_frames) {
  rtc::CritScope lock(&lock_);
  if (sink_) {
    sink_->OnData(audio_data, bits_per_sample, sample_rate,
                  number_of_channels, number_of_frames);
  }
}

void LocalAudioSinkAdapter::SetSink(cricket::AudioRenderer::Sink* sink) {
  rtc::CritScope lock(&lock_);
  ASSERT(!sink || !sink_);
  sink_ = sink;
}

LocalAudioTrackHandler::LocalAudioTrackHandler(
    AudioTrackInterface* track,
    uint32 ssrc,
    AudioProviderInterface* provider)
    : TrackHandler(track, ssrc),
      audio_track_(track),
      provider_(provider),
      sink_adapter_(new LocalAudioSinkAdapter()) {
  OnEnabledChanged();
  track->AddSink(sink_adapter_.get());
}

LocalAudioTrackHandler::~LocalAudioTrackHandler() {
}

void LocalAudioTrackHandler::OnStateChanged() {
  // TODO(perkj): What should happen when the state change?
}

void LocalAudioTrackHandler::Stop() {
  audio_track_->RemoveSink(sink_adapter_.get());
  cricket::AudioOptions options;
  provider_->SetAudioSend(ssrc(), false, options, NULL);
}

void LocalAudioTrackHandler::OnEnabledChanged() {
  cricket::AudioOptions options;
  if (audio_track_->enabled() && audio_track_->GetSource()) {
    // TODO(xians): Remove this static_cast since we should be able to connect
    // a remote audio track to peer connection.
    options = static_cast<LocalAudioSource*>(
        audio_track_->GetSource())->options();
  }

  // Use the renderer if the audio track has one, otherwise use the sink
  // adapter owned by this class.
  cricket::AudioRenderer* renderer = audio_track_->GetRenderer() ?
      audio_track_->GetRenderer() : sink_adapter_.get();
  ASSERT(renderer != NULL);
  provider_->SetAudioSend(ssrc(), audio_track_->enabled(), options, renderer);
}

RemoteAudioTrackHandler::RemoteAudioTrackHandler(
    AudioTrackInterface* track,
    uint32 ssrc,
    AudioProviderInterface* provider)
    : TrackHandler(track, ssrc),
      audio_track_(track),
      provider_(provider) {
  track->GetSource()->RegisterAudioObserver(this);
  OnEnabledChanged();
}

RemoteAudioTrackHandler::~RemoteAudioTrackHandler() {
  audio_track_->GetSource()->UnregisterAudioObserver(this);
}

void RemoteAudioTrackHandler::Stop() {
  provider_->SetAudioPlayout(ssrc(), false, NULL);
}

void RemoteAudioTrackHandler::OnStateChanged() {
}

void RemoteAudioTrackHandler::OnEnabledChanged() {
  provider_->SetAudioPlayout(ssrc(), audio_track_->enabled(),
                             audio_track_->GetRenderer());
}

void RemoteAudioTrackHandler::OnSetVolume(double volume) {
  // When the track is disabled, the volume of the source, which is the
  // corresponding WebRtc Voice Engine channel will be 0. So we do not allow
  // setting the volume to the source when the track is disabled.
  if (audio_track_->enabled())
    provider_->SetAudioPlayoutVolume(ssrc(), volume);
}

LocalVideoTrackHandler::LocalVideoTrackHandler(
    VideoTrackInterface* track,
    uint32 ssrc,
    VideoProviderInterface* provider)
    : TrackHandler(track, ssrc),
      local_video_track_(track),
      provider_(provider) {
  VideoSourceInterface* source = local_video_track_->GetSource();
  if (source)
    provider_->SetCaptureDevice(ssrc, source->GetVideoCapturer());
  OnEnabledChanged();
}

LocalVideoTrackHandler::~LocalVideoTrackHandler() {
}

void LocalVideoTrackHandler::OnStateChanged() {
}

void LocalVideoTrackHandler::Stop() {
  provider_->SetCaptureDevice(ssrc(), NULL);
  provider_->SetVideoSend(ssrc(), false, NULL);
}

void LocalVideoTrackHandler::OnEnabledChanged() {
  const cricket::VideoOptions* options = NULL;
  VideoSourceInterface* source = local_video_track_->GetSource();
  if (local_video_track_->enabled() && source) {
    options = source->options();
  }
  provider_->SetVideoSend(ssrc(), local_video_track_->enabled(), options);
}

RemoteVideoTrackHandler::RemoteVideoTrackHandler(
    VideoTrackInterface* track,
    uint32 ssrc,
    VideoProviderInterface* provider)
    : TrackHandler(track, ssrc),
      remote_video_track_(track),
      provider_(provider) {
  OnEnabledChanged();
  provider_->SetVideoPlayout(ssrc, true,
                             remote_video_track_->GetSource()->FrameInput());
}

RemoteVideoTrackHandler::~RemoteVideoTrackHandler() {
}

void RemoteVideoTrackHandler::Stop() {
  // Since cricket::VideoRenderer is not reference counted
  // we need to remove the renderer before we are deleted.
  provider_->SetVideoPlayout(ssrc(), false, NULL);
}

void RemoteVideoTrackHandler::OnStateChanged() {
}

void RemoteVideoTrackHandler::OnEnabledChanged() {
}

MediaStreamHandler::MediaStreamHandler(MediaStreamInterface* stream,
                                       AudioProviderInterface* audio_provider,
                                       VideoProviderInterface* video_provider)
    : stream_(stream),
      audio_provider_(audio_provider),
      video_provider_(video_provider) {
}

MediaStreamHandler::~MediaStreamHandler() {
  for (TrackHandlers::iterator it = track_handlers_.begin();
       it != track_handlers_.end(); ++it) {
    delete *it;
  }
}

void MediaStreamHandler::RemoveTrack(MediaStreamTrackInterface* track) {
  for (TrackHandlers::iterator it = track_handlers_.begin();
       it != track_handlers_.end(); ++it) {
    if ((*it)->track() == track) {
      TrackHandler* track = *it;
      track->Stop();
      delete track;
      track_handlers_.erase(it);
      break;
    }
  }
}

TrackHandler* MediaStreamHandler::FindTrackHandler(
    MediaStreamTrackInterface* track) {
  TrackHandlers::iterator it = track_handlers_.begin();
  for (; it != track_handlers_.end(); ++it) {
    if ((*it)->track() == track) {
      return *it;
      break;
    }
  }
  return NULL;
}

MediaStreamInterface* MediaStreamHandler::stream() {
  return stream_.get();
}

void MediaStreamHandler::OnChanged() {
}

void MediaStreamHandler::Stop() {
  for (TrackHandlers::const_iterator it = track_handlers_.begin();
      it != track_handlers_.end(); ++it) {
    (*it)->Stop();
  }
}

LocalMediaStreamHandler::LocalMediaStreamHandler(
    MediaStreamInterface* stream,
    AudioProviderInterface* audio_provider,
    VideoProviderInterface* video_provider)
    : MediaStreamHandler(stream, audio_provider, video_provider) {
}

LocalMediaStreamHandler::~LocalMediaStreamHandler() {
}

void LocalMediaStreamHandler::AddAudioTrack(AudioTrackInterface* audio_track,
                                            uint32 ssrc) {
  ASSERT(!FindTrackHandler(audio_track));

  TrackHandler* handler(new LocalAudioTrackHandler(audio_track, ssrc,
                                                   audio_provider_));
  track_handlers_.push_back(handler);
}

void LocalMediaStreamHandler::AddVideoTrack(VideoTrackInterface* video_track,
                                            uint32 ssrc) {
  ASSERT(!FindTrackHandler(video_track));

  TrackHandler* handler(new LocalVideoTrackHandler(video_track, ssrc,
                                                   video_provider_));
  track_handlers_.push_back(handler);
}

RemoteMediaStreamHandler::RemoteMediaStreamHandler(
    MediaStreamInterface* stream,
    AudioProviderInterface* audio_provider,
    VideoProviderInterface* video_provider)
    : MediaStreamHandler(stream, audio_provider, video_provider) {
}

RemoteMediaStreamHandler::~RemoteMediaStreamHandler() {
}

void RemoteMediaStreamHandler::AddAudioTrack(AudioTrackInterface* audio_track,
                                             uint32 ssrc) {
  ASSERT(!FindTrackHandler(audio_track));
  TrackHandler* handler(
      new RemoteAudioTrackHandler(audio_track, ssrc, audio_provider_));
  track_handlers_.push_back(handler);
}

void RemoteMediaStreamHandler::AddVideoTrack(VideoTrackInterface* video_track,
                                             uint32 ssrc) {
  ASSERT(!FindTrackHandler(video_track));
  TrackHandler* handler(
      new RemoteVideoTrackHandler(video_track, ssrc, video_provider_));
  track_handlers_.push_back(handler);
}

MediaStreamHandlerContainer::MediaStreamHandlerContainer(
    AudioProviderInterface* audio_provider,
    VideoProviderInterface* video_provider)
    : audio_provider_(audio_provider),
      video_provider_(video_provider) {
}

MediaStreamHandlerContainer::~MediaStreamHandlerContainer() {
  ASSERT(remote_streams_handlers_.empty());
  ASSERT(local_streams_handlers_.empty());
}

void MediaStreamHandlerContainer::TearDown() {
  for (StreamHandlerList::iterator it = remote_streams_handlers_.begin();
       it != remote_streams_handlers_.end(); ++it) {
    (*it)->Stop();
    delete *it;
  }
  remote_streams_handlers_.clear();
  for (StreamHandlerList::iterator it = local_streams_handlers_.begin();
       it != local_streams_handlers_.end(); ++it) {
    (*it)->Stop();
    delete *it;
  }
  local_streams_handlers_.clear();
}

void MediaStreamHandlerContainer::RemoveRemoteStream(
    MediaStreamInterface* stream) {
  DeleteStreamHandler(&remote_streams_handlers_, stream);
}

void MediaStreamHandlerContainer::AddRemoteAudioTrack(
    MediaStreamInterface* stream,
    AudioTrackInterface* audio_track,
    uint32 ssrc) {
  MediaStreamHandler* handler = FindStreamHandler(remote_streams_handlers_,
                                                  stream);
  if (handler == NULL) {
    handler = CreateRemoteStreamHandler(stream);
  }
  handler->AddAudioTrack(audio_track, ssrc);
}

void MediaStreamHandlerContainer::AddRemoteVideoTrack(
    MediaStreamInterface* stream,
    VideoTrackInterface* video_track,
    uint32 ssrc) {
  MediaStreamHandler* handler = FindStreamHandler(remote_streams_handlers_,
                                                  stream);
  if (handler == NULL) {
    handler = CreateRemoteStreamHandler(stream);
  }
  handler->AddVideoTrack(video_track, ssrc);
}

void MediaStreamHandlerContainer::RemoveRemoteTrack(
    MediaStreamInterface* stream,
    MediaStreamTrackInterface* track) {
  MediaStreamHandler* handler = FindStreamHandler(remote_streams_handlers_,
                                                  stream);
  if (!VERIFY(handler != NULL)) {
    LOG(LS_WARNING) << "Local MediaStreamHandler for stream  with id "
                    << stream->label() << "doesnt't exist.";
    return;
  }
  handler->RemoveTrack(track);
}

void MediaStreamHandlerContainer::RemoveLocalStream(
    MediaStreamInterface* stream) {
  DeleteStreamHandler(&local_streams_handlers_, stream);
}

void MediaStreamHandlerContainer::AddLocalAudioTrack(
    MediaStreamInterface* stream,
    AudioTrackInterface* audio_track,
    uint32 ssrc) {
  MediaStreamHandler* handler = FindStreamHandler(local_streams_handlers_,
                                                  stream);
  if (handler == NULL) {
    handler = CreateLocalStreamHandler(stream);
  }
  handler->AddAudioTrack(audio_track, ssrc);
}

void MediaStreamHandlerContainer::AddLocalVideoTrack(
    MediaStreamInterface* stream,
    VideoTrackInterface* video_track,
    uint32 ssrc) {
  MediaStreamHandler* handler = FindStreamHandler(local_streams_handlers_,
                                                  stream);
  if (handler == NULL) {
    handler = CreateLocalStreamHandler(stream);
  }
  handler->AddVideoTrack(video_track, ssrc);
}

void MediaStreamHandlerContainer::RemoveLocalTrack(
    MediaStreamInterface* stream,
    MediaStreamTrackInterface* track) {
  MediaStreamHandler* handler = FindStreamHandler(local_streams_handlers_,
                                                  stream);
  if (!VERIFY(handler != NULL)) {
    LOG(LS_WARNING) << "Remote MediaStreamHandler for stream with id "
                    << stream->label() << "doesnt't exist.";
    return;
  }
  handler->RemoveTrack(track);
}

MediaStreamHandler* MediaStreamHandlerContainer::CreateRemoteStreamHandler(
    MediaStreamInterface* stream) {
  ASSERT(!FindStreamHandler(remote_streams_handlers_, stream));

  RemoteMediaStreamHandler* handler =
      new RemoteMediaStreamHandler(stream, audio_provider_, video_provider_);
  remote_streams_handlers_.push_back(handler);
  return handler;
}

MediaStreamHandler* MediaStreamHandlerContainer::CreateLocalStreamHandler(
    MediaStreamInterface* stream) {
  ASSERT(!FindStreamHandler(local_streams_handlers_, stream));

  LocalMediaStreamHandler* handler =
      new LocalMediaStreamHandler(stream, audio_provider_, video_provider_);
  local_streams_handlers_.push_back(handler);
  return handler;
}

MediaStreamHandler* MediaStreamHandlerContainer::FindStreamHandler(
    const StreamHandlerList& handlers,
    MediaStreamInterface* stream) {
  StreamHandlerList::const_iterator it = handlers.begin();
  for (; it != handlers.end(); ++it) {
    if ((*it)->stream() == stream) {
      return *it;
    }
  }
  return NULL;
}

void MediaStreamHandlerContainer::DeleteStreamHandler(
    StreamHandlerList* streamhandlers, MediaStreamInterface* stream) {
  StreamHandlerList::iterator it = streamhandlers->begin();
  for (; it != streamhandlers->end(); ++it) {
    if ((*it)->stream() == stream) {
      (*it)->Stop();
      delete *it;
      streamhandlers->erase(it);
      break;
    }
  }
}

}  // namespace webrtc
