// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/renderer/media/remote_media_stream_impl.h"

#include <string>

#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "content/renderer/media/media_stream_extra_data.h"
#include "third_party/WebKit/public/platform/WebString.h"

namespace content {

// RemoteMediaStreamTrackObserver is responsible for listening on change
// notification on a remote webrtc MediaStreamTrack and notify WebKit.
class RemoteMediaStreamTrackObserver
    : NON_EXPORTED_BASE(public webrtc::ObserverInterface),
      NON_EXPORTED_BASE(public base::NonThreadSafe) {
 public:
  RemoteMediaStreamTrackObserver(
      webrtc::MediaStreamTrackInterface* webrtc_track,
      const WebKit::WebMediaStreamTrack& webkit_track);
  virtual ~RemoteMediaStreamTrackObserver();

  webrtc::MediaStreamTrackInterface* observered_track() {
    return webrtc_track_.get();
  }
  const WebKit::WebMediaStreamTrack& webkit_track() { return webkit_track_; }

 private:
  // webrtc::ObserverInterface implementation.
  virtual void OnChanged() OVERRIDE;

  webrtc::MediaStreamTrackInterface::TrackState state_;
  scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track_;
  WebKit::WebMediaStreamTrack webkit_track_;

  DISALLOW_COPY_AND_ASSIGN(RemoteMediaStreamTrackObserver);
};

}  // namespace content

namespace {

void InitializeWebkitTrack(webrtc::MediaStreamTrackInterface* track,
                           WebKit::WebMediaStreamTrack* webkit_track,
                           WebKit::WebMediaStreamSource::Type type) {
  WebKit::WebMediaStreamSource webkit_source;
  WebKit::WebString webkit_track_id(UTF8ToUTF16(track->id()));

  webkit_source.initialize(webkit_track_id, type, webkit_track_id);
  webkit_track->initialize(webkit_track_id, webkit_source);
}

content::RemoteMediaStreamTrackObserver* FindTrackObserver(
    webrtc::MediaStreamTrackInterface* track,
    const ScopedVector<content::RemoteMediaStreamTrackObserver>& observers) {
  ScopedVector<content::RemoteMediaStreamTrackObserver>::const_iterator it =
      observers.begin();
  for (; it != observers.end(); ++it) {
    if ((*it)->observered_track() == track)
      return *it;
  }
  return NULL;
}

} // namespace anonymous

namespace content {

RemoteMediaStreamTrackObserver::RemoteMediaStreamTrackObserver(
    webrtc::MediaStreamTrackInterface* webrtc_track,
    const WebKit::WebMediaStreamTrack& webkit_track)
    : state_(webrtc_track->state()),
      webrtc_track_(webrtc_track),
      webkit_track_(webkit_track) {
  webrtc_track->RegisterObserver(this);
}

RemoteMediaStreamTrackObserver::~RemoteMediaStreamTrackObserver() {
  webrtc_track_->UnregisterObserver(this);
}

void RemoteMediaStreamTrackObserver::OnChanged() {
  DCHECK(CalledOnValidThread());

  webrtc::MediaStreamTrackInterface::TrackState state = webrtc_track_->state();
  if (state == state_)
    return;

  state_ = state;
  switch (state) {
    case webrtc::MediaStreamTrackInterface::kInitializing:
      // Ignore the kInitializing state since there is no match in
      // WebMediaStreamSource::ReadyState.
      break;
    case webrtc::MediaStreamTrackInterface::kLive:
      webkit_track_.source().setReadyState(
          WebKit::WebMediaStreamSource::ReadyStateLive);
      break;
    case webrtc::MediaStreamTrackInterface::kEnded:
      webkit_track_.source().setReadyState(
          WebKit::WebMediaStreamSource::ReadyStateEnded);
      break;
    default:
      NOTREACHED();
      break;
  }
}

RemoteMediaStreamImpl::RemoteMediaStreamImpl(
    webrtc::MediaStreamInterface* webrtc_stream)
    : webrtc_stream_(webrtc_stream) {
  webrtc_stream_->RegisterObserver(this);

  webrtc::AudioTrackVector webrtc_audio_tracks =
      webrtc_stream_->GetAudioTracks();
  WebKit::WebVector<WebKit::WebMediaStreamTrack> webkit_audio_tracks(
      webrtc_audio_tracks.size());

  // Initialize WebKit audio tracks.
  size_t i = 0;
  for (; i < webrtc_audio_tracks.size(); ++i) {
    webrtc::AudioTrackInterface* audio_track = webrtc_audio_tracks[i];
    DCHECK(audio_track);
    InitializeWebkitTrack(audio_track,  &webkit_audio_tracks[i],
                          WebKit::WebMediaStreamSource::TypeAudio);
    audio_track_observers_.push_back(
        new RemoteMediaStreamTrackObserver(audio_track,
                                           webkit_audio_tracks[i]));
  }

  // Initialize WebKit video tracks.
  webrtc::VideoTrackVector webrtc_video_tracks =
        webrtc_stream_->GetVideoTracks();
  WebKit::WebVector<WebKit::WebMediaStreamTrack> webkit_video_tracks(
       webrtc_video_tracks.size());
  for (i = 0; i < webrtc_video_tracks.size(); ++i) {
    webrtc::VideoTrackInterface* video_track = webrtc_video_tracks[i];
    DCHECK(video_track);
    InitializeWebkitTrack(video_track,  &webkit_video_tracks[i],
                          WebKit::WebMediaStreamSource::TypeVideo);
    video_track_observers_.push_back(
        new RemoteMediaStreamTrackObserver(video_track,
                                           webkit_video_tracks[i]));
  }

  webkit_stream_.initialize(UTF8ToUTF16(webrtc_stream->label()),
                            webkit_audio_tracks, webkit_video_tracks);
  webkit_stream_.setExtraData(new MediaStreamExtraData(webrtc_stream, false));
}

RemoteMediaStreamImpl::~RemoteMediaStreamImpl() {
  webrtc_stream_->UnregisterObserver(this);
}

void RemoteMediaStreamImpl::OnChanged() {
  // Find removed audio tracks.
  ScopedVector<RemoteMediaStreamTrackObserver>::iterator audio_it =
      audio_track_observers_.begin();
  while (audio_it != audio_track_observers_.end()) {
    std::string track_id = (*audio_it)->observered_track()->id();
    if (webrtc_stream_->FindAudioTrack(track_id) == NULL) {
       webkit_stream_.removeTrack((*audio_it)->webkit_track());
       audio_it = audio_track_observers_.erase(audio_it);
    } else {
      ++audio_it;
    }
  }

  // Find removed video tracks.
  ScopedVector<RemoteMediaStreamTrackObserver>::iterator video_it =
      video_track_observers_.begin();
  while (video_it != video_track_observers_.end()) {
    std::string track_id = (*video_it)->observered_track()->id();
    if (webrtc_stream_->FindVideoTrack(track_id) == NULL) {
      webkit_stream_.removeTrack((*video_it)->webkit_track());
      video_it = video_track_observers_.erase(video_it);
    } else {
      ++video_it;
    }
  }

  // Find added audio tracks.
  webrtc::AudioTrackVector webrtc_audio_tracks =
      webrtc_stream_->GetAudioTracks();
  for (webrtc::AudioTrackVector::iterator it = webrtc_audio_tracks.begin();
       it != webrtc_audio_tracks.end(); ++it) {
    if (!FindTrackObserver(*it, audio_track_observers_)) {
      WebKit::WebMediaStreamTrack new_track;
      InitializeWebkitTrack(*it, &new_track,
                            WebKit::WebMediaStreamSource::TypeAudio);
      audio_track_observers_.push_back(
          new RemoteMediaStreamTrackObserver(*it, new_track));
      webkit_stream_.addTrack(new_track);
    }
  }

  // Find added video tracks.
  webrtc::VideoTrackVector webrtc_video_tracks =
      webrtc_stream_->GetVideoTracks();
  for (webrtc::VideoTrackVector::iterator it = webrtc_video_tracks.begin();
       it != webrtc_video_tracks.end(); ++it) {
    if (!FindTrackObserver(*it, video_track_observers_)) {
      WebKit::WebMediaStreamTrack new_track;
      InitializeWebkitTrack(*it, &new_track,
                            WebKit::WebMediaStreamSource::TypeVideo);
      video_track_observers_.push_back(
          new RemoteMediaStreamTrackObserver(*it, new_track));
      webkit_stream_.addTrack(new_track);
    }
  }
}

}  // namespace content
