/*
 *  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;

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 "Foo" isn't simulcast/SVC stream
// 2. `kAnalyzeAnySpatialStream` means all simulcast/SVC streams are required
// 3. Concrete value means that particular simulcast/SVC stream have to be
//    analyzed.
std::map<std::string, absl::optional<int>>
CalculateRequiredSpatialIndexPerStream(
    const std::vector<VideoConfig>& video_configs) {
  std::map<std::string, absl::optional<int>> out;
  for (auto& video_config : video_configs) {
    // Stream label should be set by fixture implementation here.
    RTC_DCHECK(video_config.stream_label);
    absl::optional<int> spatial_index;
    if (video_config.simulcast_config) {
      spatial_index = video_config.simulcast_config->target_spatial_index;
      if (!spatial_index) {
        spatial_index = kAnalyzeAnySpatialStream;
      }
    }
    bool res = out.insert({*video_config.stream_label, spatial_index}).second;
    RTC_DCHECK(res) << "Duplicate video_config.stream_label="
                    << *video_config.stream_label;
  }
  return out;
}

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,
    rtc::scoped_refptr<AudioProcessing> audio_processing) {
  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 = audio_processing;
  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,
    std::map<std::string, absl::optional<int>> stream_required_spatial_index,
    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_required_spatial_index));
}

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,
    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 = 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,
    double bitrate_multiplier,
    absl::optional<PeerConnectionE2EQualityTestFixture::EchoEmulationConfig>
        echo_emulation_config) {
  std::unique_ptr<InjectableComponents> components =
      configurer->ReleaseComponents();
  std::unique_ptr<Params> params = configurer->ReleaseParams();
  std::vector<PeerConfigurerImpl::VideoSource> video_sources =
      configurer->ReleaseVideoSources();
  RTC_DCHECK(components);
  RTC_DCHECK(params);
  RTC_DCHECK_EQ(params->video_configs.size(), video_sources.size());
  SetMandatoryEntities(components.get(), time_controller_);
  params->rtc_configuration.sdp_semantics = SdpSemantics::kUnifiedPlan;

  // Create peer connection factory.
  rtc::scoped_refptr<AudioProcessing> audio_processing =
      webrtc::AudioProcessingBuilder().Create();
  if (params->aec_dump_path && audio_processing) {
    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(), bitrate_multiplier,
      CalculateRequiredSpatialIndexPerStream(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,
                        audio_processing);

  std::unique_ptr<rtc::Thread> worker_thread =
      time_controller_.CreateThread("worker_thread");
  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(), 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(video_sources), audio_processing,
      std::move(worker_thread)));
}

}  // namespace webrtc_pc_e2e
}  // namespace webrtc
