/*
 *  Copyright (c) 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 "test/pc/e2e/test_peer_factory.h"

#include <utility>

#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
#include "api/task_queue/default_task_queue_factory.h"
#include "api/test/create_time_controller.h"
#include "api/test/time_controller.h"
#include "api/transport/field_trial_based_config.h"
#include "api/video_codecs/builtin_video_decoder_factory.h"
#include "api/video_codecs/builtin_video_encoder_factory.h"
#include "media/engine/webrtc_media_engine.h"
#include "media/engine/webrtc_media_engine_defaults.h"
#include "modules/audio_processing/aec_dump/aec_dump_factory.h"
#include "p2p/client/basic_port_allocator.h"
#include "test/pc/e2e/analyzer/video/quality_analyzing_video_encoder.h"
#include "test/pc/e2e/echo/echo_emulation.h"
#include "test/pc/e2e/peer_configurer.h"
#include "test/testsupport/copy_to_file_audio_capturer.h"

namespace webrtc {
namespace webrtc_pc_e2e {
namespace {

using AudioConfig =
    ::webrtc::webrtc_pc_e2e::PeerConnectionE2EQualityTestFixture::AudioConfig;
using VideoConfig =
    ::webrtc::webrtc_pc_e2e::PeerConnectionE2EQualityTestFixture::VideoConfig;
using EchoEmulationConfig = ::webrtc::webrtc_pc_e2e::
    PeerConnectionE2EQualityTestFixture::EchoEmulationConfig;
using EmulatedSFUConfigMap =
    ::webrtc::webrtc_pc_e2e::QualityAnalyzingVideoEncoder::EmulatedSFUConfigMap;

constexpr int16_t kGeneratedAudioMaxAmplitude = 32000;
constexpr int kDefaultSamplingFrequencyInHz = 48000;

// Sets mandatory entities in injectable components like `pcf_dependencies`
// and `pc_dependencies` if they are omitted. Also setup required
// dependencies, that won't be specially provided by factory and will be just
// transferred to peer connection creation code.
void SetMandatoryEntities(InjectableComponents* components,
                          TimeController& time_controller) {
  RTC_DCHECK(components->pcf_dependencies);
  RTC_DCHECK(components->pc_dependencies);

  // Setup required peer connection factory dependencies.
  if (components->pcf_dependencies->task_queue_factory == nullptr) {
    components->pcf_dependencies->task_queue_factory =
        time_controller.CreateTaskQueueFactory();
  }
  if (components->pcf_dependencies->call_factory == nullptr) {
    components->pcf_dependencies->call_factory =
        CreateTimeControllerBasedCallFactory(&time_controller);
  }
  if (components->pcf_dependencies->event_log_factory == nullptr) {
    components->pcf_dependencies->event_log_factory =
        std::make_unique<RtcEventLogFactory>(
            components->pcf_dependencies->task_queue_factory.get());
  }
  if (!components->pcf_dependencies->trials) {
    components->pcf_dependencies->trials =
        std::make_unique<FieldTrialBasedConfig>();
  }
}

// Returns mapping from stream label to optional spatial index.
// If we have stream label "Foo" and mapping contains
// 1. `absl::nullopt` means all simulcast/SVC streams are required
// 2. Concrete value means that particular simulcast/SVC stream have to be
//    analyzed.
EmulatedSFUConfigMap CalculateRequiredSpatialIndexPerStream(
    const std::vector<VideoConfig>& video_configs) {
  EmulatedSFUConfigMap result;
  for (auto& video_config : video_configs) {
    // Stream label should be set by fixture implementation here.
    RTC_DCHECK(video_config.stream_label);
    bool res = result
                   .insert({*video_config.stream_label,
                            video_config.emulated_sfu_config})
                   .second;
    RTC_DCHECK(res) << "Duplicate video_config.stream_label="
                    << *video_config.stream_label;
  }
  return result;
}

std::unique_ptr<TestAudioDeviceModule::Renderer> CreateAudioRenderer(
    const absl::optional<RemotePeerAudioConfig>& config) {
  if (!config) {
    // Return default renderer because we always require some renderer.
    return TestAudioDeviceModule::CreateDiscardRenderer(
        kDefaultSamplingFrequencyInHz);
  }
  if (config->output_file_name) {
    return TestAudioDeviceModule::CreateBoundedWavFileWriter(
        config->output_file_name.value(), config->sampling_frequency_in_hz);
  }
  return TestAudioDeviceModule::CreateDiscardRenderer(
      config->sampling_frequency_in_hz);
}

std::unique_ptr<TestAudioDeviceModule::Capturer> CreateAudioCapturer(
    const absl::optional<AudioConfig>& audio_config) {
  if (!audio_config) {
    // If we have no audio config we still need to provide some audio device.
    // In such case use generated capturer. Despite of we provided audio here,
    // in test media setup audio stream won't be added into peer connection.
    return TestAudioDeviceModule::CreatePulsedNoiseCapturer(
        kGeneratedAudioMaxAmplitude, kDefaultSamplingFrequencyInHz);
  }

  switch (audio_config->mode) {
    case AudioConfig::Mode::kGenerated:
      return TestAudioDeviceModule::CreatePulsedNoiseCapturer(
          kGeneratedAudioMaxAmplitude, audio_config->sampling_frequency_in_hz);
    case AudioConfig::Mode::kFile:
      RTC_DCHECK(audio_config->input_file_name);
      return TestAudioDeviceModule::CreateWavFileReader(
          audio_config->input_file_name.value(), /*repeat=*/true);
  }
}

rtc::scoped_refptr<AudioDeviceModule> CreateAudioDeviceModule(
    absl::optional<AudioConfig> audio_config,
    absl::optional<RemotePeerAudioConfig> remote_audio_config,
    absl::optional<EchoEmulationConfig> echo_emulation_config,
    TaskQueueFactory* task_queue_factory) {
  std::unique_ptr<TestAudioDeviceModule::Renderer> renderer =
      CreateAudioRenderer(remote_audio_config);
  std::unique_ptr<TestAudioDeviceModule::Capturer> capturer =
      CreateAudioCapturer(audio_config);
  RTC_DCHECK(renderer);
  RTC_DCHECK(capturer);

  // Setup echo emulation if required.
  if (echo_emulation_config) {
    capturer = std::make_unique<EchoEmulatingCapturer>(std::move(capturer),
                                                       *echo_emulation_config);
    renderer = std::make_unique<EchoEmulatingRenderer>(
        std::move(renderer),
        static_cast<EchoEmulatingCapturer*>(capturer.get()));
  }

  // Setup input stream dumping if required.
  if (audio_config && audio_config->input_dump_file_name) {
    capturer = std::make_unique<test::CopyToFileAudioCapturer>(
        std::move(capturer), audio_config->input_dump_file_name.value());
  }

  return TestAudioDeviceModule::Create(task_queue_factory, std::move(capturer),
                                       std::move(renderer), /*speed=*/1.f);
}

std::unique_ptr<cricket::MediaEngineInterface> CreateMediaEngine(
    PeerConnectionFactoryComponents* pcf_dependencies,
    rtc::scoped_refptr<AudioDeviceModule> audio_device_module) {
  cricket::MediaEngineDependencies media_deps;
  media_deps.task_queue_factory = pcf_dependencies->task_queue_factory.get();
  media_deps.adm = audio_device_module;
  media_deps.audio_processing = pcf_dependencies->audio_processing;
  media_deps.audio_mixer = pcf_dependencies->audio_mixer;
  media_deps.video_encoder_factory =
      std::move(pcf_dependencies->video_encoder_factory);
  media_deps.video_decoder_factory =
      std::move(pcf_dependencies->video_decoder_factory);
  webrtc::SetMediaEngineDefaults(&media_deps);
  RTC_DCHECK(pcf_dependencies->trials);
  media_deps.trials = pcf_dependencies->trials.get();

  return cricket::CreateMediaEngine(std::move(media_deps));
}

void WrapVideoEncoderFactory(
    absl::string_view peer_name,
    double bitrate_multiplier,
    EmulatedSFUConfigMap stream_to_sfu_config,
    PeerConnectionFactoryComponents* pcf_dependencies,
    VideoQualityAnalyzerInjectionHelper* video_analyzer_helper) {
  std::unique_ptr<VideoEncoderFactory> video_encoder_factory;
  if (pcf_dependencies->video_encoder_factory != nullptr) {
    video_encoder_factory = std::move(pcf_dependencies->video_encoder_factory);
  } else {
    video_encoder_factory = CreateBuiltinVideoEncoderFactory();
  }
  pcf_dependencies->video_encoder_factory =
      video_analyzer_helper->WrapVideoEncoderFactory(
          peer_name, std::move(video_encoder_factory), bitrate_multiplier,
          std::move(stream_to_sfu_config));
}

void WrapVideoDecoderFactory(
    absl::string_view peer_name,
    PeerConnectionFactoryComponents* pcf_dependencies,
    VideoQualityAnalyzerInjectionHelper* video_analyzer_helper) {
  std::unique_ptr<VideoDecoderFactory> video_decoder_factory;
  if (pcf_dependencies->video_decoder_factory != nullptr) {
    video_decoder_factory = std::move(pcf_dependencies->video_decoder_factory);
  } else {
    video_decoder_factory = CreateBuiltinVideoDecoderFactory();
  }
  pcf_dependencies->video_decoder_factory =
      video_analyzer_helper->WrapVideoDecoderFactory(
          peer_name, std::move(video_decoder_factory));
}

// Creates PeerConnectionFactoryDependencies objects, providing entities
// from InjectableComponents::PeerConnectionFactoryComponents.
PeerConnectionFactoryDependencies CreatePCFDependencies(
    std::unique_ptr<PeerConnectionFactoryComponents> pcf_dependencies,
    std::unique_ptr<cricket::MediaEngineInterface> media_engine,
    rtc::Thread* signaling_thread,
    rtc::Thread* worker_thread,
    rtc::Thread* network_thread) {
  PeerConnectionFactoryDependencies pcf_deps;
  pcf_deps.signaling_thread = signaling_thread;
  pcf_deps.worker_thread = worker_thread;
  pcf_deps.network_thread = network_thread;
  pcf_deps.media_engine = std::move(media_engine);

  pcf_deps.call_factory = std::move(pcf_dependencies->call_factory);
  pcf_deps.event_log_factory = std::move(pcf_dependencies->event_log_factory);
  pcf_deps.task_queue_factory = std::move(pcf_dependencies->task_queue_factory);

  if (pcf_dependencies->fec_controller_factory != nullptr) {
    pcf_deps.fec_controller_factory =
        std::move(pcf_dependencies->fec_controller_factory);
  }
  if (pcf_dependencies->network_controller_factory != nullptr) {
    pcf_deps.network_controller_factory =
        std::move(pcf_dependencies->network_controller_factory);
  }
  if (pcf_dependencies->neteq_factory != nullptr) {
    pcf_deps.neteq_factory = std::move(pcf_dependencies->neteq_factory);
  }
  if (pcf_dependencies->trials != nullptr) {
    pcf_deps.trials = std::move(pcf_dependencies->trials);
  }

  return pcf_deps;
}

// Creates PeerConnectionDependencies objects, providing entities
// from InjectableComponents::PeerConnectionComponents.
PeerConnectionDependencies CreatePCDependencies(
    MockPeerConnectionObserver* observer,
    uint32_t port_allocator_extra_flags,
    std::unique_ptr<PeerConnectionComponents> pc_dependencies) {
  PeerConnectionDependencies pc_deps(observer);

  auto port_allocator = std::make_unique<cricket::BasicPortAllocator>(
      pc_dependencies->network_manager, pc_dependencies->packet_socket_factory);

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

  pc_deps.allocator = std::move(port_allocator);

  if (pc_dependencies->async_resolver_factory != nullptr) {
    pc_deps.async_resolver_factory =
        std::move(pc_dependencies->async_resolver_factory);
  }
  if (pc_dependencies->cert_generator != nullptr) {
    pc_deps.cert_generator = std::move(pc_dependencies->cert_generator);
  }
  if (pc_dependencies->tls_cert_verifier != nullptr) {
    pc_deps.tls_cert_verifier = std::move(pc_dependencies->tls_cert_verifier);
  }
  if (pc_dependencies->ice_transport_factory != nullptr) {
    pc_deps.ice_transport_factory =
        std::move(pc_dependencies->ice_transport_factory);
  }
  return pc_deps;
}

}  // namespace

absl::optional<RemotePeerAudioConfig> RemotePeerAudioConfig::Create(
    absl::optional<AudioConfig> config) {
  if (!config) {
    return absl::nullopt;
  }
  return RemotePeerAudioConfig(config.value());
}

std::unique_ptr<TestPeer> TestPeerFactory::CreateTestPeer(
    std::unique_ptr<PeerConfigurerImpl> configurer,
    std::unique_ptr<MockPeerConnectionObserver> observer,
    absl::optional<RemotePeerAudioConfig> remote_audio_config,
    absl::optional<PeerConnectionE2EQualityTestFixture::EchoEmulationConfig>
        echo_emulation_config) {
  std::unique_ptr<InjectableComponents> components =
      configurer->ReleaseComponents();
  std::unique_ptr<Params> params = configurer->ReleaseParams();
  std::unique_ptr<ConfigurableParams> configurable_params =
      configurer->ReleaseConfigurableParams();
  std::vector<PeerConfigurerImpl::VideoSource> video_sources =
      configurer->ReleaseVideoSources();
  RTC_DCHECK(components);
  RTC_DCHECK(params);
  RTC_DCHECK(configurable_params);
  RTC_DCHECK_EQ(configurable_params->video_configs.size(),
                video_sources.size());
  SetMandatoryEntities(components.get(), time_controller_);
  params->rtc_configuration.sdp_semantics = SdpSemantics::kUnifiedPlan;

  // Create peer connection factory.
  if (components->pcf_dependencies->audio_processing == nullptr) {
    components->pcf_dependencies->audio_processing =
        webrtc::AudioProcessingBuilder().Create();
  }
  if (params->aec_dump_path) {
    components->pcf_dependencies->audio_processing->CreateAndAttachAecDump(
        *params->aec_dump_path, -1, task_queue_);
  }
  rtc::scoped_refptr<AudioDeviceModule> audio_device_module =
      CreateAudioDeviceModule(
          params->audio_config, remote_audio_config, echo_emulation_config,
          components->pcf_dependencies->task_queue_factory.get());
  WrapVideoEncoderFactory(
      params->name.value(), params->video_encoder_bitrate_multiplier,
      CalculateRequiredSpatialIndexPerStream(
          configurable_params->video_configs),
      components->pcf_dependencies.get(), video_analyzer_helper_);
  WrapVideoDecoderFactory(params->name.value(),
                          components->pcf_dependencies.get(),
                          video_analyzer_helper_);
  std::unique_ptr<cricket::MediaEngineInterface> media_engine =
      CreateMediaEngine(components->pcf_dependencies.get(),
                        audio_device_module);

  std::unique_ptr<rtc::Thread> worker_thread =
      time_controller_.CreateThread("worker_thread");
  // Store `webrtc::AudioProcessing` into local variable before move of
  // `components->pcf_dependencies`
  rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing =
      components->pcf_dependencies->audio_processing;
  PeerConnectionFactoryDependencies pcf_deps = CreatePCFDependencies(
      std::move(components->pcf_dependencies), std::move(media_engine),
      signaling_thread_, worker_thread.get(), components->network_thread);
  rtc::scoped_refptr<PeerConnectionFactoryInterface> peer_connection_factory =
      CreateModularPeerConnectionFactory(std::move(pcf_deps));

  // Create peer connection.
  PeerConnectionDependencies pc_deps =
      CreatePCDependencies(observer.get(), params->port_allocator_extra_flags,
                           std::move(components->pc_dependencies));
  rtc::scoped_refptr<PeerConnectionInterface> peer_connection =
      peer_connection_factory
          ->CreatePeerConnectionOrError(params->rtc_configuration,
                                        std::move(pc_deps))
          .MoveValue();
  peer_connection->SetBitrate(params->bitrate_settings);

  return absl::WrapUnique(new TestPeer(
      peer_connection_factory, peer_connection, std::move(observer),
      std::move(*params), std::move(*configurable_params),
      std::move(video_sources), audio_processing, std::move(worker_thread)));
}

}  // namespace webrtc_pc_e2e
}  // namespace webrtc
