/*
 *  Copyright 2020 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/connection_context.h"

#include <type_traits>
#include <utility>
#include <vector>

#include "api/environment/environment.h"
#include "media/base/media_engine.h"
#include "media/sctp/sctp_transport_factory.h"
#include "pc/media_factory.h"
#include "rtc_base/helpers.h"
#include "rtc_base/internal/default_socket_server.h"
#include "rtc_base/socket_server.h"
#include "rtc_base/time_utils.h"

namespace webrtc {

namespace {

rtc::Thread* MaybeStartNetworkThread(
    rtc::Thread* old_thread,
    std::unique_ptr<rtc::SocketFactory>& socket_factory_holder,
    std::unique_ptr<rtc::Thread>& thread_holder) {
  if (old_thread) {
    return old_thread;
  }
  std::unique_ptr<rtc::SocketServer> socket_server =
      rtc::CreateDefaultSocketServer();
  thread_holder = std::make_unique<rtc::Thread>(socket_server.get());
  socket_factory_holder = std::move(socket_server);

  thread_holder->SetName("pc_network_thread", nullptr);
  thread_holder->Start();
  return thread_holder.get();
}

rtc::Thread* MaybeWrapThread(rtc::Thread* signaling_thread,
                             bool& wraps_current_thread) {
  wraps_current_thread = false;
  if (signaling_thread) {
    return signaling_thread;
  }
  auto this_thread = rtc::Thread::Current();
  if (!this_thread) {
    // If this thread isn't already wrapped by an rtc::Thread, create a
    // wrapper and own it in this class.
    this_thread = rtc::ThreadManager::Instance()->WrapCurrentThread();
    wraps_current_thread = true;
  }
  return this_thread;
}

std::unique_ptr<SctpTransportFactoryInterface> MaybeCreateSctpFactory(
    std::unique_ptr<SctpTransportFactoryInterface> factory,
    rtc::Thread* network_thread) {
  if (factory) {
    return factory;
  }
#ifdef WEBRTC_HAVE_SCTP
  return std::make_unique<cricket::SctpTransportFactory>(network_thread);
#else
  return nullptr;
#endif
}

}  // namespace

// Static
rtc::scoped_refptr<ConnectionContext> ConnectionContext::Create(
    const Environment& env,
    PeerConnectionFactoryDependencies* dependencies) {
  return rtc::scoped_refptr<ConnectionContext>(
      new ConnectionContext(env, dependencies));
}

ConnectionContext::ConnectionContext(
    const Environment& env,
    PeerConnectionFactoryDependencies* dependencies)
    : network_thread_(MaybeStartNetworkThread(dependencies->network_thread,
                                              owned_socket_factory_,
                                              owned_network_thread_)),
      worker_thread_(dependencies->worker_thread,
                     []() {
                       auto thread_holder = rtc::Thread::Create();
                       thread_holder->SetName("pc_worker_thread", nullptr);
                       thread_holder->Start();
                       return thread_holder;
                     }),
      signaling_thread_(MaybeWrapThread(dependencies->signaling_thread,
                                        wraps_current_thread_)),
      env_(env),
      media_engine_(
          dependencies->media_factory != nullptr
              ? dependencies->media_factory->CreateMediaEngine(env_,
                                                               *dependencies)
              : nullptr),
      network_monitor_factory_(
          std::move(dependencies->network_monitor_factory)),
      default_network_manager_(std::move(dependencies->network_manager)),
      call_factory_(std::move(dependencies->media_factory)),
      default_socket_factory_(std::move(dependencies->packet_socket_factory)),
      sctp_factory_(
          MaybeCreateSctpFactory(std::move(dependencies->sctp_factory),
                                 network_thread())),
      use_rtx_(true) {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  RTC_DCHECK(!(default_network_manager_ && network_monitor_factory_))
      << "You can't set both network_manager and network_monitor_factory.";

  signaling_thread_->AllowInvokesToThread(worker_thread());
  signaling_thread_->AllowInvokesToThread(network_thread_);
  worker_thread_->AllowInvokesToThread(network_thread_);
  if (!network_thread_->IsCurrent()) {
    // network_thread_->IsCurrent() == true means signaling_thread_ is
    // network_thread_. In this case, no further action is required as
    // signaling_thread_ can already invoke network_thread_.
    network_thread_->PostTask(
        [thread = network_thread_, worker_thread = worker_thread_.get()] {
          thread->DisallowBlockingCalls();
          thread->DisallowAllInvokes();
          if (worker_thread == thread) {
            // In this case, worker_thread_ == network_thread_
            thread->AllowInvokesToThread(thread);
          }
        });
  }

  rtc::InitRandom(rtc::Time32());

  rtc::SocketFactory* socket_factory = dependencies->socket_factory;
  if (socket_factory == nullptr) {
    if (owned_socket_factory_) {
      socket_factory = owned_socket_factory_.get();
    } else {
      // TODO(bugs.webrtc.org/13145): This case should be deleted. Either
      // require that a PacketSocketFactory and NetworkManager always are
      // injected (with no need to construct these default objects), or require
      // that if a network_thread is injected, an approprite rtc::SocketServer
      // should be injected too.
      socket_factory = network_thread()->socketserver();
    }
  }
  if (!default_network_manager_) {
    // If network_monitor_factory_ is non-null, it will be used to create a
    // network monitor while on the network thread.
    default_network_manager_ = std::make_unique<rtc::BasicNetworkManager>(
        network_monitor_factory_.get(), socket_factory, &env_.field_trials());
  }
  if (!default_socket_factory_) {
    default_socket_factory_ =
        std::make_unique<rtc::BasicPacketSocketFactory>(socket_factory);
  }
  // Set warning levels on the threads, to give warnings when response
  // may be slower than is expected of the thread.
  // Since some of the threads may be the same, start with the least
  // restrictive limits and end with the least permissive ones.
  // This will give warnings for all cases.
  signaling_thread_->SetDispatchWarningMs(100);
  worker_thread_->SetDispatchWarningMs(30);
  network_thread_->SetDispatchWarningMs(10);

  if (media_engine_) {
    // TODO(tommi): Change VoiceEngine to do ctor time initialization so that
    // this isn't necessary.
    worker_thread_->BlockingCall([&] { media_engine_->Init(); });
  }
}

ConnectionContext::~ConnectionContext() {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  // `media_engine_` requires destruction to happen on the worker thread.
  worker_thread_->PostTask([media_engine = std::move(media_engine_)] {});

  // Make sure `worker_thread()` and `signaling_thread()` outlive
  // `default_socket_factory_` and `default_network_manager_`.
  default_socket_factory_ = nullptr;
  default_network_manager_ = nullptr;

  if (wraps_current_thread_)
    rtc::ThreadManager::Instance()->UnwrapCurrentThread();
}

}  // namespace webrtc
