/*
 * 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
