/*
 *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "media/base/fake_media_engine.h"

#include <utility>

#include "absl/memory/memory.h"
#include "absl/strings/match.h"
#include "rtc_base/checks.h"

namespace cricket {

FakeVoiceMediaChannel::DtmfInfo::DtmfInfo(uint32_t ssrc,
                                          int event_code,
                                          int duration)
    : ssrc(ssrc), event_code(event_code), duration(duration) {}

FakeVoiceMediaChannel::VoiceChannelAudioSink::VoiceChannelAudioSink(
    AudioSource* source)
    : source_(source) {
  source_->SetSink(this);
}
FakeVoiceMediaChannel::VoiceChannelAudioSink::~VoiceChannelAudioSink() {
  if (source_) {
    source_->SetSink(nullptr);
  }
}
void FakeVoiceMediaChannel::VoiceChannelAudioSink::OnData(
    const void* audio_data,
    int bits_per_sample,
    int sample_rate,
    size_t number_of_channels,
    size_t number_of_frames) {}
void FakeVoiceMediaChannel::VoiceChannelAudioSink::OnClose() {
  source_ = nullptr;
}
AudioSource* FakeVoiceMediaChannel::VoiceChannelAudioSink::source() const {
  return source_;
}

FakeVoiceMediaChannel::FakeVoiceMediaChannel(FakeVoiceEngine* engine,
                                             const AudioOptions& options)
    : engine_(engine), max_bps_(-1) {
  output_scalings_[0] = 1.0;  // For default channel.
  SetOptions(options);
}
FakeVoiceMediaChannel::~FakeVoiceMediaChannel() {
  if (engine_) {
    engine_->UnregisterChannel(this);
  }
}
const std::vector<AudioCodec>& FakeVoiceMediaChannel::recv_codecs() const {
  return recv_codecs_;
}
const std::vector<AudioCodec>& FakeVoiceMediaChannel::send_codecs() const {
  return send_codecs_;
}
const std::vector<AudioCodec>& FakeVoiceMediaChannel::codecs() const {
  return send_codecs();
}
const std::vector<FakeVoiceMediaChannel::DtmfInfo>&
FakeVoiceMediaChannel::dtmf_info_queue() const {
  return dtmf_info_queue_;
}
const AudioOptions& FakeVoiceMediaChannel::options() const {
  return options_;
}
int FakeVoiceMediaChannel::max_bps() const {
  return max_bps_;
}
bool FakeVoiceMediaChannel::SetSendParameters(
    const AudioSendParameters& params) {
  set_send_rtcp_parameters(params.rtcp);
  return (SetSendCodecs(params.codecs) &&
          SetSendExtmapAllowMixed(params.extmap_allow_mixed) &&
          SetSendRtpHeaderExtensions(params.extensions) &&
          SetMaxSendBandwidth(params.max_bandwidth_bps) &&
          SetOptions(params.options));
}
bool FakeVoiceMediaChannel::SetRecvParameters(
    const AudioRecvParameters& params) {
  set_recv_rtcp_parameters(params.rtcp);
  return (SetRecvCodecs(params.codecs) &&
          SetRecvRtpHeaderExtensions(params.extensions));
}
void FakeVoiceMediaChannel::SetPlayout(bool playout) {
  set_playout(playout);
}
void FakeVoiceMediaChannel::SetSend(bool send) {
  set_sending(send);
}
bool FakeVoiceMediaChannel::SetAudioSend(uint32_t ssrc,
                                         bool enable,
                                         const AudioOptions* options,
                                         AudioSource* source) {
  if (!SetLocalSource(ssrc, source)) {
    return false;
  }
  if (!RtpHelper<VoiceMediaChannel>::MuteStream(ssrc, !enable)) {
    return false;
  }
  if (enable && options) {
    return SetOptions(*options);
  }
  return true;
}
bool FakeVoiceMediaChannel::HasSource(uint32_t ssrc) const {
  return local_sinks_.find(ssrc) != local_sinks_.end();
}
bool FakeVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
  if (!RtpHelper<VoiceMediaChannel>::AddRecvStream(sp))
    return false;
  output_scalings_[sp.first_ssrc()] = 1.0;
  return true;
}
bool FakeVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) {
  if (!RtpHelper<VoiceMediaChannel>::RemoveRecvStream(ssrc))
    return false;
  output_scalings_.erase(ssrc);
  return true;
}
bool FakeVoiceMediaChannel::CanInsertDtmf() {
  for (std::vector<AudioCodec>::const_iterator it = send_codecs_.begin();
       it != send_codecs_.end(); ++it) {
    // Find the DTMF telephone event "codec".
    if (absl::EqualsIgnoreCase(it->name, "telephone-event")) {
      return true;
    }
  }
  return false;
}
bool FakeVoiceMediaChannel::InsertDtmf(uint32_t ssrc,
                                       int event_code,
                                       int duration) {
  dtmf_info_queue_.push_back(DtmfInfo(ssrc, event_code, duration));
  return true;
}
bool FakeVoiceMediaChannel::SetOutputVolume(uint32_t ssrc, double volume) {
  if (0 == ssrc) {
    std::map<uint32_t, double>::iterator it;
    for (it = output_scalings_.begin(); it != output_scalings_.end(); ++it) {
      it->second = volume;
    }
    return true;
  } else if (output_scalings_.find(ssrc) != output_scalings_.end()) {
    output_scalings_[ssrc] = volume;
    return true;
  }
  return false;
}
bool FakeVoiceMediaChannel::GetOutputVolume(uint32_t ssrc, double* volume) {
  if (output_scalings_.find(ssrc) == output_scalings_.end())
    return false;
  *volume = output_scalings_[ssrc];
  return true;
}
bool FakeVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
  return false;
}
void FakeVoiceMediaChannel::SetRawAudioSink(
    uint32_t ssrc,
    std::unique_ptr<webrtc::AudioSinkInterface> sink) {
  sink_ = std::move(sink);
}
std::vector<webrtc::RtpSource> FakeVoiceMediaChannel::GetSources(
    uint32_t ssrc) const {
  return std::vector<webrtc::RtpSource>();
}
bool FakeVoiceMediaChannel::SetRecvCodecs(
    const std::vector<AudioCodec>& codecs) {
  if (fail_set_recv_codecs()) {
    // Fake the failure in SetRecvCodecs.
    return false;
  }
  recv_codecs_ = codecs;
  return true;
}
bool FakeVoiceMediaChannel::SetSendCodecs(
    const std::vector<AudioCodec>& codecs) {
  if (fail_set_send_codecs()) {
    // Fake the failure in SetSendCodecs.
    return false;
  }
  send_codecs_ = codecs;
  return true;
}
bool FakeVoiceMediaChannel::SetMaxSendBandwidth(int bps) {
  max_bps_ = bps;
  return true;
}
bool FakeVoiceMediaChannel::SetOptions(const AudioOptions& options) {
  // Does a "merge" of current options and set options.
  options_.SetAll(options);
  return true;
}
bool FakeVoiceMediaChannel::SetLocalSource(uint32_t ssrc, AudioSource* source) {
  auto it = local_sinks_.find(ssrc);
  if (source) {
    if (it != local_sinks_.end()) {
      RTC_CHECK(it->second->source() == source);
    } else {
      local_sinks_.insert(std::make_pair(
          ssrc, absl::make_unique<VoiceChannelAudioSink>(source)));
    }
  } else {
    if (it != local_sinks_.end()) {
      local_sinks_.erase(it);
    }
  }
  return true;
}

bool CompareDtmfInfo(const FakeVoiceMediaChannel::DtmfInfo& info,
                     uint32_t ssrc,
                     int event_code,
                     int duration) {
  return (info.duration == duration && info.event_code == event_code &&
          info.ssrc == ssrc);
}

FakeVideoMediaChannel::FakeVideoMediaChannel(FakeVideoEngine* engine,
                                             const VideoOptions& options)
    : engine_(engine), max_bps_(-1) {
  SetOptions(options);
}
FakeVideoMediaChannel::~FakeVideoMediaChannel() {
  if (engine_) {
    engine_->UnregisterChannel(this);
  }
}
const std::vector<VideoCodec>& FakeVideoMediaChannel::recv_codecs() const {
  return recv_codecs_;
}
const std::vector<VideoCodec>& FakeVideoMediaChannel::send_codecs() const {
  return send_codecs_;
}
const std::vector<VideoCodec>& FakeVideoMediaChannel::codecs() const {
  return send_codecs();
}
bool FakeVideoMediaChannel::rendering() const {
  return playout();
}
const VideoOptions& FakeVideoMediaChannel::options() const {
  return options_;
}
const std::map<uint32_t, rtc::VideoSinkInterface<webrtc::VideoFrame>*>&
FakeVideoMediaChannel::sinks() const {
  return sinks_;
}
int FakeVideoMediaChannel::max_bps() const {
  return max_bps_;
}
bool FakeVideoMediaChannel::SetSendParameters(
    const VideoSendParameters& params) {
  set_send_rtcp_parameters(params.rtcp);
  return (SetSendCodecs(params.codecs) &&
          SetSendExtmapAllowMixed(params.extmap_allow_mixed) &&
          SetSendRtpHeaderExtensions(params.extensions) &&
          SetMaxSendBandwidth(params.max_bandwidth_bps));
}
bool FakeVideoMediaChannel::SetRecvParameters(
    const VideoRecvParameters& params) {
  set_recv_rtcp_parameters(params.rtcp);
  return (SetRecvCodecs(params.codecs) &&
          SetRecvRtpHeaderExtensions(params.extensions));
}
bool FakeVideoMediaChannel::AddSendStream(const StreamParams& sp) {
  return RtpHelper<VideoMediaChannel>::AddSendStream(sp);
}
bool FakeVideoMediaChannel::RemoveSendStream(uint32_t ssrc) {
  return RtpHelper<VideoMediaChannel>::RemoveSendStream(ssrc);
}
bool FakeVideoMediaChannel::GetSendCodec(VideoCodec* send_codec) {
  if (send_codecs_.empty()) {
    return false;
  }
  *send_codec = send_codecs_[0];
  return true;
}
bool FakeVideoMediaChannel::SetSink(
    uint32_t ssrc,
    rtc::VideoSinkInterface<webrtc::VideoFrame>* sink) {
  if (ssrc != 0 && sinks_.find(ssrc) == sinks_.end()) {
    return false;
  }
  if (ssrc != 0) {
    sinks_[ssrc] = sink;
  }
  return true;
}
bool FakeVideoMediaChannel::HasSink(uint32_t ssrc) const {
  return sinks_.find(ssrc) != sinks_.end() && sinks_.at(ssrc) != nullptr;
}
bool FakeVideoMediaChannel::SetSend(bool send) {
  return set_sending(send);
}
bool FakeVideoMediaChannel::SetVideoSend(
    uint32_t ssrc,
    const VideoOptions* options,
    rtc::VideoSourceInterface<webrtc::VideoFrame>* source) {
  if (options) {
    if (!SetOptions(*options)) {
      return false;
    }
  }
  sources_[ssrc] = source;
  return true;
}
bool FakeVideoMediaChannel::HasSource(uint32_t ssrc) const {
  return sources_.find(ssrc) != sources_.end() && sources_.at(ssrc) != nullptr;
}
bool FakeVideoMediaChannel::AddRecvStream(const StreamParams& sp) {
  if (!RtpHelper<VideoMediaChannel>::AddRecvStream(sp))
    return false;
  sinks_[sp.first_ssrc()] = NULL;
  return true;
}
bool FakeVideoMediaChannel::RemoveRecvStream(uint32_t ssrc) {
  if (!RtpHelper<VideoMediaChannel>::RemoveRecvStream(ssrc))
    return false;
  sinks_.erase(ssrc);
  return true;
}
void FakeVideoMediaChannel::FillBitrateInfo(BandwidthEstimationInfo* bwe_info) {
}
bool FakeVideoMediaChannel::GetStats(VideoMediaInfo* info) {
  return false;
}
std::vector<webrtc::RtpSource> FakeVideoMediaChannel::GetSources(
    uint32_t ssrc) const {
  return {};
}
bool FakeVideoMediaChannel::SetRecvCodecs(
    const std::vector<VideoCodec>& codecs) {
  if (fail_set_recv_codecs()) {
    // Fake the failure in SetRecvCodecs.
    return false;
  }
  recv_codecs_ = codecs;
  return true;
}
bool FakeVideoMediaChannel::SetSendCodecs(
    const std::vector<VideoCodec>& codecs) {
  if (fail_set_send_codecs()) {
    // Fake the failure in SetSendCodecs.
    return false;
  }
  send_codecs_ = codecs;

  return true;
}
bool FakeVideoMediaChannel::SetOptions(const VideoOptions& options) {
  options_ = options;
  return true;
}
bool FakeVideoMediaChannel::SetMaxSendBandwidth(int bps) {
  max_bps_ = bps;
  return true;
}

FakeDataMediaChannel::FakeDataMediaChannel(void* unused,
                                           const DataOptions& options)
    : send_blocked_(false), max_bps_(-1) {}
FakeDataMediaChannel::~FakeDataMediaChannel() {}
const std::vector<DataCodec>& FakeDataMediaChannel::recv_codecs() const {
  return recv_codecs_;
}
const std::vector<DataCodec>& FakeDataMediaChannel::send_codecs() const {
  return send_codecs_;
}
const std::vector<DataCodec>& FakeDataMediaChannel::codecs() const {
  return send_codecs();
}
int FakeDataMediaChannel::max_bps() const {
  return max_bps_;
}
bool FakeDataMediaChannel::SetSendParameters(const DataSendParameters& params) {
  set_send_rtcp_parameters(params.rtcp);
  return (SetSendCodecs(params.codecs) &&
          SetMaxSendBandwidth(params.max_bandwidth_bps));
}
bool FakeDataMediaChannel::SetRecvParameters(const DataRecvParameters& params) {
  set_recv_rtcp_parameters(params.rtcp);
  return SetRecvCodecs(params.codecs);
}
bool FakeDataMediaChannel::SetSend(bool send) {
  return set_sending(send);
}
bool FakeDataMediaChannel::SetReceive(bool receive) {
  set_playout(receive);
  return true;
}
bool FakeDataMediaChannel::AddRecvStream(const StreamParams& sp) {
  if (!RtpHelper<DataMediaChannel>::AddRecvStream(sp))
    return false;
  return true;
}
bool FakeDataMediaChannel::RemoveRecvStream(uint32_t ssrc) {
  if (!RtpHelper<DataMediaChannel>::RemoveRecvStream(ssrc))
    return false;
  return true;
}
bool FakeDataMediaChannel::SendData(const SendDataParams& params,
                                    const rtc::CopyOnWriteBuffer& payload,
                                    SendDataResult* result) {
  if (send_blocked_) {
    *result = SDR_BLOCK;
    return false;
  } else {
    last_sent_data_params_ = params;
    last_sent_data_ = std::string(payload.data<char>(), payload.size());
    return true;
  }
}
SendDataParams FakeDataMediaChannel::last_sent_data_params() {
  return last_sent_data_params_;
}
std::string FakeDataMediaChannel::last_sent_data() {
  return last_sent_data_;
}
bool FakeDataMediaChannel::is_send_blocked() {
  return send_blocked_;
}
void FakeDataMediaChannel::set_send_blocked(bool blocked) {
  send_blocked_ = blocked;
}
bool FakeDataMediaChannel::SetRecvCodecs(const std::vector<DataCodec>& codecs) {
  if (fail_set_recv_codecs()) {
    // Fake the failure in SetRecvCodecs.
    return false;
  }
  recv_codecs_ = codecs;
  return true;
}
bool FakeDataMediaChannel::SetSendCodecs(const std::vector<DataCodec>& codecs) {
  if (fail_set_send_codecs()) {
    // Fake the failure in SetSendCodecs.
    return false;
  }
  send_codecs_ = codecs;
  return true;
}
bool FakeDataMediaChannel::SetMaxSendBandwidth(int bps) {
  max_bps_ = bps;
  return true;
}

FakeVoiceEngine::FakeVoiceEngine() : fail_create_channel_(false) {
  // Add a fake audio codec. Note that the name must not be "" as there are
  // sanity checks against that.
  codecs_.push_back(AudioCodec(101, "fake_audio_codec", 0, 0, 1));
}
RtpCapabilities FakeVoiceEngine::GetCapabilities() const {
  return RtpCapabilities();
}
void FakeVoiceEngine::Init() {}
rtc::scoped_refptr<webrtc::AudioState> FakeVoiceEngine::GetAudioState() const {
  return rtc::scoped_refptr<webrtc::AudioState>();
}
VoiceMediaChannel* FakeVoiceEngine::CreateMediaChannel(
    webrtc::Call* call,
    const MediaConfig& config,
    const AudioOptions& options,
    const webrtc::CryptoOptions& crypto_options) {
  if (fail_create_channel_) {
    return nullptr;
  }

  FakeVoiceMediaChannel* ch = new FakeVoiceMediaChannel(this, options);
  channels_.push_back(ch);
  return ch;
}
FakeVoiceMediaChannel* FakeVoiceEngine::GetChannel(size_t index) {
  return (channels_.size() > index) ? channels_[index] : NULL;
}
void FakeVoiceEngine::UnregisterChannel(VoiceMediaChannel* channel) {
  channels_.erase(std::find(channels_.begin(), channels_.end(), channel));
}
const std::vector<AudioCodec>& FakeVoiceEngine::send_codecs() const {
  return codecs_;
}
const std::vector<AudioCodec>& FakeVoiceEngine::recv_codecs() const {
  return codecs_;
}
void FakeVoiceEngine::SetCodecs(const std::vector<AudioCodec>& codecs) {
  codecs_ = codecs;
}
int FakeVoiceEngine::GetInputLevel() {
  return 0;
}
bool FakeVoiceEngine::StartAecDump(rtc::PlatformFile file,
                                   int64_t max_size_bytes) {
  return false;
}
void FakeVoiceEngine::StopAecDump() {}
bool FakeVoiceEngine::StartRtcEventLog(rtc::PlatformFile file,
                                       int64_t max_size_bytes) {
  return false;
}
void FakeVoiceEngine::StopRtcEventLog() {}

FakeVideoEngine::FakeVideoEngine()
    : capture_(false), fail_create_channel_(false) {
  // Add a fake video codec. Note that the name must not be "" as there are
  // sanity checks against that.
  codecs_.push_back(VideoCodec(0, "fake_video_codec"));
}
RtpCapabilities FakeVideoEngine::GetCapabilities() const {
  return RtpCapabilities();
}
bool FakeVideoEngine::SetOptions(const VideoOptions& options) {
  options_ = options;
  return true;
}
VideoMediaChannel* FakeVideoEngine::CreateMediaChannel(
    webrtc::Call* call,
    const MediaConfig& config,
    const VideoOptions& options,
    const webrtc::CryptoOptions& crypto_options) {
  if (fail_create_channel_) {
    return nullptr;
  }

  FakeVideoMediaChannel* ch = new FakeVideoMediaChannel(this, options);
  channels_.emplace_back(ch);
  return ch;
}
FakeVideoMediaChannel* FakeVideoEngine::GetChannel(size_t index) {
  return (channels_.size() > index) ? channels_[index] : nullptr;
}
void FakeVideoEngine::UnregisterChannel(VideoMediaChannel* channel) {
  auto it = std::find(channels_.begin(), channels_.end(), channel);
  RTC_DCHECK(it != channels_.end());
  channels_.erase(it);
}
std::vector<VideoCodec> FakeVideoEngine::codecs() const {
  return codecs_;
}
void FakeVideoEngine::SetCodecs(const std::vector<VideoCodec> codecs) {
  codecs_ = codecs;
}
bool FakeVideoEngine::SetCapture(bool capture) {
  capture_ = capture;
  return true;
}

FakeMediaEngine::FakeMediaEngine()
    : CompositeMediaEngine(absl::make_unique<FakeVoiceEngine>(),
                           absl::make_unique<FakeVideoEngine>()),
      voice_(static_cast<FakeVoiceEngine*>(&voice())),
      video_(static_cast<FakeVideoEngine*>(&video())) {}
FakeMediaEngine::~FakeMediaEngine() {}
void FakeMediaEngine::SetAudioCodecs(const std::vector<AudioCodec>& codecs) {
  voice_->SetCodecs(codecs);
}
void FakeMediaEngine::SetVideoCodecs(const std::vector<VideoCodec>& codecs) {
  video_->SetCodecs(codecs);
}

FakeVoiceMediaChannel* FakeMediaEngine::GetVoiceChannel(size_t index) {
  return voice_->GetChannel(index);
}
FakeVideoMediaChannel* FakeMediaEngine::GetVideoChannel(size_t index) {
  return video_->GetChannel(index);
}

void FakeMediaEngine::set_fail_create_channel(bool fail) {
  voice_->fail_create_channel_ = fail;
  video_->fail_create_channel_ = fail;
}

DataMediaChannel* FakeDataEngine::CreateChannel(const MediaConfig& config) {
  FakeDataMediaChannel* ch = new FakeDataMediaChannel(this, DataOptions());
  channels_.push_back(ch);
  return ch;
}
FakeDataMediaChannel* FakeDataEngine::GetChannel(size_t index) {
  return (channels_.size() > index) ? channels_[index] : NULL;
}
void FakeDataEngine::UnregisterChannel(DataMediaChannel* channel) {
  channels_.erase(std::find(channels_.begin(), channels_.end(), channel));
}
void FakeDataEngine::SetDataCodecs(const std::vector<DataCodec>& data_codecs) {
  data_codecs_ = data_codecs;
}
const std::vector<DataCodec>& FakeDataEngine::data_codecs() {
  return data_codecs_;
}

}  // namespace cricket
