/*
 *  Copyright (c) 2021 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 "rtc_tools/data_channel_benchmark/peer_connection_client.h"

#include <memory>
#include <string>
#include <utility>

#include "api/audio/audio_device.h"
#include "api/audio/audio_mixer.h"
#include "api/audio/audio_processing.h"
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "api/audio_codecs/builtin_audio_encoder_factory.h"
#include "api/create_peerconnection_factory.h"
#include "api/jsep.h"
#include "api/peer_connection_interface.h"
#include "api/rtc_error.h"
#include "api/scoped_refptr.h"
#include "api/set_local_description_observer_interface.h"
#include "api/set_remote_description_observer_interface.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_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 "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/ref_counted_object.h"
#include "rtc_base/thread.h"

namespace {

constexpr char kStunServer[] = "stun:stun.l.google.com:19302";

class SetLocalDescriptionObserverAdapter
    : public webrtc::SetLocalDescriptionObserverInterface {
 public:
  using Callback = std::function<void(webrtc::RTCError)>;
  static rtc::scoped_refptr<SetLocalDescriptionObserverAdapter> Create(
      Callback callback) {
    return rtc::scoped_refptr<SetLocalDescriptionObserverAdapter>(
        new rtc::RefCountedObject<SetLocalDescriptionObserverAdapter>(
            std::move(callback)));
  }

  explicit SetLocalDescriptionObserverAdapter(Callback callback)
      : callback_(std::move(callback)) {}
  ~SetLocalDescriptionObserverAdapter() override = default;

 private:
  void OnSetLocalDescriptionComplete(webrtc::RTCError error) override {
    callback_(std::move(error));
  }

  Callback callback_;
};

class SetRemoteDescriptionObserverAdapter
    : public webrtc::SetRemoteDescriptionObserverInterface {
 public:
  using Callback = std::function<void(webrtc::RTCError)>;
  static rtc::scoped_refptr<SetRemoteDescriptionObserverAdapter> Create(
      Callback callback) {
    return rtc::scoped_refptr<SetRemoteDescriptionObserverAdapter>(
        new rtc::RefCountedObject<SetRemoteDescriptionObserverAdapter>(
            std::move(callback)));
  }

  explicit SetRemoteDescriptionObserverAdapter(Callback callback)
      : callback_(std::move(callback)) {}
  ~SetRemoteDescriptionObserverAdapter() override = default;

 private:
  void OnSetRemoteDescriptionComplete(webrtc::RTCError error) override {
    callback_(std::move(error));
  }

  Callback callback_;
};

class CreateSessionDescriptionObserverAdapter
    : public webrtc::CreateSessionDescriptionObserver {
 public:
  using Success = std::function<void(webrtc::SessionDescriptionInterface*)>;
  using Failure = std::function<void(webrtc::RTCError)>;

  static rtc::scoped_refptr<CreateSessionDescriptionObserverAdapter> Create(
      Success success,
      Failure failure) {
    return rtc::scoped_refptr<CreateSessionDescriptionObserverAdapter>(
        new rtc::RefCountedObject<CreateSessionDescriptionObserverAdapter>(
            std::move(success), std::move(failure)));
  }

  CreateSessionDescriptionObserverAdapter(Success success, Failure failure)
      : success_(std::move(success)), failure_(std::move(failure)) {}
  ~CreateSessionDescriptionObserverAdapter() override = default;

 private:
  void OnSuccess(webrtc::SessionDescriptionInterface* desc) override {
    success_(desc);
  }

  void OnFailure(webrtc::RTCError error) override {
    failure_(std::move(error));
  }

  Success success_;
  Failure failure_;
};

}  // namespace

namespace webrtc {

PeerConnectionClient::PeerConnectionClient(
    webrtc::PeerConnectionFactoryInterface* factory,
    webrtc::SignalingInterface* signaling)
    : signaling_(signaling) {
  signaling_->OnIceCandidate(
      [&](std::unique_ptr<webrtc::IceCandidateInterface> candidate) {
        AddIceCandidate(std::move(candidate));
      });
  signaling_->OnRemoteDescription(
      [&](std::unique_ptr<webrtc::SessionDescriptionInterface> sdp) {
        SetRemoteDescription(std::move(sdp));
      });
  InitializePeerConnection(factory);
}

PeerConnectionClient::~PeerConnectionClient() {
  Disconnect();
}

rtc::scoped_refptr<PeerConnectionFactoryInterface>
PeerConnectionClient::CreateDefaultFactory(rtc::Thread* signaling_thread) {
  auto factory = webrtc::CreatePeerConnectionFactory(
      /*network_thread=*/nullptr, /*worker_thread=*/nullptr,
      /*signaling_thread*/ signaling_thread,
      /*default_adm=*/nullptr, webrtc::CreateBuiltinAudioEncoderFactory(),
      webrtc::CreateBuiltinAudioDecoderFactory(),
      std::make_unique<VideoEncoderFactoryTemplate<
          LibvpxVp8EncoderTemplateAdapter, LibvpxVp9EncoderTemplateAdapter,
          OpenH264EncoderTemplateAdapter, LibaomAv1EncoderTemplateAdapter>>(),
      std::make_unique<VideoDecoderFactoryTemplate<
          LibvpxVp8DecoderTemplateAdapter, LibvpxVp9DecoderTemplateAdapter,
          OpenH264DecoderTemplateAdapter, Dav1dDecoderTemplateAdapter>>(),
      /*audio_mixer=*/nullptr, /*audio_processing=*/nullptr);

  if (!factory) {
    RTC_LOG(LS_ERROR) << "Failed to initialize PeerConnectionFactory";
    return nullptr;
  }

  return factory;
}

bool PeerConnectionClient::InitializePeerConnection(
    webrtc::PeerConnectionFactoryInterface* factory) {
  RTC_CHECK(factory)
      << "Must call InitializeFactory before InitializePeerConnection";

  webrtc::PeerConnectionInterface::RTCConfiguration config;
  webrtc::PeerConnectionInterface::IceServer server;
  server.urls.push_back(kStunServer);
  config.servers.push_back(server);
  config.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan;

  webrtc::PeerConnectionDependencies dependencies(this);
  auto result =
      factory->CreatePeerConnectionOrError(config, std::move(dependencies));

  if (!result.ok()) {
    RTC_LOG(LS_ERROR) << "Failed to create PeerConnection: "
                      << result.error().message();
    DeletePeerConnection();
    return false;
  }
  peer_connection_ = result.MoveValue();
  RTC_LOG(LS_INFO) << "PeerConnection created successfully";
  return true;
}

bool PeerConnectionClient::StartPeerConnection() {
  RTC_LOG(LS_INFO) << "Creating offer";

  peer_connection_->SetLocalDescription(
      SetLocalDescriptionObserverAdapter::Create([this](
                                                     webrtc::RTCError error) {
        if (error.ok())
          signaling_->SendDescription(peer_connection_->local_description());
      }));

  return true;
}

bool PeerConnectionClient::IsConnected() {
  return peer_connection_->peer_connection_state() ==
         webrtc::PeerConnectionInterface::PeerConnectionState::kConnected;
}

// Disconnect from the call.
void PeerConnectionClient::Disconnect() {
  for (auto& data_channel : data_channels_) {
    data_channel->Close();
    data_channel.release();
  }
  data_channels_.clear();
  DeletePeerConnection();
}

// Delete the WebRTC PeerConnection.
void PeerConnectionClient::DeletePeerConnection() {
  RTC_LOG(LS_INFO);

  if (peer_connection_) {
    peer_connection_->Close();
  }
  peer_connection_.release();
}

void PeerConnectionClient::OnIceConnectionChange(
    webrtc::PeerConnectionInterface::IceConnectionState new_state) {
  if (new_state == webrtc::PeerConnectionInterface::IceConnectionState::
                       kIceConnectionCompleted) {
    RTC_LOG(LS_INFO) << "State is updating to connected";
  } else if (new_state == webrtc::PeerConnectionInterface::IceConnectionState::
                              kIceConnectionDisconnected) {
    RTC_LOG(LS_INFO) << "Disconnecting from peer";
    Disconnect();
  }
}

void PeerConnectionClient::OnIceGatheringChange(
    webrtc::PeerConnectionInterface::IceGatheringState new_state) {
  if (new_state == webrtc::PeerConnectionInterface::kIceGatheringComplete) {
    RTC_LOG(LS_INFO) << "Client is ready to receive remote SDP";
  }
}

void PeerConnectionClient::OnIceCandidate(
    const webrtc::IceCandidateInterface* candidate) {
  signaling_->SendIceCandidate(candidate);
}

void PeerConnectionClient::OnDataChannel(
    rtc::scoped_refptr<webrtc::DataChannelInterface> channel) {
  RTC_LOG(LS_INFO) << __FUNCTION__ << " remote datachannel created";
  if (on_data_channel_callback_)
    on_data_channel_callback_(channel);
  data_channels_.push_back(channel);
}

void PeerConnectionClient::SetOnDataChannel(
    std::function<void(rtc::scoped_refptr<webrtc::DataChannelInterface>)>
        callback) {
  on_data_channel_callback_ = callback;
}

void PeerConnectionClient::OnNegotiationNeededEvent(uint32_t event_id) {
  RTC_LOG(LS_INFO) << "OnNegotiationNeededEvent";

  peer_connection_->SetLocalDescription(
      SetLocalDescriptionObserverAdapter::Create([this](
                                                     webrtc::RTCError error) {
        if (error.ok())
          signaling_->SendDescription(peer_connection_->local_description());
      }));
}

bool PeerConnectionClient::SetRemoteDescription(
    std::unique_ptr<webrtc::SessionDescriptionInterface> desc) {
  RTC_LOG(LS_INFO) << "SetRemoteDescription";
  auto type = desc->GetType();

  peer_connection_->SetRemoteDescription(
      std::move(desc),
      SetRemoteDescriptionObserverAdapter::Create([&](webrtc::RTCError) {
        RTC_LOG(LS_INFO) << "SetRemoteDescription done";

        if (type == webrtc::SdpType::kOffer) {
          // Got an offer from the remote, need to set an answer and send it.
          peer_connection_->SetLocalDescription(
              SetLocalDescriptionObserverAdapter::Create(
                  [this](webrtc::RTCError error) {
                    if (error.ok())
                      signaling_->SendDescription(
                          peer_connection_->local_description());
                  }));
        }
      }));

  return true;
}

void PeerConnectionClient::AddIceCandidate(
    std::unique_ptr<webrtc::IceCandidateInterface> candidate) {
  RTC_LOG(LS_INFO) << "AddIceCandidate";

  peer_connection_->AddIceCandidate(
      std::move(candidate), [](const webrtc::RTCError& error) {
        RTC_LOG(LS_INFO) << "Failed to add candidate: " << error.message();
      });
}

}  // namespace webrtc
