/*
 *  Copyright 2004 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_factory.h"

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

#include "absl/strings/string_view.h"
#include "api/audio_options.h"
#include "api/environment/environment.h"
#include "api/environment/environment_factory.h"
#include "api/ice_transport_interface.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/scoped_refptr.h"
#include "api/sequence_checker.h"
#include "api/transport/bitrate_settings.h"
#include "api/units/data_rate.h"
#include "call/call_config.h"
#include "media/base/codec.h"
#include "media/base/media_engine.h"
#include "p2p/base/basic_async_resolver_factory.h"
#include "p2p/base/default_ice_transport_factory.h"
#include "p2p/base/ice_transport_internal.h"
#include "p2p/base/port.h"
#include "p2p/base/port_allocator.h"
#include "p2p/client/basic_port_allocator.h"
#include "pc/audio_track.h"
#include "pc/codec_vendor.h"
#include "pc/connection_context.h"
#include "pc/ice_server_parsing.h"
#include "pc/local_audio_source.h"
#include "pc/media_factory.h"
#include "pc/media_stream.h"
#include "pc/media_stream_proxy.h"
#include "pc/media_stream_track_proxy.h"
#include "pc/peer_connection.h"
#include "pc/peer_connection_proxy.h"
#include "pc/rtp_parameters_conversion.h"
#include "pc/video_track.h"
#include "rtc_base/checks.h"
#include "rtc_base/experiments/field_trial_parser.h"
#include "rtc_base/experiments/field_trial_units.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_conversions.h"
#include "rtc_base/rtc_certificate_generator.h"
#include "rtc_base/system/file_wrapper.h"

namespace webrtc {
namespace {

Environment AssembleEnvironment(PeerConnectionFactoryDependencies& deps) {
  // Assemble Environment here rather than in ConnectionContext::Create
  // to avoid dependency on EnvironmentFactory by ConnectionContext and thus its
  // users.
  if (!deps.env.has_value()) {
    return CreateEnvironment();
  }

  Environment env = *std::move(deps.env);
  // Clear Environment from `deps` to avoid accidental usage of the wrong
  // Environment.
  deps.env = std::nullopt;
  return env;
}

}  // namespace

// Static
scoped_refptr<PeerConnectionFactory> PeerConnectionFactory::Create(
    PeerConnectionFactoryDependencies dependencies) {
  Environment env = AssembleEnvironment(dependencies);
  auto context = ConnectionContext::Create(env, &dependencies);
  if (!context) {
    return nullptr;
  }
  return make_ref_counted<PeerConnectionFactory>(env, context, &dependencies);
}

PeerConnectionFactory::PeerConnectionFactory(
    Environment env,
    scoped_refptr<ConnectionContext> context,
    PeerConnectionFactoryDependencies* dependencies)
    : env_(env),
      context_(context ? context
                       : ConnectionContext::Create(env_, dependencies)),
      codec_vendor_(media_engine(), context_->use_rtx(), env_.field_trials()),
      event_log_factory_(std::move(dependencies->event_log_factory)),
      fec_controller_factory_(std::move(dependencies->fec_controller_factory)),
      network_state_predictor_factory_(
          std::move(dependencies->network_state_predictor_factory)),
      injected_network_controller_factory_(
          std::move(dependencies->network_controller_factory)),
      neteq_factory_(std::move(dependencies->neteq_factory)),
      decode_metronome_(std::move(dependencies->decode_metronome)),
      encode_metronome_(std::move(dependencies->encode_metronome)) {}

PeerConnectionFactory::PeerConnectionFactory(
    PeerConnectionFactoryDependencies dependencies)
    : PeerConnectionFactory(AssembleEnvironment(dependencies),
                            /* context= */ nullptr,
                            &dependencies) {}

PeerConnectionFactory::~PeerConnectionFactory() {
  RTC_DCHECK_RUN_ON(signaling_thread());
  worker_thread()->BlockingCall([this] {
    RTC_DCHECK_RUN_ON(worker_thread());
    decode_metronome_ = nullptr;
    encode_metronome_ = nullptr;
    StopAecDump();
  });
}

void PeerConnectionFactory::SetOptions(const Options& options) {
  RTC_DCHECK_RUN_ON(signaling_thread());
  options_ = options;
}

RtpCapabilities PeerConnectionFactory::GetRtpSenderCapabilities(
    MediaType kind) const {
  RTC_DCHECK_RUN_ON(signaling_thread());
  switch (kind) {
    case MediaType::AUDIO: {
      Codecs cricket_codecs;
      cricket_codecs = codec_vendor_.audio_send_codecs().codecs();
      auto extensions = GetDefaultEnabledRtpHeaderExtensions(
          media_engine()->voice(), /* field_trials= */ nullptr);
      return ToRtpCapabilities(cricket_codecs, extensions);
    }
    case MediaType::VIDEO: {
      Codecs cricket_codecs;
      cricket_codecs = codec_vendor_.video_send_codecs().codecs();
      auto extensions = GetDefaultEnabledRtpHeaderExtensions(
          media_engine()->video(), /* field_trials= */ nullptr);
      return ToRtpCapabilities(cricket_codecs, extensions);
    }
    default:
      return RtpCapabilities();
  }
  RTC_DLOG(LS_ERROR) << "Got unexpected MediaType " << kind;
  RTC_CHECK_NOTREACHED();
}

RtpCapabilities PeerConnectionFactory::GetRtpReceiverCapabilities(
    MediaType kind) const {
  RTC_DCHECK_RUN_ON(signaling_thread());
  switch (kind) {
    case MediaType::AUDIO: {
      Codecs cricket_codecs;
      cricket_codecs = codec_vendor_.audio_recv_codecs().codecs();
      auto extensions = GetDefaultEnabledRtpHeaderExtensions(
          media_engine()->voice(), /* field_trials= */ nullptr);
      return ToRtpCapabilities(cricket_codecs, extensions);
    }
    case MediaType::VIDEO: {
      Codecs cricket_codecs = codec_vendor_.video_recv_codecs().codecs();
      auto extensions = GetDefaultEnabledRtpHeaderExtensions(
          media_engine()->video(), /* field_trials= */ nullptr);
      return ToRtpCapabilities(cricket_codecs, extensions);
    }
    default:
      return RtpCapabilities();
  }
  RTC_DLOG(LS_ERROR) << "Got unexpected MediaType " << kind;
  RTC_CHECK_NOTREACHED();
}

scoped_refptr<AudioSourceInterface> PeerConnectionFactory::CreateAudioSource(
    const AudioOptions& options) {
  RTC_DCHECK(signaling_thread()->IsCurrent());
  scoped_refptr<LocalAudioSource> source(LocalAudioSource::Create(&options));
  return source;
}

bool PeerConnectionFactory::StartAecDump(FILE* file, int64_t max_size_bytes) {
  RTC_DCHECK_RUN_ON(worker_thread());
  if (!file) {
    RTC_LOG(LS_ERROR) << "Cannot start AEC dump with null file pointer.";
    return false;
  }
  if (media_engine_ref_) {
    RTC_LOG(LS_WARNING) << "Replacing ongoing AEC dump.";
  } else {
    media_engine_ref_ =
        std::make_unique<ConnectionContext::MediaEngineReference>(context_);
  }
  const bool started = media_engine_ref_->media_engine()->voice().StartAecDump(
      FileWrapper(file), max_size_bytes);
  if (!started) {  // E.g. if the file couldn't be opened/created.
    StopAecDump();
  }
  return started;
}

void PeerConnectionFactory::StopAecDump() {
  RTC_DCHECK_RUN_ON(worker_thread());
  if (!media_engine_ref_)
    return;
  media_engine_ref_->media_engine()->voice().StopAecDump();
  media_engine_ref_ = nullptr;
}

const MediaEngineInterface* PeerConnectionFactory::media_engine() const {
  RTC_DCHECK(context_);
  return context_->media_engine();
}

RTCErrorOr<scoped_refptr<PeerConnectionInterface>>
PeerConnectionFactory::CreatePeerConnectionOrError(
    const PeerConnectionInterface::RTCConfiguration& configuration,
    PeerConnectionDependencies dependencies) {
  RTC_DCHECK_RUN_ON(signaling_thread());

  // TODO(https://crbug.com/webrtc/13528): Remove support for kPlanB.
  if (configuration.sdp_semantics == SdpSemantics::kPlanB_DEPRECATED) {
    RTC_LOG(LS_WARNING)
        << "PeerConnection constructed with legacy SDP semantics!";
  }

  RTCError err = IceConfig(configuration).IsValid();
  if (!err.ok()) {
    RTC_LOG(LS_ERROR) << "Invalid ICE configuration: " << err.message();
    return err;
  }

  ServerAddresses stun_servers;
  std::vector<RelayServerConfig> turn_servers;
  err = ParseAndValidateIceServersFromConfiguration(configuration, stun_servers,
                                                    turn_servers);
  if (!err.ok()) {
    return err;
  }

  if (!dependencies.observer) {
    RTC_LOG(LS_ERROR) << "PeerConnection initialized without a "
                         "PeerConnectionObserver";
    return RTCError(RTCErrorType::INVALID_PARAMETER,
                    "Attempt to create a PeerConnection without an observer");
  }

  EnvironmentFactory env_factory(env_);

  // Field trials active for this PeerConnection is the first of:
  // a) Specified in the PeerConnectionDependencies
  // b) Specified in the PeerConnectionFactoryDependencies
  // c) Created as default by the EnvironmentFactory.
  env_factory.Set(std::move(dependencies.trials));

  if (event_log_factory_ != nullptr) {
    worker_thread()->BlockingCall([&] {
      Environment env_for_rtc_event_log = env_factory.Create();
      env_factory.Set(event_log_factory_->Create(env_for_rtc_event_log));
    });
  }

  const Environment env = env_factory.Create();

  // Set internal defaults if optional dependencies are not set.
  if (!dependencies.cert_generator) {
    dependencies.cert_generator = std::make_unique<RTCCertificateGenerator>(
        signaling_thread(), network_thread());
  }

  if (!dependencies.async_dns_resolver_factory) {
    dependencies.async_dns_resolver_factory =
        std::make_unique<BasicAsyncDnsResolverFactory>();
  }

  if (!dependencies.allocator) {
    dependencies.allocator = std::make_unique<BasicPortAllocator>(
        env, context_->default_network_manager(),
        context_->default_socket_factory(), configuration.turn_customizer);
    dependencies.allocator->SetPortRange(
        configuration.port_allocator_config.min_port,
        configuration.port_allocator_config.max_port);
    dependencies.allocator->set_flags(
        configuration.port_allocator_config.flags);
  }

  if (!dependencies.ice_transport_factory) {
    dependencies.ice_transport_factory =
        std::make_unique<DefaultIceTransportFactory>();
  }

  dependencies.allocator->SetNetworkIgnoreMask(options().network_ignore_mask);
  dependencies.allocator->SetVpnList(configuration.vpn_list);

  std::unique_ptr<Call> call =
      worker_thread()->BlockingCall([this, &env, &configuration] {
        return CreateCall_w(env, std::move(configuration));
      });

  auto pc = PeerConnection::Create(env, context_, options_, std::move(call),
                                   configuration, dependencies, stun_servers,
                                   turn_servers);
  // We configure the proxy with a pointer to the network thread for methods
  // that need to be invoked there rather than on the signaling thread.
  // Internally, the proxy object has a member variable named `worker_thread_`
  // which will point to the network thread (and not the factory's
  // worker_thread()).  All such methods have thread checks though, so the code
  // should still be clear (outside of macro expansion).
  return scoped_refptr<PeerConnectionInterface>(PeerConnectionProxy::Create(
      signaling_thread(), network_thread(), std::move(pc)));
}

scoped_refptr<MediaStreamInterface>
PeerConnectionFactory::CreateLocalMediaStream(const std::string& stream_id) {
  RTC_DCHECK(signaling_thread()->IsCurrent());
  return MediaStreamProxy::Create(signaling_thread(),
                                  MediaStream::Create(stream_id));
}

scoped_refptr<VideoTrackInterface> PeerConnectionFactory::CreateVideoTrack(
    scoped_refptr<VideoTrackSourceInterface> source,
    absl::string_view id) {
  RTC_DCHECK(signaling_thread()->IsCurrent());
  scoped_refptr<VideoTrackInterface> track =
      VideoTrack::Create(id, source, worker_thread());
  return VideoTrackProxy::Create(signaling_thread(), worker_thread(), track);
}

scoped_refptr<AudioTrackInterface> PeerConnectionFactory::CreateAudioTrack(
    const std::string& id,
    AudioSourceInterface* source) {
  RTC_DCHECK(signaling_thread()->IsCurrent());
  scoped_refptr<AudioTrackInterface> track =
      AudioTrack::Create(id, scoped_refptr<AudioSourceInterface>(source));
  return AudioTrackProxy::Create(signaling_thread(), track);
}

std::unique_ptr<Call> PeerConnectionFactory::CreateCall_w(
    const Environment& env,
    const PeerConnectionInterface::RTCConfiguration& configuration) {
  RTC_DCHECK_RUN_ON(worker_thread());

  CallConfig call_config(env, network_thread());
  if (!context_->media_engine() || !context_->call_factory()) {
    return nullptr;
  }
  call_config.audio_state = media_engine()->voice().GetAudioState();

  FieldTrialParameter<DataRate> min_bandwidth("min",
                                              DataRate::KilobitsPerSec(30));
  FieldTrialParameter<DataRate> start_bandwidth("start",
                                                DataRate::KilobitsPerSec(300));
  FieldTrialParameter<DataRate> max_bandwidth("max",
                                              DataRate::KilobitsPerSec(2000));
  ParseFieldTrial({&min_bandwidth, &start_bandwidth, &max_bandwidth},
                  env.field_trials().Lookup("WebRTC-PcFactoryDefaultBitrates"));

  call_config.bitrate_config.min_bitrate_bps =
      saturated_cast<int>(min_bandwidth->bps());
  call_config.bitrate_config.start_bitrate_bps =
      saturated_cast<int>(start_bandwidth->bps());
  call_config.bitrate_config.max_bitrate_bps =
      saturated_cast<int>(max_bandwidth->bps());

  call_config.fec_controller_factory = fec_controller_factory_.get();
  call_config.network_state_predictor_factory =
      network_state_predictor_factory_.get();
  call_config.neteq_factory = neteq_factory_.get();

  if (field_trials().IsEnabled("WebRTC-Bwe-InjectedCongestionController")) {
    RTC_LOG(LS_INFO) << "Using pcf injected network controller factory";
    call_config.network_controller_factory =
        injected_network_controller_factory_.get();
  } else {
    RTC_LOG(LS_INFO) << "Using default network controller factory";
  }
  call_config.decode_metronome = decode_metronome_.get();
  call_config.encode_metronome = encode_metronome_.get();
  call_config.pacer_burst_interval = configuration.pacer_burst_interval;
  return context_->call_factory()->CreateCall(std::move(call_config));
}

}  // namespace webrtc
