/*
 * libjingle
 * Copyright 2013, 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.
 *
 */

#ifndef TALK_APP_WEBRTC_TEST_FAKEMEDIASTREAMSIGNALING_H_
#define TALK_APP_WEBRTC_TEST_FAKEMEDIASTREAMSIGNALING_H_

#include "talk/app/webrtc/audiotrack.h"
#include "talk/app/webrtc/mediastreamsignaling.h"
#include "talk/app/webrtc/videotrack.h"

static const char kStream1[] = "stream1";
static const char kVideoTrack1[] = "video1";
static const char kAudioTrack1[] = "audio1";

static const char kStream2[] = "stream2";
static const char kVideoTrack2[] = "video2";
static const char kAudioTrack2[] = "audio2";

class FakeMediaStreamSignaling : public webrtc::MediaStreamSignaling,
                                 public webrtc::MediaStreamSignalingObserver {
 public:
  explicit FakeMediaStreamSignaling(cricket::ChannelManager* channel_manager) :
    webrtc::MediaStreamSignaling(rtc::Thread::Current(), this,
                                 channel_manager) {
  }

  void SendAudioVideoStream1() {
    ClearLocalStreams();
    AddLocalStream(CreateStream(kStream1, kAudioTrack1, kVideoTrack1));
  }

  void SendAudioVideoStream2() {
    ClearLocalStreams();
    AddLocalStream(CreateStream(kStream2, kAudioTrack2, kVideoTrack2));
  }

  void SendAudioVideoStream1And2() {
    ClearLocalStreams();
    AddLocalStream(CreateStream(kStream1, kAudioTrack1, kVideoTrack1));
    AddLocalStream(CreateStream(kStream2, kAudioTrack2, kVideoTrack2));
  }

  void SendNothing() {
    ClearLocalStreams();
  }

  void UseOptionsAudioOnly() {
    ClearLocalStreams();
    AddLocalStream(CreateStream(kStream2, kAudioTrack2, ""));
  }

  void UseOptionsVideoOnly() {
    ClearLocalStreams();
    AddLocalStream(CreateStream(kStream2, "", kVideoTrack2));
  }

  void ClearLocalStreams() {
    while (local_streams()->count() != 0) {
      RemoveLocalStream(local_streams()->at(0));
    }
  }

  // Implements MediaStreamSignalingObserver.
  virtual void OnAddRemoteStream(webrtc::MediaStreamInterface* stream) {
  }
  virtual void OnRemoveRemoteStream(webrtc::MediaStreamInterface* stream) {
  }
  virtual void OnAddDataChannel(webrtc::DataChannelInterface* data_channel) {
  }
  virtual void OnAddLocalAudioTrack(webrtc::MediaStreamInterface* stream,
                                    webrtc::AudioTrackInterface* audio_track,
                                    uint32 ssrc) {
  }
  virtual void OnAddLocalVideoTrack(webrtc::MediaStreamInterface* stream,
                                    webrtc::VideoTrackInterface* video_track,
                                    uint32 ssrc) {
  }
  virtual void OnAddRemoteAudioTrack(webrtc::MediaStreamInterface* stream,
                                     webrtc::AudioTrackInterface* audio_track,
                                     uint32 ssrc) {
  }

  virtual void OnAddRemoteVideoTrack(webrtc::MediaStreamInterface* stream,
                                     webrtc::VideoTrackInterface* video_track,
                                     uint32 ssrc) {
  }

  virtual void OnRemoveRemoteAudioTrack(
      webrtc::MediaStreamInterface* stream,
      webrtc::AudioTrackInterface* audio_track) {
  }

  virtual void OnRemoveRemoteVideoTrack(
      webrtc::MediaStreamInterface* stream,
      webrtc::VideoTrackInterface* video_track) {
  }

  virtual void OnRemoveLocalAudioTrack(
      webrtc::MediaStreamInterface* stream,
      webrtc::AudioTrackInterface* audio_track,
      uint32 ssrc) {
  }
  virtual void OnRemoveLocalVideoTrack(
      webrtc::MediaStreamInterface* stream,
      webrtc::VideoTrackInterface* video_track) {
  }
  virtual void OnRemoveLocalStream(webrtc::MediaStreamInterface* stream) {
  }

 private:
  rtc::scoped_refptr<webrtc::MediaStreamInterface> CreateStream(
      const std::string& stream_label,
      const std::string& audio_track_id,
      const std::string& video_track_id) {
    rtc::scoped_refptr<webrtc::MediaStreamInterface> stream(
        webrtc::MediaStream::Create(stream_label));

    if (!audio_track_id.empty()) {
      rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
          webrtc::AudioTrack::Create(audio_track_id, NULL));
      stream->AddTrack(audio_track);
    }

    if (!video_track_id.empty()) {
      rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track(
          webrtc::VideoTrack::Create(video_track_id, NULL));
      stream->AddTrack(video_track);
    }
    return stream;
  }
};

#endif  // TALK_APP_WEBRTC_TEST_FAKEMEDIASTREAMSIGNALING_H_
