/*
 *  Copyright 2017 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 "ortc/ortcfactory.h"

#include <sstream>
#include <utility>  // For std::move.
#include <vector>

#include "absl/memory/memory.h"
#include "api/mediastreamtrackproxy.h"
#include "api/proxy.h"
#include "api/rtcerror.h"
#include "api/video_codecs/builtin_video_decoder_factory.h"
#include "api/video_codecs/builtin_video_encoder_factory.h"
#include "api/videosourceproxy.h"
#include "logging/rtc_event_log/rtc_event_log.h"
#include "media/base/mediaconstants.h"
#include "media/base/rtpdataengine.h"
#include "modules/audio_processing/include/audio_processing.h"
#include "ortc/ortcrtpreceiveradapter.h"
#include "ortc/ortcrtpsenderadapter.h"
#include "ortc/rtptransportadapter.h"
#include "ortc/rtptransportcontrolleradapter.h"
#include "p2p/base/basicpacketsocketfactory.h"
#include "p2p/base/udptransport.h"
#include "pc/audiotrack.h"
#include "pc/channelmanager.h"
#include "pc/localaudiosource.h"
#include "pc/rtpparametersconversion.h"
#include "pc/videotrack.h"
#include "rtc_base/asyncpacketsocket.h"
#include "rtc_base/bind.h"
#include "rtc_base/checks.h"
#include "rtc_base/helpers.h"
#include "rtc_base/logging.h"

namespace {

const int kDefaultRtcpCnameLength = 16;

// Asserts that all of the built-in capabilities can be converted to
// RtpCapabilities. If they can't, something's wrong (for example, maybe a new
// feedback mechanism is supported, but an enum value wasn't added to
// rtpparameters.h).
template <typename C>
webrtc::RtpCapabilities ToRtpCapabilitiesWithAsserts(
    const std::vector<C>& cricket_codecs,
    const cricket::RtpHeaderExtensions& cricket_extensions) {
  webrtc::RtpCapabilities capabilities =
      webrtc::ToRtpCapabilities(cricket_codecs, cricket_extensions);
  RTC_DCHECK_EQ(capabilities.codecs.size(), cricket_codecs.size());
  for (size_t i = 0; i < capabilities.codecs.size(); ++i) {
    RTC_DCHECK_EQ(capabilities.codecs[i].rtcp_feedback.size(),
                  cricket_codecs[i].feedback_params.params().size());
  }
  RTC_DCHECK_EQ(capabilities.header_extensions.size(),
                cricket_extensions.size());
  return capabilities;
}

}  // namespace

namespace webrtc {

// Note that this proxy class uses the network thread as the "worker" thread.
BEGIN_OWNED_PROXY_MAP(OrtcFactory)
PROXY_SIGNALING_THREAD_DESTRUCTOR()
PROXY_METHOD0(RTCErrorOr<std::unique_ptr<RtpTransportControllerInterface>>,
              CreateRtpTransportController)
PROXY_METHOD4(RTCErrorOr<std::unique_ptr<RtpTransportInterface>>,
              CreateRtpTransport,
              const RtpTransportParameters&,
              PacketTransportInterface*,
              PacketTransportInterface*,
              RtpTransportControllerInterface*)

PROXY_METHOD4(RTCErrorOr<std::unique_ptr<SrtpTransportInterface>>,
              CreateSrtpTransport,
              const RtpTransportParameters&,
              PacketTransportInterface*,
              PacketTransportInterface*,
              RtpTransportControllerInterface*)

PROXY_CONSTMETHOD1(RtpCapabilities,
                   GetRtpSenderCapabilities,
                   cricket::MediaType)
PROXY_METHOD2(RTCErrorOr<std::unique_ptr<OrtcRtpSenderInterface>>,
              CreateRtpSender,
              rtc::scoped_refptr<MediaStreamTrackInterface>,
              RtpTransportInterface*)
PROXY_METHOD2(RTCErrorOr<std::unique_ptr<OrtcRtpSenderInterface>>,
              CreateRtpSender,
              cricket::MediaType,
              RtpTransportInterface*)
PROXY_CONSTMETHOD1(RtpCapabilities,
                   GetRtpReceiverCapabilities,
                   cricket::MediaType)
PROXY_METHOD2(RTCErrorOr<std::unique_ptr<OrtcRtpReceiverInterface>>,
              CreateRtpReceiver,
              cricket::MediaType,
              RtpTransportInterface*)
PROXY_WORKER_METHOD3(RTCErrorOr<std::unique_ptr<UdpTransportInterface>>,
                     CreateUdpTransport,
                     int,
                     uint16_t,
                     uint16_t)
PROXY_METHOD1(rtc::scoped_refptr<AudioSourceInterface>,
              CreateAudioSource,
              const cricket::AudioOptions&)
PROXY_METHOD2(rtc::scoped_refptr<VideoTrackInterface>,
              CreateVideoTrack,
              const std::string&,
              VideoTrackSourceInterface*)
PROXY_METHOD2(rtc::scoped_refptr<AudioTrackInterface>,
              CreateAudioTrack,
              const std::string&,
              AudioSourceInterface*)
END_PROXY_MAP()

// static
RTCErrorOr<std::unique_ptr<OrtcFactoryInterface>> OrtcFactory::Create(
    rtc::Thread* network_thread,
    rtc::Thread* signaling_thread,
    rtc::NetworkManager* network_manager,
    rtc::PacketSocketFactory* socket_factory,
    AudioDeviceModule* adm,
    std::unique_ptr<cricket::MediaEngineInterface> media_engine,
    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory) {
  // Hop to signaling thread if needed.
  if (signaling_thread && !signaling_thread->IsCurrent()) {
    return signaling_thread
        ->Invoke<RTCErrorOr<std::unique_ptr<OrtcFactoryInterface>>>(
            RTC_FROM_HERE,
            rtc::Bind(&OrtcFactory::Create_s, network_thread, signaling_thread,
                      network_manager, socket_factory, adm,
                      media_engine.release(), audio_encoder_factory,
                      audio_decoder_factory));
  }
  return Create_s(network_thread, signaling_thread, network_manager,
                  socket_factory, adm, media_engine.release(),
                  audio_encoder_factory, audio_decoder_factory);
}

RTCErrorOr<std::unique_ptr<OrtcFactoryInterface>> OrtcFactoryInterface::Create(
    rtc::Thread* network_thread,
    rtc::Thread* signaling_thread,
    rtc::NetworkManager* network_manager,
    rtc::PacketSocketFactory* socket_factory,
    AudioDeviceModule* adm,
    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory) {
  return OrtcFactory::Create(network_thread, signaling_thread, network_manager,
                             socket_factory, adm, nullptr,
                             audio_encoder_factory, audio_decoder_factory);
}

OrtcFactory::OrtcFactory(
    rtc::Thread* network_thread,
    rtc::Thread* signaling_thread,
    rtc::NetworkManager* network_manager,
    rtc::PacketSocketFactory* socket_factory,
    AudioDeviceModule* adm,
    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory)
    : network_thread_(network_thread),
      signaling_thread_(signaling_thread),
      network_manager_(network_manager),
      socket_factory_(socket_factory),
      adm_(adm),
      null_event_log_(RtcEventLog::CreateNull()),
      audio_encoder_factory_(audio_encoder_factory),
      audio_decoder_factory_(audio_decoder_factory) {
  if (!rtc::CreateRandomString(kDefaultRtcpCnameLength, &default_cname_)) {
    RTC_LOG(LS_ERROR) << "Failed to generate CNAME?";
    RTC_NOTREACHED();
  }
  if (!network_thread_) {
    owned_network_thread_ = rtc::Thread::CreateWithSocketServer();
    owned_network_thread_->Start();
    network_thread_ = owned_network_thread_.get();
  }

  // The worker thread is created internally because it's an implementation
  // detail, and consumers of the API don't need to really know about it.
  worker_thread_ = rtc::Thread::Create();
  worker_thread_->SetName("ORTC-worker", this);
  worker_thread_->Start();

  if (signaling_thread_) {
    RTC_DCHECK_RUN_ON(signaling_thread_);
  } else {
    signaling_thread_ = rtc::Thread::Current();
    if (!signaling_thread_) {
      // If this thread isn't already wrapped by an rtc::Thread, create a
      // wrapper and own it in this class.
      signaling_thread_ = rtc::ThreadManager::Instance()->WrapCurrentThread();
      wraps_signaling_thread_ = true;
    }
  }

  if (signaling_thread_->name().empty()) {
    signaling_thread_->SetName("ORTC-signaling", this);
  }

  if (!network_manager_) {
    owned_network_manager_.reset(new rtc::BasicNetworkManager());
    network_manager_ = owned_network_manager_.get();
  }
  if (!socket_factory_) {
    owned_socket_factory_.reset(
        new rtc::BasicPacketSocketFactory(network_thread_));
    socket_factory_ = owned_socket_factory_.get();
  }
}

OrtcFactory::~OrtcFactory() {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  if (wraps_signaling_thread_) {
    rtc::ThreadManager::Instance()->UnwrapCurrentThread();
  }
}

RTCErrorOr<std::unique_ptr<RtpTransportControllerInterface>>
OrtcFactory::CreateRtpTransportController() {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  return RtpTransportControllerAdapter::CreateProxied(
      cricket::MediaConfig(), channel_manager_.get(), null_event_log_.get(),
      signaling_thread_, worker_thread_.get(), network_thread_);
}

RTCErrorOr<std::unique_ptr<RtpTransportInterface>>
OrtcFactory::CreateRtpTransport(
    const RtpTransportParameters& parameters,
    PacketTransportInterface* rtp,
    PacketTransportInterface* rtcp,
    RtpTransportControllerInterface* transport_controller) {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  RtpTransportParameters copied_parameters = parameters;
  if (copied_parameters.rtcp.cname.empty()) {
    copied_parameters.rtcp.cname = default_cname_;
  }
  if (transport_controller) {
    return transport_controller->GetInternal()->CreateProxiedRtpTransport(
        copied_parameters, rtp, rtcp);
  } else {
    // If |transport_controller| is null, create one automatically, which the
    // returned RtpTransport will own.
    auto controller_result = CreateRtpTransportController();
    if (!controller_result.ok()) {
      return controller_result.MoveError();
    }
    auto controller = controller_result.MoveValue();
    auto transport_result =
        controller->GetInternal()->CreateProxiedRtpTransport(copied_parameters,
                                                             rtp, rtcp);
    // If RtpTransport was successfully created, transfer ownership of
    // |rtp_transport_controller|. Otherwise it will go out of scope and be
    // deleted automatically.
    if (transport_result.ok()) {
      transport_result.value()
          ->GetInternal()
          ->TakeOwnershipOfRtpTransportController(std::move(controller));
    }
    return transport_result;
  }
}

RTCErrorOr<std::unique_ptr<SrtpTransportInterface>>
OrtcFactory::CreateSrtpTransport(
    const RtpTransportParameters& parameters,
    PacketTransportInterface* rtp,
    PacketTransportInterface* rtcp,
    RtpTransportControllerInterface* transport_controller) {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  RtpTransportParameters copied_parameters = parameters;
  if (copied_parameters.rtcp.cname.empty()) {
    copied_parameters.rtcp.cname = default_cname_;
  }
  if (transport_controller) {
    return transport_controller->GetInternal()->CreateProxiedSrtpTransport(
        copied_parameters, rtp, rtcp);
  } else {
    // If |transport_controller| is null, create one automatically, which the
    // returned SrtpTransport will own.
    auto controller_result = CreateRtpTransportController();
    if (!controller_result.ok()) {
      return controller_result.MoveError();
    }
    auto controller = controller_result.MoveValue();
    auto transport_result =
        controller->GetInternal()->CreateProxiedSrtpTransport(copied_parameters,
                                                              rtp, rtcp);
    // If SrtpTransport was successfully created, transfer ownership of
    // |rtp_transport_controller|. Otherwise it will go out of scope and be
    // deleted automatically.
    if (transport_result.ok()) {
      transport_result.value()
          ->GetInternal()
          ->TakeOwnershipOfRtpTransportController(std::move(controller));
    }
    return transport_result;
  }
}

RtpCapabilities OrtcFactory::GetRtpSenderCapabilities(
    cricket::MediaType kind) const {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  switch (kind) {
    case cricket::MEDIA_TYPE_AUDIO: {
      cricket::AudioCodecs cricket_codecs;
      cricket::RtpHeaderExtensions cricket_extensions;
      channel_manager_->GetSupportedAudioSendCodecs(&cricket_codecs);
      channel_manager_->GetSupportedAudioRtpHeaderExtensions(
          &cricket_extensions);
      return ToRtpCapabilitiesWithAsserts(cricket_codecs, cricket_extensions);
    }
    case cricket::MEDIA_TYPE_VIDEO: {
      cricket::VideoCodecs cricket_codecs;
      cricket::RtpHeaderExtensions cricket_extensions;
      channel_manager_->GetSupportedVideoCodecs(&cricket_codecs);
      channel_manager_->GetSupportedVideoRtpHeaderExtensions(
          &cricket_extensions);
      return ToRtpCapabilitiesWithAsserts(cricket_codecs, cricket_extensions);
    }
    case cricket::MEDIA_TYPE_DATA:
      return RtpCapabilities();
  }
  // Not reached; avoids compile warning.
  FATAL();
}

RTCErrorOr<std::unique_ptr<OrtcRtpSenderInterface>>
OrtcFactory::CreateRtpSender(
    rtc::scoped_refptr<MediaStreamTrackInterface> track,
    RtpTransportInterface* transport) {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  if (!track) {
    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
                         "Cannot pass null track into CreateRtpSender.");
  }
  auto result =
      CreateRtpSender(cricket::MediaTypeFromString(track->kind()), transport);
  if (!result.ok()) {
    return result;
  }
  auto err = result.value()->SetTrack(track);
  if (!err.ok()) {
    return std::move(err);
  }
  return result;
}

RTCErrorOr<std::unique_ptr<OrtcRtpSenderInterface>>
OrtcFactory::CreateRtpSender(cricket::MediaType kind,
                             RtpTransportInterface* transport) {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  if (kind == cricket::MEDIA_TYPE_DATA) {
    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
                         "Cannot create data RtpSender.");
  }
  if (!transport) {
    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
                         "Cannot pass null transport into CreateRtpSender.");
  }
  return transport->GetInternal()
      ->rtp_transport_controller()
      ->CreateProxiedRtpSender(kind, transport);
}

RtpCapabilities OrtcFactory::GetRtpReceiverCapabilities(
    cricket::MediaType kind) const {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  switch (kind) {
    case cricket::MEDIA_TYPE_AUDIO: {
      cricket::AudioCodecs cricket_codecs;
      cricket::RtpHeaderExtensions cricket_extensions;
      channel_manager_->GetSupportedAudioReceiveCodecs(&cricket_codecs);
      channel_manager_->GetSupportedAudioRtpHeaderExtensions(
          &cricket_extensions);
      return ToRtpCapabilitiesWithAsserts(cricket_codecs, cricket_extensions);
    }
    case cricket::MEDIA_TYPE_VIDEO: {
      cricket::VideoCodecs cricket_codecs;
      cricket::RtpHeaderExtensions cricket_extensions;
      channel_manager_->GetSupportedVideoCodecs(&cricket_codecs);
      channel_manager_->GetSupportedVideoRtpHeaderExtensions(
          &cricket_extensions);
      return ToRtpCapabilitiesWithAsserts(cricket_codecs, cricket_extensions);
    }
    case cricket::MEDIA_TYPE_DATA:
      return RtpCapabilities();
  }
  // Not reached; avoids compile warning.
  FATAL();
}

RTCErrorOr<std::unique_ptr<OrtcRtpReceiverInterface>>
OrtcFactory::CreateRtpReceiver(cricket::MediaType kind,
                               RtpTransportInterface* transport) {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  if (kind == cricket::MEDIA_TYPE_DATA) {
    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
                         "Cannot create data RtpReceiver.");
  }
  if (!transport) {
    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
                         "Cannot pass null transport into CreateRtpReceiver.");
  }
  return transport->GetInternal()
      ->rtp_transport_controller()
      ->CreateProxiedRtpReceiver(kind, transport);
}

// UdpTransport expects all methods to be called on one thread, which needs to
// be the network thread, since that's where its socket can safely be used. So
// return a proxy to the created UdpTransport.
BEGIN_OWNED_PROXY_MAP(UdpTransport)
PROXY_WORKER_THREAD_DESTRUCTOR()
PROXY_WORKER_CONSTMETHOD0(rtc::SocketAddress, GetLocalAddress)
PROXY_WORKER_METHOD1(bool, SetRemoteAddress, const rtc::SocketAddress&)
PROXY_WORKER_CONSTMETHOD0(rtc::SocketAddress, GetRemoteAddress)
protected:
rtc::PacketTransportInternal* GetInternal() override {
  return internal();
}
END_PROXY_MAP()

RTCErrorOr<std::unique_ptr<UdpTransportInterface>>
OrtcFactory::CreateUdpTransport(int family,
                                uint16_t min_port,
                                uint16_t max_port) {
  RTC_DCHECK_RUN_ON(network_thread_);
  if (family != AF_INET && family != AF_INET6) {
    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
                         "Address family must be AF_INET or AF_INET6.");
  }
  if (min_port > max_port) {
    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
                         "Port range invalid; minimum port must be less than "
                         "or equal to max port.");
  }
  std::unique_ptr<rtc::AsyncPacketSocket> socket(
      socket_factory_->CreateUdpSocket(
          rtc::SocketAddress(rtc::GetAnyIP(family), 0), min_port, max_port));
  if (!socket) {
    // Only log at warning level, because this method may be called with
    // specific port ranges to determine if a port is available, expecting the
    // possibility of an error.
    LOG_AND_RETURN_ERROR_EX(RTCErrorType::RESOURCE_EXHAUSTED,
                            "Local socket allocation failure.", LS_WARNING);
  }
  RTC_LOG(LS_INFO) << "Created UDP socket with address "
                   << socket->GetLocalAddress().ToSensitiveString() << ".";
  // Make a unique debug name (for logging/diagnostics only).
  std::ostringstream oss;
  static int udp_id = 0;
  oss << "udp" << udp_id++;
  return UdpTransportProxyWithInternal<cricket::UdpTransport>::Create(
      signaling_thread_, network_thread_,
      std::unique_ptr<cricket::UdpTransport>(
          new cricket::UdpTransport(oss.str(), std::move(socket))));
}

rtc::scoped_refptr<AudioSourceInterface> OrtcFactory::CreateAudioSource(
    const cricket::AudioOptions& options) {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  return rtc::scoped_refptr<LocalAudioSource>(
      LocalAudioSource::Create(&options));
}

rtc::scoped_refptr<VideoTrackInterface> OrtcFactory::CreateVideoTrack(
    const std::string& id,
    VideoTrackSourceInterface* source) {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  rtc::scoped_refptr<VideoTrackInterface> track(
      VideoTrack::Create(id, source, worker_thread_.get()));
  return VideoTrackProxy::Create(signaling_thread_, worker_thread_.get(),
                                 track);
}

rtc::scoped_refptr<AudioTrackInterface> OrtcFactory::CreateAudioTrack(
    const std::string& id,
    AudioSourceInterface* source) {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  rtc::scoped_refptr<AudioTrackInterface> track(AudioTrack::Create(id, source));
  return AudioTrackProxy::Create(signaling_thread_, track);
}

// static
RTCErrorOr<std::unique_ptr<OrtcFactoryInterface>> OrtcFactory::Create_s(
    rtc::Thread* network_thread,
    rtc::Thread* signaling_thread,
    rtc::NetworkManager* network_manager,
    rtc::PacketSocketFactory* socket_factory,
    AudioDeviceModule* adm,
    cricket::MediaEngineInterface* media_engine,
    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory) {
  // Add the unique_ptr wrapper back.
  std::unique_ptr<cricket::MediaEngineInterface> owned_media_engine(
      media_engine);
  std::unique_ptr<OrtcFactory> new_factory(new OrtcFactory(
      network_thread, signaling_thread, network_manager, socket_factory, adm,
      audio_encoder_factory, audio_decoder_factory));
  RTCError err = new_factory->Initialize(std::move(owned_media_engine));
  if (!err.ok()) {
    return std::move(err);
  }
  // Return a proxy so that any calls on the returned object (including
  // destructor) happen on the signaling thread.
  rtc::Thread* signaling = new_factory->signaling_thread();
  rtc::Thread* network = new_factory->network_thread();
  return OrtcFactoryProxy::Create(signaling, network, std::move(new_factory));
}

RTCError OrtcFactory::Initialize(
    std::unique_ptr<cricket::MediaEngineInterface> media_engine) {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  // TODO(deadbeef): Get rid of requirement to hop to worker thread here.
  if (!media_engine) {
    media_engine =
        worker_thread_->Invoke<std::unique_ptr<cricket::MediaEngineInterface>>(
            RTC_FROM_HERE, rtc::Bind(&OrtcFactory::CreateMediaEngine_w, this));
  }

  channel_manager_.reset(new cricket::ChannelManager(
      std::move(media_engine), absl::make_unique<cricket::RtpDataEngine>(),
      worker_thread_.get(), network_thread_));
  channel_manager_->SetVideoRtxEnabled(true);
  if (!channel_manager_->Init()) {
    LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
                         "Failed to initialize ChannelManager.");
  }
  return RTCError::OK();
}

std::unique_ptr<cricket::MediaEngineInterface>
OrtcFactory::CreateMediaEngine_w() {
  RTC_DCHECK_RUN_ON(worker_thread_.get());
  // The null arguments are optional factories that could be passed into the
  // OrtcFactory, but aren't yet.
  //
  // Note that |adm_| may be null, in which case the platform-specific default
  // AudioDeviceModule will be used.
  return std::unique_ptr<cricket::MediaEngineInterface>(
      cricket::WebRtcMediaEngineFactory::Create(
          rtc::scoped_refptr<webrtc::AudioDeviceModule>(adm_),
          audio_encoder_factory_, audio_decoder_factory_,
          webrtc::CreateBuiltinVideoEncoderFactory(),
          webrtc::CreateBuiltinVideoDecoderFactory(), nullptr,
          webrtc::AudioProcessingBuilder().Create()));
}

}  // namespace webrtc
