/*
 *  Copyright 2017 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/peer_connection_wrapper.h"

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

#include "api/data_channel_interface.h"
#include "api/function_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_sender_interface.h"
#include "api/rtp_transceiver_interface.h"
#include "api/scoped_refptr.h"
#include "api/stats/rtc_stats_report.h"
#include "api/units/time_delta.h"
#include "pc/peer_connection.h"
#include "pc/peer_connection_proxy.h"
#include "pc/test/fake_video_track_source.h"
#include "pc/test/mock_peer_connection_observers.h"
#include "rtc_base/checks.h"
#include "rtc_base/event.h"
#include "rtc_base/logging.h"
#include "test/gmock.h"
#include "test/gtest.h"
#include "test/run_loop.h"
#include "test/wait_until.h"

namespace webrtc {

using ::testing::Eq;
using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;

PeerConnectionWrapper::PeerConnectionWrapper(
    scoped_refptr<PeerConnectionFactoryInterface> pc_factory,
    scoped_refptr<PeerConnectionInterface> pc,
    std::unique_ptr<MockPeerConnectionObserver> observer)
    : pc_factory_(std::move(pc_factory)),
      observer_(std::move(observer)),
      pc_(std::move(pc)) {
  RTC_DCHECK(pc_factory_);
  RTC_DCHECK(pc_);
  RTC_DCHECK(observer_);
  observer_->SetPeerConnectionInterface(pc_.get());
}

PeerConnectionWrapper::~PeerConnectionWrapper() {
  if (pc_)
    pc_->Close();
}

PeerConnectionFactoryInterface* PeerConnectionWrapper::pc_factory() {
  return pc_factory_.get();
}

PeerConnectionInterface* PeerConnectionWrapper::pc() {
  return pc_.get();
}

MockPeerConnectionObserver* PeerConnectionWrapper::observer() {
  return observer_.get();
}

PeerConnection* PeerConnectionWrapper::GetInternalPeerConnection() {
  auto* pci =
      static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
          pc());
  return static_cast<PeerConnection*>(pci->internal());
}

const PeerConnection* PeerConnectionWrapper::GetInternalPeerConnection() const {
  const auto* pci = static_cast<
      const PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
      pc_.get());
  return static_cast<const PeerConnection*>(pci->internal());
}

std::unique_ptr<SessionDescriptionInterface>
PeerConnectionWrapper::CreateOffer() {
  return CreateOffer(RTCOfferAnswerOptions());
}

std::unique_ptr<SessionDescriptionInterface> PeerConnectionWrapper::CreateOffer(
    const PeerConnectionInterface::RTCOfferAnswerOptions& options,
    std::string* error_out) {
  return CreateSdp(
      [this, options](CreateSessionDescriptionObserver* observer) {
        pc()->CreateOffer(observer, options);
      },
      error_out);
}

std::unique_ptr<SessionDescriptionInterface>
PeerConnectionWrapper::CreateOfferAndSetAsLocal() {
  return CreateOfferAndSetAsLocal(RTCOfferAnswerOptions());
}

std::unique_ptr<SessionDescriptionInterface>
PeerConnectionWrapper::CreateOfferAndSetAsLocal(
    const PeerConnectionInterface::RTCOfferAnswerOptions& options) {
  std::unique_ptr<SessionDescriptionInterface> offer = CreateOffer(options);
  if (!offer) {
    return nullptr;
  }
  EXPECT_TRUE(SetLocalDescription(offer->Clone()));
  return offer;
}

std::unique_ptr<SessionDescriptionInterface>
PeerConnectionWrapper::CreateAnswer() {
  return CreateAnswer(RTCOfferAnswerOptions());
}

std::unique_ptr<SessionDescriptionInterface>
PeerConnectionWrapper::CreateAnswer(
    const PeerConnectionInterface::RTCOfferAnswerOptions& options,
    std::string* error_out) {
  return CreateSdp(
      [this, options](CreateSessionDescriptionObserver* observer) {
        pc()->CreateAnswer(observer, options);
      },
      error_out);
}

std::unique_ptr<SessionDescriptionInterface>
PeerConnectionWrapper::CreateAnswerAndSetAsLocal() {
  return CreateAnswerAndSetAsLocal(RTCOfferAnswerOptions());
}

std::unique_ptr<SessionDescriptionInterface>
PeerConnectionWrapper::CreateAnswerAndSetAsLocal(
    const PeerConnectionInterface::RTCOfferAnswerOptions& options) {
  std::unique_ptr<SessionDescriptionInterface> answer = CreateAnswer(options);
  if (!answer) {
    return nullptr;
  }
  EXPECT_TRUE(SetLocalDescription(answer->Clone()));
  return answer;
}

std::unique_ptr<SessionDescriptionInterface>
PeerConnectionWrapper::CreateRollback() {
  return CreateRollbackSessionDescription();
}

std::unique_ptr<SessionDescriptionInterface> PeerConnectionWrapper::CreateSdp(
    FunctionView<void(CreateSessionDescriptionObserver*)> fn,
    std::string* error_out) {
  // Tests in SdpMungingTest call this method from outside the signaling thread.
  const bool signaling_is_current =
      GetInternalPeerConnection()->signaling_thread()->IsCurrent();
  Event done;
  auto observer = make_ref_counted<MockCreateSessionDescriptionObserver>(
      [&]() { done.Set(); });
  fn(observer.get());
  if (signaling_is_current) {
    EXPECT_TRUE(WaitUntil([&] { return observer->called(); }));
  } else {
    done.Wait(Event::kForever);
    EXPECT_TRUE(observer->called());
  }
  if (error_out && !observer->result()) {
    *error_out = observer->error();
  }
  return observer->MoveDescription();
}

bool PeerConnectionWrapper::SetLocalDescription(
    std::unique_ptr<SessionDescriptionInterface> desc,
    std::string* error_out) {
  return SetSdp(
      [this, &desc](SetSessionDescriptionObserver* observer) {
        pc()->SetLocalDescription(observer, desc.release());
      },
      error_out);
}

bool PeerConnectionWrapper::SetLocalDescription(
    std::unique_ptr<SessionDescriptionInterface> desc,
    RTCError* error_out) {
  auto observer = make_ref_counted<FakeSetLocalDescriptionObserver>();
  pc()->SetLocalDescription(std::move(desc), observer);
  EXPECT_TRUE(WaitUntil([&] { return observer->called(); }));
  bool ok = observer->error().ok();
  if (error_out)
    *error_out = std::move(observer->error());
  return ok;
}

bool PeerConnectionWrapper::SetRemoteDescription(
    std::unique_ptr<SessionDescriptionInterface> desc,
    std::string* error_out) {
  return SetSdp(
      [this, &desc](SetSessionDescriptionObserver* observer) {
        pc()->SetRemoteDescription(observer, desc.release());
      },
      error_out);
}

bool PeerConnectionWrapper::SetRemoteDescription(
    std::unique_ptr<SessionDescriptionInterface> desc,
    RTCError* error_out) {
  auto observer = make_ref_counted<FakeSetRemoteDescriptionObserver>();
  pc()->SetRemoteDescription(std::move(desc), observer);
  EXPECT_TRUE(WaitUntil([&] { return observer->called(); }));
  bool ok = observer->error().ok();
  if (error_out)
    *error_out = std::move(observer->error());
  return ok;
}

bool PeerConnectionWrapper::SetSdp(
    FunctionView<void(SetSessionDescriptionObserver*)> fn,
    std::string* error_out) {
  auto observer = make_ref_counted<MockSetSessionDescriptionObserver>();
  fn(observer.get());
  EXPECT_TRUE(WaitUntil([&] { return observer->called(); }));
  if (error_out && !observer->result()) {
    *error_out = observer->error();
  }
  return observer->result();
}

bool PeerConnectionWrapper::ExchangeOfferAnswerWith(
    PeerConnectionWrapper* answerer) {
  return ExchangeOfferAnswerWith(answerer, RTCOfferAnswerOptions(),
                                 RTCOfferAnswerOptions());
}

bool PeerConnectionWrapper::ExchangeOfferAnswerWith(
    PeerConnectionWrapper* answerer,
    const PeerConnectionInterface::RTCOfferAnswerOptions& offer_options,
    const PeerConnectionInterface::RTCOfferAnswerOptions& answer_options) {
  RTC_DCHECK(answerer);
  if (answerer == this) {
    RTC_LOG(LS_ERROR) << "Cannot exchange offer/answer with ourself!";
    return false;
  }
  std::unique_ptr<SessionDescriptionInterface> offer =
      CreateOffer(offer_options);
  EXPECT_TRUE(offer);
  if (!offer) {
    return false;
  }
  bool set_local_offer = SetLocalDescription(offer->Clone());
  EXPECT_TRUE(set_local_offer);
  if (!set_local_offer) {
    return false;
  }
  bool set_remote_offer = answerer->SetRemoteDescription(std::move(offer));
  EXPECT_TRUE(set_remote_offer);
  if (!set_remote_offer) {
    return false;
  }
  std::unique_ptr<SessionDescriptionInterface> answer =
      answerer->CreateAnswer(answer_options);
  EXPECT_TRUE(answer);
  if (!answer) {
    return false;
  }
  bool set_local_answer = answerer->SetLocalDescription(answer->Clone());
  EXPECT_TRUE(set_local_answer);
  if (!set_local_answer) {
    return false;
  }
  bool set_remote_answer = SetRemoteDescription(std::move(answer));
  EXPECT_TRUE(set_remote_answer);
  return set_remote_answer;
}

scoped_refptr<RtpTransceiverInterface> PeerConnectionWrapper::AddTransceiver(
    MediaType media_type) {
  RTCErrorOr<scoped_refptr<RtpTransceiverInterface>> result =
      pc()->AddTransceiver(media_type);
  EXPECT_EQ(RTCErrorType::NONE, result.error().type());
  return result.MoveValue();
}

scoped_refptr<RtpTransceiverInterface> PeerConnectionWrapper::AddTransceiver(
    MediaType media_type,
    const RtpTransceiverInit& init) {
  RTCErrorOr<scoped_refptr<RtpTransceiverInterface>> result =
      pc()->AddTransceiver(media_type, init);
  EXPECT_EQ(RTCErrorType::NONE, result.error().type());
  return result.MoveValue();
}

scoped_refptr<RtpTransceiverInterface> PeerConnectionWrapper::AddTransceiver(
    scoped_refptr<MediaStreamTrackInterface> track) {
  RTCErrorOr<scoped_refptr<RtpTransceiverInterface>> result =
      pc()->AddTransceiver(track);
  EXPECT_EQ(RTCErrorType::NONE, result.error().type());
  return result.MoveValue();
}

scoped_refptr<RtpTransceiverInterface> PeerConnectionWrapper::AddTransceiver(
    scoped_refptr<MediaStreamTrackInterface> track,
    const RtpTransceiverInit& init) {
  RTCErrorOr<scoped_refptr<RtpTransceiverInterface>> result =
      pc()->AddTransceiver(track, init);
  EXPECT_EQ(RTCErrorType::NONE, result.error().type());
  return result.MoveValue();
}

scoped_refptr<AudioTrackInterface> PeerConnectionWrapper::CreateAudioTrack(
    const std::string& label) {
  return pc_factory()->CreateAudioTrack(label, nullptr);
}

scoped_refptr<VideoTrackInterface> PeerConnectionWrapper::CreateVideoTrack(
    const std::string& label) {
  return pc_factory()->CreateVideoTrack(FakeVideoTrackSource::Create(), label);
}

scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddTrack(
    scoped_refptr<MediaStreamTrackInterface> track,
    const std::vector<std::string>& stream_ids) {
  RTCErrorOr<scoped_refptr<RtpSenderInterface>> result =
      pc()->AddTrack(track, stream_ids);
  EXPECT_EQ(RTCErrorType::NONE, result.error().type());
  return result.MoveValue();
}

scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddTrack(
    scoped_refptr<MediaStreamTrackInterface> track,
    const std::vector<std::string>& stream_ids,
    const std::vector<RtpEncodingParameters>& init_send_encodings) {
  RTCErrorOr<scoped_refptr<RtpSenderInterface>> result =
      pc()->AddTrack(track, stream_ids, init_send_encodings);
  EXPECT_EQ(RTCErrorType::NONE, result.error().type());
  return result.MoveValue();
}

scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddAudioTrack(
    const std::string& track_label,
    const std::vector<std::string>& stream_ids) {
  return AddTrack(CreateAudioTrack(track_label), stream_ids);
}

scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddVideoTrack(
    const std::string& track_label,
    const std::vector<std::string>& stream_ids) {
  return AddTrack(CreateVideoTrack(track_label), stream_ids);
}

scoped_refptr<DataChannelInterface> PeerConnectionWrapper::CreateDataChannel(
    const std::string& label,
    const std::optional<DataChannelInit>& config) {
  const DataChannelInit* config_ptr = config.has_value() ? &(*config) : nullptr;
  auto result = pc()->CreateDataChannelOrError(label, config_ptr);
  if (!result.ok()) {
    RTC_LOG(LS_ERROR) << "CreateDataChannel failed: "
                      << ToString(result.error().type()) << " "
                      << result.error().message();
    return nullptr;
  }
  return result.MoveValue();
}

PeerConnectionInterface::SignalingState
PeerConnectionWrapper::signaling_state() {
  return pc()->signaling_state();
}

bool PeerConnectionWrapper::IsIceGatheringDone() {
  return observer()->ice_gathering_complete_;
}

bool PeerConnectionWrapper::IsIceConnected() {
  return observer()->ice_connected_;
}

scoped_refptr<const RTCStatsReport> PeerConnectionWrapper::GetStats() {
  auto callback = make_ref_counted<MockRTCStatsCollectorCallback>();
  pc()->GetStats(callback.get());
  EXPECT_TRUE(WaitUntil([&] { return callback->called(); }));
  return callback->report();
}

bool PeerConnectionWrapper::RunUntilIceGatheringDone(test::RunLoop& run_loop,
                                                     TimeDelta timeout) {
  if (observer()->ice_gathering_complete()) {
    return true;
  }
  observer()->SetIceGatheringCompleteCallback(run_loop.QuitClosure());
  run_loop.RunFor(timeout);

  // Clear the callback just in case the timeout happened before it fired.
  observer()->SetIceGatheringCompleteCallback(nullptr);

  return observer()->ice_gathering_complete();
}

}  // namespace webrtc
