/*
 *  Copyright 2013 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 "pc/test/peer_connection_test_wrapper.h"

#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "api/audio/audio_device.h"
#include "api/audio_codecs/audio_decoder_factory.h"
#include "api/audio_codecs/audio_encoder_factory.h"
#include "api/audio_options.h"
#include "api/create_peerconnection_factory.h"
#include "api/data_channel_interface.h"
#include "api/environment/environment.h"
#include "api/environment/environment_factory.h"
#include "api/field_trials_view.h"
#include "api/jsep.h"
#include "api/make_ref_counted.h"
#include "api/media_stream_interface.h"
#include "api/media_types.h"
#include "api/peer_connection_interface.h"
#include "api/rtc_error.h"
#include "api/rtp_parameters.h"
#include "api/rtp_receiver_interface.h"
#include "api/scoped_refptr.h"
#include "api/sequence_checker.h"
#include "api/test/rtc_error_matchers.h"
#include "api/units/time_delta.h"
#include "api/video/resolution.h"
#include "api/video_codecs/sdp_video_format.h"
#include "api/video_codecs/video_decoder_factory.h"
#include "api/video_codecs/video_decoder_factory_template.h"
#include "api/video_codecs/video_decoder_factory_template_dav1d_adapter.h"
#include "api/video_codecs/video_decoder_factory_template_libvpx_vp8_adapter.h"
#include "api/video_codecs/video_decoder_factory_template_libvpx_vp9_adapter.h"
#include "api/video_codecs/video_decoder_factory_template_open_h264_adapter.h"
#include "api/video_codecs/video_encoder.h"
#include "api/video_codecs/video_encoder_factory.h"
#include "api/video_codecs/video_encoder_factory_template.h"
#include "api/video_codecs/video_encoder_factory_template_libaom_av1_adapter.h"
#include "api/video_codecs/video_encoder_factory_template_libvpx_vp8_adapter.h"
#include "api/video_codecs/video_encoder_factory_template_libvpx_vp9_adapter.h"
#include "api/video_codecs/video_encoder_factory_template_open_h264_adapter.h"
#include "media/engine/simulcast_encoder_adapter.h"
#include "p2p/test/fake_port_allocator.h"
#include "pc/test/fake_audio_capture_module.h"
#include "pc/test/fake_periodic_video_source.h"
#include "pc/test/fake_periodic_video_track_source.h"
#include "pc/test/fake_rtc_certificate_generator.h"
#include "pc/test/fake_video_track_renderer.h"
#include "pc/test/mock_peer_connection_observers.h"
#include "rtc_base/logging.h"
#include "rtc_base/rtc_certificate_generator.h"
#include "rtc_base/socket_server.h"
#include "system_wrappers/include/clock.h"
#include "test/gmock.h"
#include "test/gtest.h"
#include "test/wait_until.h"

namespace webrtc {
namespace {

const char kStreamIdBase[] = "stream_id";
const char kVideoTrackLabelBase[] = "video_track";
const char kAudioTrackLabelBase[] = "audio_track";
constexpr int kMaxWait = 10000;
constexpr int kTestAudioFrameCount = 3;
constexpr int kTestVideoFrameCount = 3;

class FuzzyMatchedVideoEncoderFactory : public VideoEncoderFactory {
 public:
  std::vector<SdpVideoFormat> GetSupportedFormats() const override {
    return factory_.GetSupportedFormats();
  }

  std::unique_ptr<VideoEncoder> Create(const Environment& env,
                                       const SdpVideoFormat& format) override {
    if (std::optional<SdpVideoFormat> original_format =
            FuzzyMatchSdpVideoFormat(factory_.GetSupportedFormats(), format)) {
      return std::make_unique<SimulcastEncoderAdapter>(env, &factory_, nullptr,
                                                       *original_format);
    }

    return nullptr;
  }

  CodecSupport QueryCodecSupport(
      const SdpVideoFormat& format,
      std::optional<std::string> scalability_mode) const override {
    return factory_.QueryCodecSupport(format, scalability_mode);
  }

 private:
  VideoEncoderFactoryTemplate<LibvpxVp8EncoderTemplateAdapter,
                              LibvpxVp9EncoderTemplateAdapter,
                              OpenH264EncoderTemplateAdapter,
                              LibaomAv1EncoderTemplateAdapter>
      factory_;
};
}  // namespace

void PeerConnectionTestWrapper::Connect(PeerConnectionTestWrapper* caller,
                                        PeerConnectionTestWrapper* callee) {
  caller->SubscribeOnIceCandidateReady(
      callee, [callee](const std::string& mid, int index,
                       const std::string& candidate) {
        callee->AddIceCandidate(mid, index, candidate);
      });
  callee->SubscribeOnIceCandidateReady(
      caller, [caller](const std::string& mid, int index,
                       const std::string& candidate) {
        caller->AddIceCandidate(mid, index, candidate);
      });
  caller->SubscribeOnSdpReady(callee, [callee](const std::string& sdp) {
    callee->ReceiveOfferSdp(sdp);
  });
  callee->SubscribeOnSdpReady(caller, [caller](const std::string& sdp) {
    caller->ReceiveAnswerSdp(sdp);
  });
}

void PeerConnectionTestWrapper::AwaitNegotiation(
    PeerConnectionTestWrapper* caller,
    PeerConnectionTestWrapper* callee) {
  auto offer = caller->AwaitCreateOffer();
  caller->AwaitSetLocalDescription(offer.get());
  callee->AwaitSetRemoteDescription(offer.get());
  auto answer = callee->AwaitCreateAnswer();
  callee->AwaitSetLocalDescription(answer.get());
  caller->AwaitSetRemoteDescription(answer.get());
}

PeerConnectionTestWrapper::PeerConnectionTestWrapper(
    const std::string& name,
    const Environment& env,
    SocketServer* socket_server,
    Thread* network_thread,
    Thread* worker_thread)
    : name_(name),
      env_(env),
      socket_server_(socket_server),
      network_thread_(network_thread),
      worker_thread_(worker_thread),
      pending_negotiation_(false) {
  pc_thread_checker_.Detach();
}

PeerConnectionTestWrapper::~PeerConnectionTestWrapper() {
  RTC_DCHECK_RUN_ON(&pc_thread_checker_);
  // To avoid flaky bot failures, make sure fake sources are stopped prior to
  // closing the peer connections. See https://crbug.com/webrtc/15018.
  StopFakeVideoSources();
  // Either network_thread or worker_thread might be active at this point.
  // Relying on ~PeerConnection to properly wait for them doesn't work,
  // as a vptr race might occur (before we enter the destruction body).
  // See: bugs.webrtc.org/9847
  if (pc()) {
    pc()->Close();
  }
}

bool PeerConnectionTestWrapper::CreatePc(
    const PeerConnectionInterface::RTCConfiguration& config,
    scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
    scoped_refptr<AudioDecoderFactory> audio_decoder_factory,
    std::unique_ptr<VideoEncoderFactory> video_encoder_factory,
    std::unique_ptr<VideoDecoderFactory> video_decoder_factory,
    std::unique_ptr<FieldTrialsView> field_trials) {
  EnvironmentFactory env_factory(env_);
  env_factory.Set(field_trials.get());
  Environment env = env_factory.Create();
  auto port_allocator =
      std::make_unique<FakePortAllocator>(env, socket_server_, network_thread_);

  RTC_DCHECK_RUN_ON(&pc_thread_checker_);

  fake_audio_capture_module_ = FakeAudioCaptureModule::Create();
  if (fake_audio_capture_module_ == nullptr) {
    return false;
  }

  peer_connection_factory_ = CreatePeerConnectionFactory(
      network_thread_, worker_thread_, Thread::Current(),
      scoped_refptr<AudioDeviceModule>(fake_audio_capture_module_),
      audio_encoder_factory, audio_decoder_factory,
      std::move(video_encoder_factory), std::move(video_decoder_factory),
      nullptr /* audio_mixer */, nullptr /* audio_processing */, nullptr,
      std::move(field_trials));
  if (!peer_connection_factory_) {
    return false;
  }

  std::unique_ptr<RTCCertificateGeneratorInterface> cert_generator(
      new FakeRTCCertificateGenerator());
  PeerConnectionDependencies deps(this);
  deps.allocator = std::move(port_allocator);
  deps.cert_generator = std::move(cert_generator);
  auto result = peer_connection_factory_->CreatePeerConnectionOrError(
      config, std::move(deps));
  if (result.ok()) {
    peer_connection_ = result.MoveValue();
    return true;
  } else {
    return false;
  }
}

bool PeerConnectionTestWrapper::CreatePc(
    const PeerConnectionInterface::RTCConfiguration& config,
    scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
    scoped_refptr<AudioDecoderFactory> audio_decoder_factory,
    std::unique_ptr<FieldTrialsView> field_trials) {
  return CreatePc(
      config, std::move(audio_encoder_factory),
      std::move(audio_decoder_factory),
      std::make_unique<FuzzyMatchedVideoEncoderFactory>(),
      std::make_unique<VideoDecoderFactoryTemplate<
          LibvpxVp8DecoderTemplateAdapter, LibvpxVp9DecoderTemplateAdapter,
          OpenH264DecoderTemplateAdapter, Dav1dDecoderTemplateAdapter>>(),
      std::move(field_trials));
}

scoped_refptr<DataChannelInterface>
PeerConnectionTestWrapper::CreateDataChannel(const std::string& label,
                                             const DataChannelInit& init) {
  auto result = peer_connection_->CreateDataChannelOrError(label, &init);
  if (!result.ok()) {
    RTC_LOG(LS_ERROR) << "CreateDataChannel failed: "
                      << ToString(result.error().type()) << " "
                      << result.error().message();
    return nullptr;
  }
  return result.MoveValue();
}

std::optional<RtpCodecCapability>
PeerConnectionTestWrapper::FindFirstSendCodecWithName(
    MediaType media_type,
    const std::string& name) const {
  std::vector<RtpCodecCapability> codecs =
      peer_connection_factory_->GetRtpSenderCapabilities(media_type).codecs;
  for (const auto& codec : codecs) {
    if (absl::EqualsIgnoreCase(codec.name, name)) {
      return codec;
    }
  }
  return std::nullopt;
}

void PeerConnectionTestWrapper::WaitForNegotiation() {
  EXPECT_THAT(
      WaitUntil([&] { return !pending_negotiation_; }, ::testing::IsTrue(),
                {.timeout = TimeDelta::Millis(kMaxWait)}),
      IsRtcOk());
}

std::unique_ptr<SessionDescriptionInterface>
PeerConnectionTestWrapper::AwaitCreateOffer() {
  auto observer = make_ref_counted<MockCreateSessionDescriptionObserver>();
  peer_connection_->CreateOffer(observer.get(), {});
  EXPECT_THAT(
      WaitUntil([&] { return observer->called(); }, ::testing::IsTrue()),
      IsRtcOk());
  return observer->MoveDescription();
}

std::unique_ptr<SessionDescriptionInterface>
PeerConnectionTestWrapper::AwaitCreateAnswer() {
  auto observer = make_ref_counted<MockCreateSessionDescriptionObserver>();
  peer_connection_->CreateAnswer(observer.get(), {});
  EXPECT_THAT(
      WaitUntil([&] { return observer->called(); }, ::testing::IsTrue()),
      IsRtcOk());
  return observer->MoveDescription();
}

void PeerConnectionTestWrapper::AwaitSetLocalDescription(
    webrtc::SessionDescriptionInterface* sdp) {
  auto observer = make_ref_counted<MockSetSessionDescriptionObserver>();
  peer_connection_->SetLocalDescription(observer.get(), sdp->Clone().release());
  EXPECT_THAT(
      WaitUntil([&] { return observer->called(); }, ::testing::IsTrue()),
      IsRtcOk());
}

void PeerConnectionTestWrapper::AwaitSetRemoteDescription(
    SessionDescriptionInterface* sdp) {
  auto observer = make_ref_counted<MockSetSessionDescriptionObserver>();
  peer_connection_->SetRemoteDescription(observer.get(),
                                         sdp->Clone().release());
  EXPECT_THAT(
      WaitUntil([&] { return observer->called(); }, ::testing::IsTrue()),
      IsRtcOk());
}

void PeerConnectionTestWrapper::ListenForRemoteIceCandidates(
    scoped_refptr<PeerConnectionTestWrapper> remote_wrapper) {
  remote_wrapper_ = remote_wrapper;
  remote_wrapper_->SubscribeOnIceCandidateReady(
      this,
      [this](const std::string& mid, int index, const std::string& candidate) {
        OnRemoteIceCandidate(mid, index, candidate);
      });
}

void PeerConnectionTestWrapper::AwaitAddRemoteIceCandidates() {
  EXPECT_TRUE(remote_wrapper_);
  EXPECT_THAT(
      WaitUntil(
          [&] {
            return remote_wrapper_->pc()->ice_gathering_state() ==
                   PeerConnectionInterface::kIceGatheringComplete;
          },
          ::testing::IsTrue(), {.timeout = TimeDelta::Millis(kMaxWait)}),
      IsRtcOk());
  for (const auto& remote_ice_candidate : remote_ice_candidates_) {
    peer_connection_->AddIceCandidate(remote_ice_candidate.get());
  }
  remote_wrapper_ = nullptr;
  remote_ice_candidates_.clear();
}

void PeerConnectionTestWrapper::OnRemoteIceCandidate(
    const std::string& sdp_mid,
    int sdp_mline_index,
    const std::string& candidate) {
  remote_ice_candidates_.emplace_back(
      CreateIceCandidate(sdp_mid, sdp_mline_index, candidate, nullptr));
}

void PeerConnectionTestWrapper::OnSignalingChange(
    PeerConnectionInterface::SignalingState new_state) {
  if (new_state == PeerConnectionInterface::SignalingState::kStable) {
    pending_negotiation_ = false;
  }
}

void PeerConnectionTestWrapper::OnAddTrack(
    scoped_refptr<RtpReceiverInterface> receiver,
    const std::vector<scoped_refptr<MediaStreamInterface>>& streams) {
  RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_ << ": OnAddTrack";
  if (receiver->track()->kind() == MediaStreamTrackInterface::kVideoKind) {
    auto* video_track =
        static_cast<VideoTrackInterface*>(receiver->track().get());
    renderer_ = std::make_unique<FakeVideoTrackRenderer>(video_track);
  }
}

void PeerConnectionTestWrapper::OnIceCandidate(const IceCandidate* candidate) {
  std::string sdp = candidate->ToString();
  NotifyOnIceCandidateReady(candidate->sdp_mid(), candidate->sdp_mline_index(),
                            sdp);
}

void PeerConnectionTestWrapper::OnDataChannel(
    scoped_refptr<DataChannelInterface> data_channel) {
  NotifyOnDataChannel(data_channel.get());
}

void PeerConnectionTestWrapper::OnSuccess(SessionDescriptionInterface* desc) {
  // This callback should take the ownership of `desc`.
  std::unique_ptr<SessionDescriptionInterface> owned_desc(desc);
  std::string sdp;
  EXPECT_TRUE(desc->ToString(&sdp));

  RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_ << ": "
                   << desc->GetType() << " sdp created: " << sdp;

  SetLocalDescription(desc->GetType(), sdp);

  NotifyOnSdpReady(sdp);
}

void PeerConnectionTestWrapper::CreateOffer(
    const PeerConnectionInterface::RTCOfferAnswerOptions& options) {
  RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_ << ": CreateOffer.";
  pending_negotiation_ = true;
  peer_connection_->CreateOffer(this, options);
}

void PeerConnectionTestWrapper::CreateAnswer(
    const PeerConnectionInterface::RTCOfferAnswerOptions& options) {
  RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_
                   << ": CreateAnswer.";
  pending_negotiation_ = true;
  peer_connection_->CreateAnswer(this, options);
}

void PeerConnectionTestWrapper::ReceiveOfferSdp(const std::string& sdp) {
  SetRemoteDescription(SdpType::kOffer, sdp);
  CreateAnswer(PeerConnectionInterface::RTCOfferAnswerOptions());
}

void PeerConnectionTestWrapper::ReceiveAnswerSdp(const std::string& sdp) {
  SetRemoteDescription(SdpType::kAnswer, sdp);
}

void PeerConnectionTestWrapper::SetLocalDescription(SdpType type,
                                                    const std::string& sdp) {
  RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_
                   << ": SetLocalDescription " << type << " " << sdp;

  auto observer = make_ref_counted<MockSetSessionDescriptionObserver>();
  peer_connection_->SetLocalDescription(
      observer.get(), CreateSessionDescription(type, sdp).release());
}

void PeerConnectionTestWrapper::SetRemoteDescription(SdpType type,
                                                     const std::string& sdp) {
  RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_
                   << ": SetRemoteDescription " << type << " " << sdp;

  auto observer = make_ref_counted<MockSetSessionDescriptionObserver>();
  peer_connection_->SetRemoteDescription(
      observer.get(), CreateSessionDescription(type, sdp).release());
}

void PeerConnectionTestWrapper::AddIceCandidate(const std::string& sdp_mid,
                                                int sdp_mline_index,
                                                const std::string& candidate) {
  std::unique_ptr<IceCandidate> owned_candidate(
      CreateIceCandidate(sdp_mid, sdp_mline_index, candidate, nullptr));
  EXPECT_TRUE(peer_connection_->AddIceCandidate(owned_candidate.get()));
}

bool PeerConnectionTestWrapper::WaitForCallEstablished() {
  if (!WaitForConnection())
    return false;
  if (!WaitForAudio())
    return false;
  if (!WaitForVideo())
    return false;
  return true;
}

bool PeerConnectionTestWrapper::WaitForConnection() {
  EXPECT_THAT(
      WaitUntil([&] { return CheckForConnection(); }, ::testing::IsTrue(),
                {.timeout = TimeDelta::Millis(kMaxWait)}),
      IsRtcOk());
  if (testing::Test::HasFailure()) {
    return false;
  }
  RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_ << ": Connected.";
  return true;
}

bool PeerConnectionTestWrapper::CheckForConnection() {
  return (peer_connection_->ice_connection_state() ==
          PeerConnectionInterface::kIceConnectionConnected) ||
         (peer_connection_->ice_connection_state() ==
          PeerConnectionInterface::kIceConnectionCompleted);
}

bool PeerConnectionTestWrapper::WaitForAudio() {
  EXPECT_THAT(WaitUntil([&] { return CheckForAudio(); }, ::testing::IsTrue(),
                        {.timeout = TimeDelta::Millis(kMaxWait)}),
              IsRtcOk());
  if (testing::Test::HasFailure()) {
    return false;
  }
  RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_
                   << ": Got enough audio frames.";
  return true;
}

bool PeerConnectionTestWrapper::CheckForAudio() {
  return (fake_audio_capture_module_->frames_received() >=
          kTestAudioFrameCount);
}

bool PeerConnectionTestWrapper::WaitForVideo() {
  EXPECT_THAT(WaitUntil([&] { return CheckForVideo(); }, ::testing::IsTrue(),
                        {.timeout = TimeDelta::Millis(kMaxWait)}),
              IsRtcOk());
  if (testing::Test::HasFailure()) {
    return false;
  }
  RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_
                   << ": Got enough video frames.";
  return true;
}

bool PeerConnectionTestWrapper::CheckForVideo() {
  if (!renderer_) {
    return false;
  }
  return (renderer_->num_rendered_frames() >= kTestVideoFrameCount);
}

void PeerConnectionTestWrapper::GetAndAddUserMedia(
    bool audio,
    const AudioOptions& audio_options,
    bool video) {
  scoped_refptr<MediaStreamInterface> stream =
      GetUserMedia(audio, audio_options, video);
  for (const auto& audio_track : stream->GetAudioTracks()) {
    EXPECT_TRUE(peer_connection_->AddTrack(audio_track, {stream->id()}).ok());
  }
  for (const auto& video_track : stream->GetVideoTracks()) {
    EXPECT_TRUE(peer_connection_->AddTrack(video_track, {stream->id()}).ok());
  }
}

scoped_refptr<MediaStreamInterface> PeerConnectionTestWrapper::GetUserMedia(
    bool audio,
    const AudioOptions& audio_options,
    bool video,
    Resolution resolution) {
  std::string stream_id =
      kStreamIdBase + absl::StrCat(num_get_user_media_calls_++);
  scoped_refptr<MediaStreamInterface> stream =
      peer_connection_factory_->CreateLocalMediaStream(stream_id);

  if (audio) {
    AudioOptions options = audio_options;
    // Disable highpass filter so that we can get all the test audio frames.
    options.highpass_filter = false;
    scoped_refptr<AudioSourceInterface> source =
        peer_connection_factory_->CreateAudioSource(options);
    scoped_refptr<AudioTrackInterface> audio_track(
        peer_connection_factory_->CreateAudioTrack(kAudioTrackLabelBase,
                                                   source.get()));
    stream->AddTrack(audio_track);
  }

  if (video) {
    // Set max frame rate to 10fps to reduce the risk of the tests to be flaky.
    FakePeriodicVideoSource::Config config;
    config.frame_interval = TimeDelta::Millis(100);
    config.timestamp_offset = env_.clock().CurrentTime();
    config.width = resolution.width;
    config.height = resolution.height;

    auto source = make_ref_counted<FakePeriodicVideoTrackSource>(
        config, /* remote */ false);
    fake_video_sources_.push_back(source);

    std::string videotrack_label = stream_id + kVideoTrackLabelBase;
    scoped_refptr<VideoTrackInterface> video_track(
        peer_connection_factory_->CreateVideoTrack(source, videotrack_label));

    stream->AddTrack(video_track);
  }
  return stream;
}

void PeerConnectionTestWrapper::StopFakeVideoSources() {
  for (const auto& fake_video_source : fake_video_sources_) {
    fake_video_source->fake_periodic_source().Stop();
  }
  fake_video_sources_.clear();
}

}  // namespace webrtc
