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

#include <utility>

#include "absl/memory/memory.h"
#include "absl/types/optional.h"
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "api/audio_codecs/builtin_audio_encoder_factory.h"
#include "api/scoped_refptr.h"
#include "api/video_codecs/builtin_video_decoder_factory.h"
#include "api/video_codecs/builtin_video_encoder_factory.h"
#include "logging/rtc_event_log/rtc_event_log_factory.h"
#include "media/engine/webrtc_media_engine.h"
#include "modules/audio_device/include/audio_device.h"
#include "modules/audio_processing/include/audio_processing.h"
#include "p2p/client/basic_port_allocator.h"
#include "rtc_base/location.h"
#include "test/testsupport/copy_to_file_audio_capturer.h"

namespace webrtc {
namespace webrtc_pc_e2e {
namespace {

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

using AudioConfig = PeerConnectionE2EQualityTestFixture::AudioConfig;

// 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) {
  RTC_DCHECK(components->pcf_dependencies);
  RTC_DCHECK(components->pc_dependencies);

  // Setup required peer connection factory dependencies.
  if (components->pcf_dependencies->call_factory == nullptr) {
    components->pcf_dependencies->call_factory = webrtc::CreateCallFactory();
  }
  if (components->pcf_dependencies->event_log_factory == nullptr) {
    components->pcf_dependencies->event_log_factory =
        webrtc::CreateRtcEventLogFactory();
  }
}

std::unique_ptr<TestAudioDeviceModule::Capturer> CreateAudioCapturer(
    AudioConfig audio_config) {
  if (audio_config.mode == AudioConfig::Mode::kGenerated) {
    return TestAudioDeviceModule::CreatePulsedNoiseCapturer(
        kGeneratedAudioMaxAmplitude, kSamplingFrequencyInHz);
  }
  if (audio_config.mode == AudioConfig::Mode::kFile) {
    RTC_DCHECK(audio_config.input_file_name);
    return TestAudioDeviceModule::CreateWavFileReader(
        audio_config.input_file_name.value());
  }
  RTC_NOTREACHED() << "Unknown audio_config->mode";
  return nullptr;
}

rtc::scoped_refptr<AudioDeviceModule> CreateAudioDeviceModule(
    absl::optional<AudioConfig> audio_config,
    absl::optional<std::string> audio_output_file_name) {
  std::unique_ptr<TestAudioDeviceModule::Capturer> capturer;
  if (audio_config) {
    capturer = CreateAudioCapturer(audio_config.value());
  } else {
    // 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.
    capturer = TestAudioDeviceModule::CreatePulsedNoiseCapturer(
        kGeneratedAudioMaxAmplitude, kSamplingFrequencyInHz);
  }
  RTC_DCHECK(capturer);

  if (audio_config && audio_config->input_dump_file_name) {
    capturer = absl::make_unique<test::CopyToFileAudioCapturer>(
        std::move(capturer), audio_config->input_dump_file_name.value());
  }

  std::unique_ptr<TestAudioDeviceModule::Renderer> renderer;
  if (audio_output_file_name) {
    renderer = TestAudioDeviceModule::CreateBoundedWavFileWriter(
        audio_output_file_name.value(), kSamplingFrequencyInHz);
  } else {
    renderer =
        TestAudioDeviceModule::CreateDiscardRenderer(kSamplingFrequencyInHz);
  }

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

std::unique_ptr<VideoEncoderFactory> CreateVideoEncoderFactory(
    PeerConnectionFactoryComponents* pcf_dependencies,
    VideoQualityAnalyzerInjectionHelper* video_analyzer_helper,
    double bitrate_multiplier,
    std::map<std::string, absl::optional<int>> stream_required_spatial_index) {
  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();
  }
  return video_analyzer_helper->WrapVideoEncoderFactory(
      std::move(video_encoder_factory), bitrate_multiplier,
      std::move(stream_required_spatial_index));
}

std::unique_ptr<VideoDecoderFactory> CreateVideoDecoderFactory(
    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();
  }
  return video_analyzer_helper->WrapVideoDecoderFactory(
      std::move(video_decoder_factory));
}

std::unique_ptr<cricket::MediaEngineInterface> CreateMediaEngine(
    PeerConnectionFactoryComponents* pcf_dependencies,
    absl::optional<AudioConfig> audio_config,
    double bitrate_multiplier,
    std::map<std::string, absl::optional<int>> stream_required_spatial_index,
    VideoQualityAnalyzerInjectionHelper* video_analyzer_helper,
    absl::optional<std::string> audio_output_file_name) {
  rtc::scoped_refptr<AudioDeviceModule> adm = CreateAudioDeviceModule(
      std::move(audio_config), std::move(audio_output_file_name));

  std::unique_ptr<VideoEncoderFactory> video_encoder_factory =
      CreateVideoEncoderFactory(pcf_dependencies, video_analyzer_helper,
                                bitrate_multiplier,
                                std::move(stream_required_spatial_index));
  std::unique_ptr<VideoDecoderFactory> video_decoder_factory =
      CreateVideoDecoderFactory(pcf_dependencies, video_analyzer_helper);

  return cricket::WebRtcMediaEngineFactory::Create(
      adm, webrtc::CreateBuiltinAudioEncoderFactory(),
      webrtc::CreateBuiltinAudioDecoderFactory(),
      std::move(video_encoder_factory), std::move(video_decoder_factory),
      /*audio_mixer=*/nullptr, webrtc::AudioProcessingBuilder().Create());
}

// Creates PeerConnectionFactoryDependencies objects, providing entities
// from InjectableComponents::PeerConnectionFactoryComponents and also
// creating entities, that are required for correct injection of media quality
// analyzers.
PeerConnectionFactoryDependencies CreatePCFDependencies(
    std::unique_ptr<PeerConnectionFactoryComponents> pcf_dependencies,
    absl::optional<AudioConfig> audio_config,
    double bitrate_multiplier,
    std::map<std::string, absl::optional<int>> stream_required_spatial_index,
    VideoQualityAnalyzerInjectionHelper* video_analyzer_helper,
    rtc::Thread* network_thread,
    rtc::Thread* signaling_thread,
    absl::optional<std::string> audio_output_file_name) {
  PeerConnectionFactoryDependencies pcf_deps;
  pcf_deps.network_thread = network_thread;
  pcf_deps.signaling_thread = signaling_thread;
  pcf_deps.media_engine = CreateMediaEngine(
      pcf_dependencies.get(), std::move(audio_config), bitrate_multiplier,
      std::move(stream_required_spatial_index), video_analyzer_helper,
      std::move(audio_output_file_name));

  pcf_deps.call_factory = std::move(pcf_dependencies->call_factory);
  pcf_deps.event_log_factory = std::move(pcf_dependencies->event_log_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->media_transport_factory != nullptr) {
    pcf_deps.media_transport_factory =
        std::move(pcf_dependencies->media_transport_factory);
  }

  return pcf_deps;
}

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

  auto port_allocator = absl::make_unique<cricket::BasicPortAllocator>(
      pc_dependencies->network_manager);

  // 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);
  }
  return pc_deps;
}

}  // namespace

std::unique_ptr<TestPeer> TestPeer::CreateTestPeer(
    std::unique_ptr<InjectableComponents> components,
    std::unique_ptr<Params> params,
    std::unique_ptr<MockPeerConnectionObserver> observer,
    VideoQualityAnalyzerInjectionHelper* video_analyzer_helper,
    rtc::Thread* signaling_thread,
    absl::optional<std::string> audio_output_file_name,
    double bitrate_multiplier) {
  RTC_DCHECK(components);
  RTC_DCHECK(params);
  SetMandatoryEntities(components.get());
  params->rtc_configuration.sdp_semantics = SdpSemantics::kUnifiedPlan;

  std::map<std::string, absl::optional<int>> stream_required_spatial_index;
  for (auto& video_config : params->video_configs) {
    // Stream label should be set by fixture implementation here.
    RTC_DCHECK(video_config.stream_label);
    bool res = stream_required_spatial_index
                   .insert({*video_config.stream_label,
                            video_config.target_spatial_index})
                   .second;
    RTC_DCHECK(res) << "Duplicate video_config.stream_label="
                    << *video_config.stream_label;
  }

  // Create peer connection factory.
  PeerConnectionFactoryDependencies pcf_deps = CreatePCFDependencies(
      std::move(components->pcf_dependencies), params->audio_config,
      bitrate_multiplier, std::move(stream_required_spatial_index),
      video_analyzer_helper, components->network_thread, signaling_thread,
      std::move(audio_output_file_name));
  rtc::scoped_refptr<PeerConnectionFactoryInterface> pcf =
      CreateModularPeerConnectionFactory(std::move(pcf_deps));

  // Create peer connection.
  PeerConnectionDependencies pc_deps = CreatePCDependencies(
      std::move(components->pc_dependencies), observer.get());
  rtc::scoped_refptr<PeerConnectionInterface> pc =
      pcf->CreatePeerConnection(params->rtc_configuration, std::move(pc_deps));

  return absl::WrapUnique(
      new TestPeer(pcf, pc, std::move(observer), std::move(params)));
}

bool TestPeer::AddIceCandidates(
    rtc::ArrayView<const IceCandidateInterface* const> candidates) {
  bool success = true;
  for (const auto* candidate : candidates) {
    if (!pc()->AddIceCandidate(candidate)) {
      std::string candidate_str;
      bool res = candidate->ToString(&candidate_str);
      RTC_CHECK(res);
      RTC_LOG(LS_ERROR) << "Failed to add ICE candidate, candidate_str="
                        << candidate_str;
      success = false;
    }
  }
  return success;
}

TestPeer::TestPeer(
    rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory,
    rtc::scoped_refptr<PeerConnectionInterface> pc,
    std::unique_ptr<MockPeerConnectionObserver> observer,
    std::unique_ptr<Params> params)
    : PeerConnectionWrapper::PeerConnectionWrapper(std::move(pc_factory),
                                                   std::move(pc),
                                                   std::move(observer)),
      params_(std::move(params)) {}

}  // namespace webrtc_pc_e2e
}  // namespace webrtc
