/*
 *  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/channel_manager.h"

#include <utility>

#include "absl/algorithm/container.h"
#include "absl/memory/memory.h"
#include "absl/strings/match.h"
#include "media/base/media_constants.h"
#include "rtc_base/checks.h"
#include "rtc_base/location.h"
#include "rtc_base/logging.h"
#include "rtc_base/thread_checker.h"
#include "rtc_base/trace_event.h"

namespace cricket {

ChannelManager::ChannelManager(
    std::unique_ptr<MediaEngineInterface> media_engine,
    std::unique_ptr<DataEngineInterface> data_engine,
    rtc::Thread* worker_thread,
    rtc::Thread* network_thread)
    : media_engine_(std::move(media_engine)),
      data_engine_(std::move(data_engine)),
      main_thread_(rtc::Thread::Current()),
      worker_thread_(worker_thread),
      network_thread_(network_thread) {
  RTC_DCHECK(data_engine_);
  RTC_DCHECK(worker_thread_);
  RTC_DCHECK(network_thread_);
}

ChannelManager::~ChannelManager() {
  if (initialized_) {
    Terminate();
  }
  // The media engine needs to be deleted on the worker thread for thread safe
  // destruction,
  worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] { media_engine_.reset(); });
}

bool ChannelManager::SetVideoRtxEnabled(bool enable) {
  // To be safe, this call is only allowed before initialization. Apps like
  // Flute only have a singleton ChannelManager and we don't want this flag to
  // be toggled between calls or when there's concurrent calls. We expect apps
  // to enable this at startup and retain that setting for the lifetime of the
  // app.
  if (!initialized_) {
    enable_rtx_ = enable;
    return true;
  } else {
    RTC_LOG(LS_WARNING) << "Cannot toggle rtx after initialization!";
    return false;
  }
}

void ChannelManager::GetSupportedAudioSendCodecs(
    std::vector<AudioCodec>* codecs) const {
  if (!media_engine_) {
    return;
  }
  *codecs = media_engine_->voice().send_codecs();
}

void ChannelManager::GetSupportedAudioReceiveCodecs(
    std::vector<AudioCodec>* codecs) const {
  if (!media_engine_) {
    return;
  }
  *codecs = media_engine_->voice().recv_codecs();
}

void ChannelManager::GetSupportedAudioRtpHeaderExtensions(
    RtpHeaderExtensions* ext) const {
  if (!media_engine_) {
    return;
  }
  *ext = media_engine_->voice().GetCapabilities().header_extensions;
}

void ChannelManager::GetSupportedVideoSendCodecs(
    std::vector<VideoCodec>* codecs) const {
  if (!media_engine_) {
    return;
  }
  codecs->clear();

  std::vector<VideoCodec> video_codecs = media_engine_->video().send_codecs();
  for (const auto& video_codec : video_codecs) {
    if (!enable_rtx_ &&
        absl::EqualsIgnoreCase(kRtxCodecName, video_codec.name)) {
      continue;
    }
    codecs->push_back(video_codec);
  }
}

void ChannelManager::GetSupportedVideoReceiveCodecs(
    std::vector<VideoCodec>* codecs) const {
  if (!media_engine_) {
    return;
  }
  codecs->clear();

  std::vector<VideoCodec> video_codecs = media_engine_->video().recv_codecs();
  for (const auto& video_codec : video_codecs) {
    if (!enable_rtx_ &&
        absl::EqualsIgnoreCase(kRtxCodecName, video_codec.name)) {
      continue;
    }
    codecs->push_back(video_codec);
  }
}

void ChannelManager::GetSupportedVideoRtpHeaderExtensions(
    RtpHeaderExtensions* ext) const {
  if (!media_engine_) {
    return;
  }
  *ext = media_engine_->video().GetCapabilities().header_extensions;
}

void ChannelManager::GetSupportedDataCodecs(
    std::vector<DataCodec>* codecs) const {
  *codecs = data_engine_->data_codecs();
}

bool ChannelManager::Init() {
  RTC_DCHECK(!initialized_);
  if (initialized_) {
    return false;
  }
  RTC_DCHECK(network_thread_);
  RTC_DCHECK(worker_thread_);
  if (!network_thread_->IsCurrent()) {
    // Do not allow invoking calls to other threads on the network thread.
    network_thread_->Invoke<void>(
        RTC_FROM_HERE, [&] { network_thread_->DisallowBlockingCalls(); });
  }

  if (media_engine_) {
    initialized_ = worker_thread_->Invoke<bool>(
        RTC_FROM_HERE, [&] { return media_engine_->Init(); });
    RTC_DCHECK(initialized_);
  } else {
    initialized_ = true;
  }
  return initialized_;
}

void ChannelManager::Terminate() {
  RTC_DCHECK(initialized_);
  if (!initialized_) {
    return;
  }
  // Need to destroy the channels on the worker thread.
  worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
    video_channels_.clear();
    voice_channels_.clear();
    data_channels_.clear();
  });
  initialized_ = false;
}

VoiceChannel* ChannelManager::CreateVoiceChannel(
    webrtc::Call* call,
    const cricket::MediaConfig& media_config,
    webrtc::RtpTransportInternal* rtp_transport,
    const webrtc::MediaTransportConfig& media_transport_config,
    rtc::Thread* signaling_thread,
    const std::string& content_name,
    bool srtp_required,
    const webrtc::CryptoOptions& crypto_options,
    rtc::UniqueRandomIdGenerator* ssrc_generator,
    const AudioOptions& options) {
  if (!worker_thread_->IsCurrent()) {
    return worker_thread_->Invoke<VoiceChannel*>(RTC_FROM_HERE, [&] {
      return CreateVoiceChannel(call, media_config, rtp_transport,
                                media_transport_config, signaling_thread,
                                content_name, srtp_required, crypto_options,
                                ssrc_generator, options);
    });
  }

  RTC_DCHECK_RUN_ON(worker_thread_);
  RTC_DCHECK(initialized_);
  RTC_DCHECK(call);
  if (!media_engine_) {
    return nullptr;
  }

  VoiceMediaChannel* media_channel = media_engine_->voice().CreateMediaChannel(
      call, media_config, options, crypto_options);
  if (!media_channel) {
    return nullptr;
  }

  auto voice_channel = std::make_unique<VoiceChannel>(
      worker_thread_, network_thread_, signaling_thread,
      absl::WrapUnique(media_channel), content_name, srtp_required,
      crypto_options, ssrc_generator);

  voice_channel->Init_w(rtp_transport, media_transport_config);

  VoiceChannel* voice_channel_ptr = voice_channel.get();
  voice_channels_.push_back(std::move(voice_channel));
  return voice_channel_ptr;
}

void ChannelManager::DestroyVoiceChannel(VoiceChannel* voice_channel) {
  TRACE_EVENT0("webrtc", "ChannelManager::DestroyVoiceChannel");
  if (!voice_channel) {
    return;
  }
  if (!worker_thread_->IsCurrent()) {
    worker_thread_->Invoke<void>(RTC_FROM_HERE,
                                 [&] { DestroyVoiceChannel(voice_channel); });
    return;
  }

  RTC_DCHECK(initialized_);

  auto it = absl::c_find_if(voice_channels_,
                            [&](const std::unique_ptr<VoiceChannel>& p) {
                              return p.get() == voice_channel;
                            });
  RTC_DCHECK(it != voice_channels_.end());
  if (it == voice_channels_.end()) {
    return;
  }

  voice_channels_.erase(it);
}

VideoChannel* ChannelManager::CreateVideoChannel(
    webrtc::Call* call,
    const cricket::MediaConfig& media_config,
    webrtc::RtpTransportInternal* rtp_transport,
    const webrtc::MediaTransportConfig& media_transport_config,
    rtc::Thread* signaling_thread,
    const std::string& content_name,
    bool srtp_required,
    const webrtc::CryptoOptions& crypto_options,
    rtc::UniqueRandomIdGenerator* ssrc_generator,
    const VideoOptions& options,
    webrtc::VideoBitrateAllocatorFactory* video_bitrate_allocator_factory) {
  if (!worker_thread_->IsCurrent()) {
    return worker_thread_->Invoke<VideoChannel*>(RTC_FROM_HERE, [&] {
      return CreateVideoChannel(
          call, media_config, rtp_transport, media_transport_config,
          signaling_thread, content_name, srtp_required, crypto_options,
          ssrc_generator, options, video_bitrate_allocator_factory);
    });
  }

  RTC_DCHECK_RUN_ON(worker_thread_);
  RTC_DCHECK(initialized_);
  RTC_DCHECK(call);
  if (!media_engine_) {
    return nullptr;
  }

  VideoMediaChannel* media_channel = media_engine_->video().CreateMediaChannel(
      call, media_config, options, crypto_options,
      video_bitrate_allocator_factory);
  if (!media_channel) {
    return nullptr;
  }

  auto video_channel = std::make_unique<VideoChannel>(
      worker_thread_, network_thread_, signaling_thread,
      absl::WrapUnique(media_channel), content_name, srtp_required,
      crypto_options, ssrc_generator);

  video_channel->Init_w(rtp_transport, media_transport_config);

  VideoChannel* video_channel_ptr = video_channel.get();
  video_channels_.push_back(std::move(video_channel));
  return video_channel_ptr;
}

void ChannelManager::DestroyVideoChannel(VideoChannel* video_channel) {
  TRACE_EVENT0("webrtc", "ChannelManager::DestroyVideoChannel");
  if (!video_channel) {
    return;
  }
  if (!worker_thread_->IsCurrent()) {
    worker_thread_->Invoke<void>(RTC_FROM_HERE,
                                 [&] { DestroyVideoChannel(video_channel); });
    return;
  }

  RTC_DCHECK(initialized_);

  auto it = absl::c_find_if(video_channels_,
                            [&](const std::unique_ptr<VideoChannel>& p) {
                              return p.get() == video_channel;
                            });
  RTC_DCHECK(it != video_channels_.end());
  if (it == video_channels_.end()) {
    return;
  }

  video_channels_.erase(it);
}

RtpDataChannel* ChannelManager::CreateRtpDataChannel(
    const cricket::MediaConfig& media_config,
    webrtc::RtpTransportInternal* rtp_transport,
    rtc::Thread* signaling_thread,
    const std::string& content_name,
    bool srtp_required,
    const webrtc::CryptoOptions& crypto_options,
    rtc::UniqueRandomIdGenerator* ssrc_generator) {
  if (!worker_thread_->IsCurrent()) {
    return worker_thread_->Invoke<RtpDataChannel*>(RTC_FROM_HERE, [&] {
      return CreateRtpDataChannel(media_config, rtp_transport, signaling_thread,
                                  content_name, srtp_required, crypto_options,
                                  ssrc_generator);
    });
  }

  // This is ok to alloc from a thread other than the worker thread.
  RTC_DCHECK(initialized_);
  DataMediaChannel* media_channel = data_engine_->CreateChannel(media_config);
  if (!media_channel) {
    RTC_LOG(LS_WARNING) << "Failed to create RTP data channel.";
    return nullptr;
  }

  auto data_channel = std::make_unique<RtpDataChannel>(
      worker_thread_, network_thread_, signaling_thread,
      absl::WrapUnique(media_channel), content_name, srtp_required,
      crypto_options, ssrc_generator);

  // Media Transports are not supported with Rtp Data Channel.
  data_channel->Init_w(rtp_transport, webrtc::MediaTransportConfig());

  RtpDataChannel* data_channel_ptr = data_channel.get();
  data_channels_.push_back(std::move(data_channel));
  return data_channel_ptr;
}

void ChannelManager::DestroyRtpDataChannel(RtpDataChannel* data_channel) {
  TRACE_EVENT0("webrtc", "ChannelManager::DestroyRtpDataChannel");
  if (!data_channel) {
    return;
  }
  if (!worker_thread_->IsCurrent()) {
    worker_thread_->Invoke<void>(
        RTC_FROM_HERE, [&] { return DestroyRtpDataChannel(data_channel); });
    return;
  }

  RTC_DCHECK(initialized_);

  auto it = absl::c_find_if(data_channels_,
                            [&](const std::unique_ptr<RtpDataChannel>& p) {
                              return p.get() == data_channel;
                            });
  RTC_DCHECK(it != data_channels_.end());
  if (it == data_channels_.end()) {
    return;
  }

  data_channels_.erase(it);
}

bool ChannelManager::StartAecDump(webrtc::FileWrapper file,
                                  int64_t max_size_bytes) {
  return worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
    return media_engine_->voice().StartAecDump(std::move(file), max_size_bytes);
  });
}

void ChannelManager::StopAecDump() {
  worker_thread_->Invoke<void>(RTC_FROM_HERE,
                               [&] { media_engine_->voice().StopAecDump(); });
}

}  // namespace cricket
