// Copyright (c) 2012 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/mock_peer_connection_impl.h"

#include <vector>

#include "base/logging.h"
#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"

using testing::_;
using webrtc::AudioTrackInterface;
using webrtc::CreateSessionDescriptionObserver;
using webrtc::DtmfSenderInterface;
using webrtc::DtmfSenderObserverInterface;
using webrtc::IceCandidateInterface;
using webrtc::MediaConstraintsInterface;
using webrtc::MediaStreamInterface;
using webrtc::PeerConnectionInterface;
using webrtc::SessionDescriptionInterface;
using webrtc::SetSessionDescriptionObserver;

namespace content {

class MockStreamCollection : public webrtc::StreamCollectionInterface {
 public:
  virtual size_t count() OVERRIDE {
    return streams_.size();
  }
  virtual MediaStreamInterface* at(size_t index) OVERRIDE {
    return streams_[index];
  }
  virtual MediaStreamInterface* find(const std::string& label) OVERRIDE {
    for (size_t i = 0; i < streams_.size(); ++i) {
      if (streams_[i]->label() == label)
        return streams_[i];
    }
    return NULL;
  }
  virtual webrtc::MediaStreamTrackInterface* FindAudioTrack(
      const std::string& id) OVERRIDE {
    for (size_t i = 0; i < streams_.size(); ++i) {
      webrtc::MediaStreamTrackInterface* track =
          streams_.at(i)->FindAudioTrack(id);
      if (track)
        return track;
    }
    return NULL;
  }
  virtual webrtc::MediaStreamTrackInterface* FindVideoTrack(
      const std::string& id) OVERRIDE {
    for (size_t i = 0; i < streams_.size(); ++i) {
      webrtc::MediaStreamTrackInterface* track =
          streams_.at(i)->FindVideoTrack(id);
      if (track)
        return track;
    }
    return NULL;
  }
  void AddStream(MediaStreamInterface* stream) {
    streams_.push_back(stream);
  }
  void RemoveStream(MediaStreamInterface* stream) {
    StreamVector::iterator it = streams_.begin();
    for (; it != streams_.end(); ++it) {
      if (it->get() == stream) {
        streams_.erase(it);
        break;
      }
    }
  }

 protected:
  virtual ~MockStreamCollection() {}

 private:
  typedef std::vector<rtc::scoped_refptr<MediaStreamInterface> >
      StreamVector;
  StreamVector streams_;
};

class MockDataChannel : public webrtc::DataChannelInterface {
 public:
  MockDataChannel(const std::string& label,
                  const webrtc::DataChannelInit* config)
      : label_(label),
        reliable_(config->reliable),
        state_(webrtc::DataChannelInterface::kConnecting),
        config_(*config) {
  }

  virtual void RegisterObserver(
      webrtc::DataChannelObserver* observer) OVERRIDE {
  }

  virtual void UnregisterObserver() OVERRIDE {
  }

  virtual std::string label() const OVERRIDE {
    return label_;
  }

  virtual bool reliable() const OVERRIDE {
    return reliable_;
  }

  virtual bool ordered() const OVERRIDE {
    return config_.ordered;
  }

  virtual unsigned short maxRetransmitTime() const OVERRIDE {
    return config_.maxRetransmitTime;
  }

  virtual unsigned short maxRetransmits() const OVERRIDE {
    return config_.maxRetransmits;
  }

  virtual std::string protocol() const OVERRIDE {
    return config_.protocol;
  }

  virtual bool negotiated() const OVERRIDE {
    return config_.negotiated;
  }

  virtual int id() const OVERRIDE {
    NOTIMPLEMENTED();
    return 0;
  }

  virtual DataState state() const OVERRIDE {
    return state_;
  }

  virtual uint64 buffered_amount() const OVERRIDE {
    NOTIMPLEMENTED();
    return 0;
  }

  virtual void Close() OVERRIDE {
    state_ = webrtc::DataChannelInterface::kClosing;
  }

  virtual bool Send(const webrtc::DataBuffer& buffer) OVERRIDE {
    return state_ == webrtc::DataChannelInterface::kOpen;
  }

 protected:
  virtual ~MockDataChannel() {}

 private:
  std::string label_;
  bool reliable_;
  webrtc::DataChannelInterface::DataState state_;
  webrtc::DataChannelInit config_;
};

class MockDtmfSender : public DtmfSenderInterface {
 public:
  explicit MockDtmfSender(AudioTrackInterface* track)
      : track_(track),
        observer_(NULL),
        duration_(0),
        inter_tone_gap_(0) {}
  virtual void RegisterObserver(
      DtmfSenderObserverInterface* observer) OVERRIDE {
    observer_ = observer;
  }
  virtual void UnregisterObserver() OVERRIDE {
    observer_ = NULL;
  }
  virtual bool CanInsertDtmf() OVERRIDE {
    return true;
  }
  virtual bool InsertDtmf(const std::string& tones, int duration,
                          int inter_tone_gap) OVERRIDE {
    tones_ = tones;
    duration_ = duration;
    inter_tone_gap_ = inter_tone_gap;
    return true;
  }
  virtual const AudioTrackInterface* track() const OVERRIDE {
    return track_.get();
  }
  virtual std::string tones() const OVERRIDE {
    return tones_;
  }
  virtual int duration() const OVERRIDE { return duration_; }
  virtual int inter_tone_gap() const OVERRIDE { return inter_tone_gap_; }

 protected:
  virtual ~MockDtmfSender() {}

 private:
  rtc::scoped_refptr<AudioTrackInterface> track_;
  DtmfSenderObserverInterface* observer_;
  std::string tones_;
  int duration_;
  int inter_tone_gap_;
};

const char MockPeerConnectionImpl::kDummyOffer[] = "dummy offer";
const char MockPeerConnectionImpl::kDummyAnswer[] = "dummy answer";

MockPeerConnectionImpl::MockPeerConnectionImpl(
    MockPeerConnectionDependencyFactory* factory)
    : dependency_factory_(factory),
      local_streams_(new rtc::RefCountedObject<MockStreamCollection>),
      remote_streams_(new rtc::RefCountedObject<MockStreamCollection>),
      hint_audio_(false),
      hint_video_(false),
      getstats_result_(true),
      sdp_mline_index_(-1) {
  ON_CALL(*this, SetLocalDescription(_, _)).WillByDefault(testing::Invoke(
      this, &MockPeerConnectionImpl::SetLocalDescriptionWorker));
  ON_CALL(*this, SetRemoteDescription(_, _)).WillByDefault(testing::Invoke(
      this, &MockPeerConnectionImpl::SetRemoteDescriptionWorker));
}

MockPeerConnectionImpl::~MockPeerConnectionImpl() {}

rtc::scoped_refptr<webrtc::StreamCollectionInterface>
MockPeerConnectionImpl::local_streams() {
  return local_streams_;
}

rtc::scoped_refptr<webrtc::StreamCollectionInterface>
MockPeerConnectionImpl::remote_streams() {
  return remote_streams_;
}

bool MockPeerConnectionImpl::AddStream(
    MediaStreamInterface* local_stream,
    const MediaConstraintsInterface* constraints) {
  DCHECK(stream_label_.empty());
  stream_label_ = local_stream->label();
  local_streams_->AddStream(local_stream);
  return true;
}

void MockPeerConnectionImpl::RemoveStream(
    MediaStreamInterface* local_stream) {
  DCHECK_EQ(stream_label_, local_stream->label());
  stream_label_.clear();
  local_streams_->RemoveStream(local_stream);
}

rtc::scoped_refptr<DtmfSenderInterface>
MockPeerConnectionImpl::CreateDtmfSender(AudioTrackInterface* track) {
  if (!track) {
    return NULL;
  }
  return new rtc::RefCountedObject<MockDtmfSender>(track);
}

rtc::scoped_refptr<webrtc::DataChannelInterface>
MockPeerConnectionImpl::CreateDataChannel(const std::string& label,
                      const webrtc::DataChannelInit* config) {
  return new rtc::RefCountedObject<MockDataChannel>(label, config);
}

bool MockPeerConnectionImpl::GetStats(
    webrtc::StatsObserver* observer,
    webrtc::MediaStreamTrackInterface* track,
    StatsOutputLevel level) {
  if (!getstats_result_)
    return false;

  DCHECK_EQ(kStatsOutputLevelStandard, level);
  webrtc::StatsReport report1, report2;
  report1.id = "1234";
  report1.type = "ssrc";
  report1.timestamp = 42;
  report1.values.push_back(
      webrtc::StatsReport::Value(
          webrtc::StatsReport::kStatsValueNameFingerprint,
          "trackvalue"));

  std::vector<webrtc::StatsReport> reports;
  reports.push_back(report1);

  // If selector is given, we pass back one report.
  // If selector is not given, we pass back two.
  if (!track) {
    report2.id = "nontrack";
    report2.type = "generic";
    report2.timestamp = 44;
    report2.values.push_back(
        webrtc::StatsReport::Value(
            webrtc::StatsReport::kStatsValueNameFingerprintAlgorithm,
            "somevalue"));
    reports.push_back(report2);
  }

  // Note that the callback is synchronous, not asynchronous; it will
  // happen before the request call completes.
  observer->OnComplete(reports);

  return true;
}

const webrtc::SessionDescriptionInterface*
MockPeerConnectionImpl::local_description() const {
  return local_desc_.get();
}

const webrtc::SessionDescriptionInterface*
MockPeerConnectionImpl::remote_description() const {
  return remote_desc_.get();
}

void MockPeerConnectionImpl::AddRemoteStream(MediaStreamInterface* stream) {
  remote_streams_->AddStream(stream);
}

void MockPeerConnectionImpl::CreateOffer(
    CreateSessionDescriptionObserver* observer,
    const MediaConstraintsInterface* constraints) {
  DCHECK(observer);
  created_sessiondescription_.reset(
      dependency_factory_->CreateSessionDescription("unknown", kDummyOffer,
                                                    NULL));
}

void MockPeerConnectionImpl::CreateAnswer(
    CreateSessionDescriptionObserver* observer,
    const MediaConstraintsInterface* constraints) {
  DCHECK(observer);
  created_sessiondescription_.reset(
      dependency_factory_->CreateSessionDescription("unknown", kDummyAnswer,
                                                    NULL));
}

void MockPeerConnectionImpl::SetLocalDescriptionWorker(
    SetSessionDescriptionObserver* observer,
    SessionDescriptionInterface* desc) {
  desc->ToString(&description_sdp_);
  local_desc_.reset(desc);
}

void MockPeerConnectionImpl::SetRemoteDescriptionWorker(
    SetSessionDescriptionObserver* observer,
    SessionDescriptionInterface* desc) {
  desc->ToString(&description_sdp_);
  remote_desc_.reset(desc);
}

bool MockPeerConnectionImpl::UpdateIce(
    const IceServers& configuration,
    const MediaConstraintsInterface* constraints) {
  return true;
}

bool MockPeerConnectionImpl::AddIceCandidate(
    const IceCandidateInterface* candidate) {
  sdp_mid_ = candidate->sdp_mid();
  sdp_mline_index_ = candidate->sdp_mline_index();
  return candidate->ToString(&ice_sdp_);
}

void MockPeerConnectionImpl::RegisterUMAObserver(
    webrtc::UMAObserver* observer) {
  NOTIMPLEMENTED();
}

}  // namespace content
