/*
 *  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,
      MediaTransportInterface* media_transport,
      DataChannelTransportInterface* data_channel_transport,
      JsepTransportController::NegotiationState negotiation_state) override;

  void OnRtcpPacketReceived(rtc::CopyOnWriteBuffer* packet_ptr,
                            int64_t packet_time_us);
  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 absl::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, false));
    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;
  return config;
}

void ScenarioIceConnectionImpl::SendRtpPacket(
    rtc::ArrayView<const uint8_t> packet_view) {
  rtc::CopyOnWriteBuffer packet(packet_view.data(), packet_view.size(),
                                ::cricket::kMaxRtpPacketLen);
  // TODO(srte): Move |packet| into lambda when we have c++14.
  network_thread_->PostTask(RTC_FROM_HERE, [this, packet]() mutable {
    RTC_DCHECK_RUN_ON(network_thread_);
    if (rtp_transport_ == nullptr)
      return;
    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);
  // TODO(srte): Move |packet| into lambda when we have c++14.
  network_thread_->PostTask(RTC_FROM_HERE, [this, packet]() mutable {
    RTC_DCHECK_RUN_ON(network_thread_);
    if (rtp_transport_ == nullptr)
      return;
    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,
    MediaTransportInterface* media_transport,
    DataChannelTransportInterface* data_channel_transport,
    JsepTransportController::NegotiationState negotiation_state) {
  RTC_DCHECK_RUN_ON(network_thread_);
  if (rtp_transport == nullptr) {
    rtp_transport_->SignalRtcpPacketReceived.disconnect(this);
    rtp_transport_->UnregisterRtpDemuxerSink(this);
  } else {
    RTC_DCHECK(rtp_transport_ == nullptr || rtp_transport_ == rtp_transport);
    if (rtp_transport_ != rtp_transport) {
      rtp_transport_ = rtp_transport;
      rtp_transport_->SignalRtcpPacketReceived.connect(
          this, &ScenarioIceConnectionImpl::OnRtcpPacketReceived);
    }
    RtpDemuxerCriteria criteria;
    criteria.mid = mid;
    rtp_transport_->RegisterRtpDemuxerSink(criteria, this);
  }
  return true;
}

void ScenarioIceConnectionImpl::OnRtcpPacketReceived(
    rtc::CopyOnWriteBuffer* packet,
    int64_t packet_time_us) {
  RTC_DCHECK_RUN_ON(network_thread_);
  observer_->OnPacketReceived(*packet);
}

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
