/*
 * 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/localvideosource.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();
  }
}

LocalAudioTrackHandler::LocalAudioTrackHandler(
    AudioTrackInterface* track,
    uint32 ssrc,
    AudioProviderInterface* provider)
    : TrackHandler(track, ssrc),
      audio_track_(track),
      provider_(provider) {
  OnEnabledChanged();
}

LocalAudioTrackHandler::~LocalAudioTrackHandler() {
}

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

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

void LocalAudioTrackHandler::OnEnabledChanged() {
  cricket::AudioOptions options;
  if (audio_track_->enabled() && audio_track_->GetSource()) {
    options = static_cast<LocalAudioSource*>(
        audio_track_->GetSource())->options();
  }
  provider_->SetAudioSend(ssrc(), audio_track_->enabled(), options,
                          audio_track_->GetRenderer());
}

RemoteAudioTrackHandler::RemoteAudioTrackHandler(
    AudioTrackInterface* track,
    uint32 ssrc,
    AudioProviderInterface* provider)
    : TrackHandler(track, ssrc),
      audio_track_(track),
      provider_(provider) {
  OnEnabledChanged();
}

RemoteAudioTrackHandler::~RemoteAudioTrackHandler() {
}

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

void RemoteAudioTrackHandler::OnStateChanged() {
}

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

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();
}

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() {
  provider_->SetVideoPlayout(ssrc(),
                             remote_video_track_->enabled(),
                             remote_video_track_->FrameInput());
}

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
