/*
 *  Copyright (c) 2019 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 "test/peer_scenario/scenario_connection.h"

#include "absl/memory/memory.h"
#include "media/base/rtp_utils.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "p2p/client/basic_port_allocator.h"
#include "pc/jsep_transport_controller.h"
#include "pc/rtp_transport_internal.h"
#include "pc/session_description.h"

namespace webrtc {
class ScenarioIceConnectionImpl : public ScenarioIceConnection,
                                  public sigslot::has_slots<>,
                                  private JsepTransportController::Observer,
                                  private RtpPacketSinkInterface {
 public:
  ScenarioIceConnectionImpl(test::NetworkEmulationManagerImpl* net,
                            IceConnectionObserver* observer);
  ~ScenarioIceConnectionImpl() override;

  void SendRtpPacket(rtc::ArrayView<const uint8_t> packet_view) override;
  void SendRtcpPacket(rtc::ArrayView<const uint8_t> packet_view) override;

  void SetRemoteSdp(SdpType type, const std::string& remote_sdp) override;
  void SetLocalSdp(SdpType type, const std::string& local_sdp) override;

  EmulatedEndpoint* endpoint() override { return endpoint_; }
  const cricket::TransportDescription& transport_description() const override {
    return transport_description_;
  }

 private:
  JsepTransportController::Config CreateJsepConfig();
  bool OnTransportChanged(
      const std::string& mid,
      RtpTransportInternal* rtp_transport,
      rtc::scoped_refptr<DtlsTransport> dtls_transport,
      DataChannelTransportInterface* data_channel_transport) override;

  void OnRtpPacket(const RtpPacketReceived& packet) override;
  void OnCandidates(const std::string& mid,
                    const std::vector<cricket::Candidate>& candidates);

  IceConnectionObserver* const observer_;
  EmulatedEndpoint* const endpoint_;
  EmulatedNetworkManagerInterface* const manager_;
  rtc::Thread* const signaling_thread_;
  rtc::Thread* const network_thread_;
  rtc::scoped_refptr<rtc::RTCCertificate> const certificate_
      RTC_GUARDED_BY(network_thread_);
  cricket::TransportDescription const transport_description_
      RTC_GUARDED_BY(signaling_thread_);
  std::unique_ptr<cricket::BasicPortAllocator> port_allocator_
      RTC_GUARDED_BY(network_thread_);
  std::unique_ptr<JsepTransportController> jsep_controller_;
  RtpTransportInternal* rtp_transport_ RTC_GUARDED_BY(network_thread_) =
      nullptr;
  std::unique_ptr<SessionDescriptionInterface> remote_description_
      RTC_GUARDED_BY(signaling_thread_);
  std::unique_ptr<SessionDescriptionInterface> local_description_
      RTC_GUARDED_BY(signaling_thread_);
};

std::unique_ptr<ScenarioIceConnection> ScenarioIceConnection::Create(
    webrtc::test::NetworkEmulationManagerImpl* net,
    IceConnectionObserver* observer) {
  return std::make_unique<ScenarioIceConnectionImpl>(net, observer);
}

ScenarioIceConnectionImpl::ScenarioIceConnectionImpl(
    test::NetworkEmulationManagerImpl* net,
    IceConnectionObserver* observer)
    : observer_(observer),
      endpoint_(net->CreateEndpoint(EmulatedEndpointConfig())),
      manager_(net->CreateEmulatedNetworkManagerInterface({endpoint_})),
      signaling_thread_(rtc::Thread::Current()),
      network_thread_(manager_->network_thread()),
      certificate_(rtc::RTCCertificate::Create(
          absl::WrapUnique(rtc::SSLIdentity::Generate("", ::rtc::KT_DEFAULT)))),
      transport_description_(
          /*transport_options*/ {},
          rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH),
          rtc::CreateRandomString(cricket::ICE_PWD_LENGTH),
          cricket::IceMode::ICEMODE_FULL,
          cricket::ConnectionRole::CONNECTIONROLE_PASSIVE,
          rtc::SSLFingerprint::CreateFromCertificate(*certificate_.get())
              .get()),
      port_allocator_(
          new cricket::BasicPortAllocator(manager_->network_manager())),
      jsep_controller_(
          new JsepTransportController(signaling_thread_,
                                      network_thread_,
                                      port_allocator_.get(),
                                      /*async_resolver_factory*/ nullptr,
                                      CreateJsepConfig())) {
  network_thread_->Invoke<void>(RTC_FROM_HERE, [this] {
    RTC_DCHECK_RUN_ON(network_thread_);
    uint32_t flags = cricket::PORTALLOCATOR_DISABLE_TCP;
    port_allocator_->set_flags(port_allocator_->flags() | flags);
    port_allocator_->Initialize();
    RTC_CHECK(port_allocator_->SetConfiguration(/*stun_servers*/ {},
                                                /*turn_servers*/ {}, 0,
                                                webrtc::NO_PRUNE));
    jsep_controller_->SetLocalCertificate(certificate_);
  });
}

ScenarioIceConnectionImpl::~ScenarioIceConnectionImpl() {
  network_thread_->Invoke<void>(RTC_FROM_HERE, [this] {
    RTC_DCHECK_RUN_ON(network_thread_);
    jsep_controller_.reset();
    port_allocator_.reset();
    rtp_transport_ = nullptr;
  });
}

JsepTransportController::Config ScenarioIceConnectionImpl::CreateJsepConfig() {
  JsepTransportController::Config config;
  config.transport_observer = this;
  config.bundle_policy =
      PeerConnectionInterface::BundlePolicy::kBundlePolicyMaxBundle;
  config.rtcp_handler = [this](const rtc::CopyOnWriteBuffer& packet,
                               int64_t packet_time_us) {
    RTC_DCHECK_RUN_ON(network_thread_);
    observer_->OnPacketReceived(packet);
  };
  return config;
}

void ScenarioIceConnectionImpl::SendRtpPacket(
    rtc::ArrayView<const uint8_t> packet_view) {
  rtc::CopyOnWriteBuffer packet(packet_view.data(), packet_view.size(),
                                ::cricket::kMaxRtpPacketLen);
  network_thread_->PostTask(
      RTC_FROM_HERE, [this, packet = std::move(packet)]() mutable {
        RTC_DCHECK_RUN_ON(network_thread_);
        if (rtp_transport_ != nullptr)
          rtp_transport_->SendRtpPacket(&packet, rtc::PacketOptions(),
                                        cricket::PF_SRTP_BYPASS);
      });
}

void ScenarioIceConnectionImpl::SendRtcpPacket(
    rtc::ArrayView<const uint8_t> packet_view) {
  rtc::CopyOnWriteBuffer packet(packet_view.data(), packet_view.size(),
                                ::cricket::kMaxRtpPacketLen);
  network_thread_->PostTask(
      RTC_FROM_HERE, [this, packet = std::move(packet)]() mutable {
        RTC_DCHECK_RUN_ON(network_thread_);
        if (rtp_transport_ != nullptr)
          rtp_transport_->SendRtcpPacket(&packet, rtc::PacketOptions(),
                                         cricket::PF_SRTP_BYPASS);
      });
}
void ScenarioIceConnectionImpl::SetRemoteSdp(SdpType type,
                                             const std::string& remote_sdp) {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  remote_description_ = webrtc::CreateSessionDescription(type, remote_sdp);
  jsep_controller_->SignalIceCandidatesGathered.connect(
      this, &ScenarioIceConnectionImpl::OnCandidates);
  auto res = jsep_controller_->SetRemoteDescription(
      remote_description_->GetType(), remote_description_->description());
  RTC_CHECK(res.ok()) << res.message();
  RtpDemuxerCriteria criteria;
  for (const auto& content : remote_description_->description()->contents()) {
    if (content.media_description()->as_audio()) {
      for (const auto& codec :
           content.media_description()->as_audio()->codecs()) {
        criteria.payload_types.insert(codec.id);
      }
    }
    if (content.media_description()->as_video()) {
      for (const auto& codec :
           content.media_description()->as_video()->codecs()) {
        criteria.payload_types.insert(codec.id);
      }
    }
  }

  network_thread_->PostTask(RTC_FROM_HERE, [this, criteria]() {
    RTC_DCHECK_RUN_ON(network_thread_);
    RTC_DCHECK(rtp_transport_);
    rtp_transport_->RegisterRtpDemuxerSink(criteria, this);
  });
}

void ScenarioIceConnectionImpl::SetLocalSdp(SdpType type,
                                            const std::string& local_sdp) {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  local_description_ = webrtc::CreateSessionDescription(type, local_sdp);
  auto res = jsep_controller_->SetLocalDescription(
      local_description_->GetType(), local_description_->description());
  RTC_CHECK(res.ok()) << res.message();
  jsep_controller_->MaybeStartGathering();
}

bool ScenarioIceConnectionImpl::OnTransportChanged(
    const std::string& mid,
    RtpTransportInternal* rtp_transport,
    rtc::scoped_refptr<DtlsTransport> dtls_transport,
    DataChannelTransportInterface* data_channel_transport) {
  RTC_DCHECK_RUN_ON(network_thread_);
  if (rtp_transport == nullptr) {
    rtp_transport_->UnregisterRtpDemuxerSink(this);
  } else {
    RTC_DCHECK(rtp_transport_ == nullptr || rtp_transport_ == rtp_transport);
    if (rtp_transport_ != rtp_transport) {
      rtp_transport_ = rtp_transport;
    }
    RtpDemuxerCriteria criteria;
    criteria.mid = mid;
    rtp_transport_->RegisterRtpDemuxerSink(criteria, this);
  }
  return true;
}

void ScenarioIceConnectionImpl::OnRtpPacket(const RtpPacketReceived& packet) {
  RTC_DCHECK_RUN_ON(network_thread_);
  observer_->OnPacketReceived(packet.Buffer());
}

void ScenarioIceConnectionImpl::OnCandidates(
    const std::string& mid,
    const std::vector<cricket::Candidate>& candidates) {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  observer_->OnIceCandidates(mid, candidates);
}

}  // namespace webrtc
