/*
 *  Copyright 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 <cstdint>
#include <memory>

#include "api/enable_media_with_defaults.h"
#include "api/peer_connection_interface.h"
#include "api/rtc_event_log/rtc_event_log_factory.h"
#include "api/scoped_refptr.h"
#include "api/task_queue/default_task_queue_factory.h"
#include "api/transport/field_trial_based_config.h"
#include "media/engine/webrtc_media_engine.h"
#include "modules/audio_device/include/test_audio_device.h"
#include "p2p/base/basic_packet_socket_factory.h"
#include "p2p/client/basic_port_allocator.h"
#include "pc/peer_connection_wrapper.h"
#include "pc/test/mock_peer_connection_observers.h"
#include "rtc_base/gunit.h"
#include "rtc_base/task_queue_for_test.h"
#include "test/gmock.h"
#include "test/gtest.h"
#include "test/network/network_emulation.h"
#include "test/network/network_emulation_manager.h"
#include "test/network/simulated_network.h"

namespace webrtc {
namespace test {
namespace {

constexpr int kDefaultTimeoutMs = 1000;
constexpr int kMaxAptitude = 32000;
constexpr int kSamplingFrequency = 48000;
constexpr char kSignalThreadName[] = "signaling_thread";

bool AddIceCandidates(PeerConnectionWrapper* peer,
                      std::vector<const IceCandidateInterface*> candidates) {
  bool success = true;
  for (const auto candidate : candidates) {
    if (!peer->pc()->AddIceCandidate(candidate)) {
      success = false;
    }
  }
  return success;
}

rtc::scoped_refptr<PeerConnectionFactoryInterface> CreatePeerConnectionFactory(
    rtc::Thread* signaling_thread,
    rtc::Thread* network_thread) {
  PeerConnectionFactoryDependencies pcf_deps;
  pcf_deps.task_queue_factory = CreateDefaultTaskQueueFactory();
  pcf_deps.event_log_factory = std::make_unique<RtcEventLogFactory>();
  pcf_deps.network_thread = network_thread;
  pcf_deps.signaling_thread = signaling_thread;
  pcf_deps.trials = std::make_unique<FieldTrialBasedConfig>();
  pcf_deps.adm = TestAudioDeviceModule::Create(
      pcf_deps.task_queue_factory.get(),
      TestAudioDeviceModule::CreatePulsedNoiseCapturer(kMaxAptitude,
                                                       kSamplingFrequency),
      TestAudioDeviceModule::CreateDiscardRenderer(kSamplingFrequency),
      /*speed=*/1.f);
  EnableMediaWithDefaults(pcf_deps);
  return CreateModularPeerConnectionFactory(std::move(pcf_deps));
}

rtc::scoped_refptr<PeerConnectionInterface> CreatePeerConnection(
    const rtc::scoped_refptr<PeerConnectionFactoryInterface>& pcf,
    PeerConnectionObserver* observer,
    rtc::PacketSocketFactory* packet_socket_factory,
    rtc::NetworkManager* network_manager,
    EmulatedTURNServerInterface* turn_server = nullptr) {
  PeerConnectionDependencies pc_deps(observer);
  auto port_allocator = std::make_unique<cricket::BasicPortAllocator>(
      network_manager, packet_socket_factory);

  // This test does not support TCP
  int flags = cricket::PORTALLOCATOR_DISABLE_TCP;
  port_allocator->set_flags(port_allocator->flags() | flags);

  pc_deps.allocator = std::move(port_allocator);
  PeerConnectionInterface::RTCConfiguration rtc_configuration;
  rtc_configuration.sdp_semantics = SdpSemantics::kUnifiedPlan;
  if (turn_server != nullptr) {
    webrtc::PeerConnectionInterface::IceServer server;
    server.username = turn_server->GetIceServerConfig().username;
    server.password = turn_server->GetIceServerConfig().username;
    server.urls.push_back(turn_server->GetIceServerConfig().url);
    rtc_configuration.servers.push_back(server);
  }

  auto result =
      pcf->CreatePeerConnectionOrError(rtc_configuration, std::move(pc_deps));
  if (!result.ok()) {
    return nullptr;
  }
  return result.MoveValue();
}

}  // namespace

TEST(NetworkEmulationManagerPCTest, Run) {
  std::unique_ptr<rtc::Thread> signaling_thread = rtc::Thread::Create();
  signaling_thread->SetName(kSignalThreadName, nullptr);
  signaling_thread->Start();

  // Setup emulated network
  NetworkEmulationManagerImpl emulation(
      TimeMode::kRealTime, EmulatedNetworkStatsGatheringMode::kDefault);

  EmulatedNetworkNode* alice_node = emulation.CreateEmulatedNode(
      std::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig()));
  EmulatedNetworkNode* bob_node = emulation.CreateEmulatedNode(
      std::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig()));
  EmulatedEndpoint* alice_endpoint =
      emulation.CreateEndpoint(EmulatedEndpointConfig());
  EmulatedEndpoint* bob_endpoint =
      emulation.CreateEndpoint(EmulatedEndpointConfig());
  emulation.CreateRoute(alice_endpoint, {alice_node}, bob_endpoint);
  emulation.CreateRoute(bob_endpoint, {bob_node}, alice_endpoint);

  EmulatedNetworkManagerInterface* alice_network =
      emulation.CreateEmulatedNetworkManagerInterface({alice_endpoint});
  EmulatedNetworkManagerInterface* bob_network =
      emulation.CreateEmulatedNetworkManagerInterface({bob_endpoint});

  // Setup peer connections.
  rtc::scoped_refptr<PeerConnectionFactoryInterface> alice_pcf;
  rtc::scoped_refptr<PeerConnectionInterface> alice_pc;
  std::unique_ptr<MockPeerConnectionObserver> alice_observer =
      std::make_unique<MockPeerConnectionObserver>();

  rtc::scoped_refptr<PeerConnectionFactoryInterface> bob_pcf;
  rtc::scoped_refptr<PeerConnectionInterface> bob_pc;
  std::unique_ptr<MockPeerConnectionObserver> bob_observer =
      std::make_unique<MockPeerConnectionObserver>();

  SendTask(signaling_thread.get(), [&]() {
    alice_pcf = CreatePeerConnectionFactory(signaling_thread.get(),
                                            alice_network->network_thread());
    alice_pc = CreatePeerConnection(alice_pcf, alice_observer.get(),
                                    alice_network->packet_socket_factory(),
                                    alice_network->network_manager());

    bob_pcf = CreatePeerConnectionFactory(signaling_thread.get(),
                                          bob_network->network_thread());
    bob_pc = CreatePeerConnection(bob_pcf, bob_observer.get(),
                                  bob_network->packet_socket_factory(),
                                  bob_network->network_manager());
  });

  std::unique_ptr<PeerConnectionWrapper> alice =
      std::make_unique<PeerConnectionWrapper>(alice_pcf, alice_pc,
                                              std::move(alice_observer));
  std::unique_ptr<PeerConnectionWrapper> bob =
      std::make_unique<PeerConnectionWrapper>(bob_pcf, bob_pc,
                                              std::move(bob_observer));

  SendTask(signaling_thread.get(), [&]() {
    rtc::scoped_refptr<webrtc::AudioSourceInterface> source =
        alice_pcf->CreateAudioSource(cricket::AudioOptions());
    rtc::scoped_refptr<AudioTrackInterface> track =
        alice_pcf->CreateAudioTrack("audio", source.get());
    alice->AddTransceiver(track);

    // Connect peers.
    ASSERT_TRUE(alice->ExchangeOfferAnswerWith(bob.get()));
    // Do the SDP negotiation, and also exchange ice candidates.
    ASSERT_TRUE_WAIT(
        alice->signaling_state() == PeerConnectionInterface::kStable,
        kDefaultTimeoutMs);
    ASSERT_TRUE_WAIT(alice->IsIceGatheringDone(), kDefaultTimeoutMs);
    ASSERT_TRUE_WAIT(bob->IsIceGatheringDone(), kDefaultTimeoutMs);

    // Connect an ICE candidate pairs.
    ASSERT_TRUE(
        AddIceCandidates(bob.get(), alice->observer()->GetAllCandidates()));
    ASSERT_TRUE(
        AddIceCandidates(alice.get(), bob->observer()->GetAllCandidates()));
    // This means that ICE and DTLS are connected.
    ASSERT_TRUE_WAIT(bob->IsIceConnected(), kDefaultTimeoutMs);
    ASSERT_TRUE_WAIT(alice->IsIceConnected(), kDefaultTimeoutMs);

    // Close peer connections
    alice->pc()->Close();
    bob->pc()->Close();

    // Delete peers.
    alice.reset();
    bob.reset();
  });
}

TEST(NetworkEmulationManagerPCTest, RunTURN) {
  std::unique_ptr<rtc::Thread> signaling_thread = rtc::Thread::Create();
  signaling_thread->SetName(kSignalThreadName, nullptr);
  signaling_thread->Start();

  // Setup emulated network
  NetworkEmulationManagerImpl emulation(
      TimeMode::kRealTime, EmulatedNetworkStatsGatheringMode::kDefault);

  EmulatedNetworkNode* alice_node = emulation.CreateEmulatedNode(
      std::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig()));
  EmulatedNetworkNode* bob_node = emulation.CreateEmulatedNode(
      std::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig()));
  EmulatedNetworkNode* turn_node = emulation.CreateEmulatedNode(
      std::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig()));
  EmulatedEndpoint* alice_endpoint =
      emulation.CreateEndpoint(EmulatedEndpointConfig());
  EmulatedEndpoint* bob_endpoint =
      emulation.CreateEndpoint(EmulatedEndpointConfig());
  EmulatedTURNServerInterface* alice_turn =
      emulation.CreateTURNServer(EmulatedTURNServerConfig());
  EmulatedTURNServerInterface* bob_turn =
      emulation.CreateTURNServer(EmulatedTURNServerConfig());

  emulation.CreateRoute(alice_endpoint, {alice_node},
                        alice_turn->GetClientEndpoint());
  emulation.CreateRoute(alice_turn->GetClientEndpoint(), {alice_node},
                        alice_endpoint);

  emulation.CreateRoute(bob_endpoint, {bob_node},
                        bob_turn->GetClientEndpoint());
  emulation.CreateRoute(bob_turn->GetClientEndpoint(), {bob_node},
                        bob_endpoint);

  emulation.CreateRoute(alice_turn->GetPeerEndpoint(), {turn_node},
                        bob_turn->GetPeerEndpoint());
  emulation.CreateRoute(bob_turn->GetPeerEndpoint(), {turn_node},
                        alice_turn->GetPeerEndpoint());

  EmulatedNetworkManagerInterface* alice_network =
      emulation.CreateEmulatedNetworkManagerInterface({alice_endpoint});
  EmulatedNetworkManagerInterface* bob_network =
      emulation.CreateEmulatedNetworkManagerInterface({bob_endpoint});

  // Setup peer connections.
  rtc::scoped_refptr<PeerConnectionFactoryInterface> alice_pcf;
  rtc::scoped_refptr<PeerConnectionInterface> alice_pc;
  std::unique_ptr<MockPeerConnectionObserver> alice_observer =
      std::make_unique<MockPeerConnectionObserver>();

  rtc::scoped_refptr<PeerConnectionFactoryInterface> bob_pcf;
  rtc::scoped_refptr<PeerConnectionInterface> bob_pc;
  std::unique_ptr<MockPeerConnectionObserver> bob_observer =
      std::make_unique<MockPeerConnectionObserver>();

  SendTask(signaling_thread.get(), [&]() {
    alice_pcf = CreatePeerConnectionFactory(signaling_thread.get(),
                                            alice_network->network_thread());
    alice_pc = CreatePeerConnection(
        alice_pcf, alice_observer.get(), alice_network->packet_socket_factory(),
        alice_network->network_manager(), alice_turn);

    bob_pcf = CreatePeerConnectionFactory(signaling_thread.get(),
                                          bob_network->network_thread());
    bob_pc = CreatePeerConnection(bob_pcf, bob_observer.get(),
                                  bob_network->packet_socket_factory(),
                                  bob_network->network_manager(), bob_turn);
  });

  std::unique_ptr<PeerConnectionWrapper> alice =
      std::make_unique<PeerConnectionWrapper>(alice_pcf, alice_pc,
                                              std::move(alice_observer));
  std::unique_ptr<PeerConnectionWrapper> bob =
      std::make_unique<PeerConnectionWrapper>(bob_pcf, bob_pc,
                                              std::move(bob_observer));

  SendTask(signaling_thread.get(), [&]() {
    rtc::scoped_refptr<webrtc::AudioSourceInterface> source =
        alice_pcf->CreateAudioSource(cricket::AudioOptions());
    rtc::scoped_refptr<AudioTrackInterface> track =
        alice_pcf->CreateAudioTrack("audio", source.get());
    alice->AddTransceiver(track);

    // Connect peers.
    ASSERT_TRUE(alice->ExchangeOfferAnswerWith(bob.get()));
    // Do the SDP negotiation, and also exchange ice candidates.
    ASSERT_TRUE_WAIT(
        alice->signaling_state() == PeerConnectionInterface::kStable,
        kDefaultTimeoutMs);
    ASSERT_TRUE_WAIT(alice->IsIceGatheringDone(), kDefaultTimeoutMs);
    ASSERT_TRUE_WAIT(bob->IsIceGatheringDone(), kDefaultTimeoutMs);

    // Connect an ICE candidate pairs.
    ASSERT_TRUE(
        AddIceCandidates(bob.get(), alice->observer()->GetAllCandidates()));
    ASSERT_TRUE(
        AddIceCandidates(alice.get(), bob->observer()->GetAllCandidates()));
    // This means that ICE and DTLS are connected.
    ASSERT_TRUE_WAIT(bob->IsIceConnected(), kDefaultTimeoutMs);
    ASSERT_TRUE_WAIT(alice->IsIceConnected(), kDefaultTimeoutMs);

    // Close peer connections
    alice->pc()->Close();
    bob->pc()->Close();

    // Delete peers.
    alice.reset();
    bob.reset();
  });
}

}  // namespace test
}  // namespace webrtc
