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

#include <utility>

#include "media/base/mediaconstants.h"
#include "ortc/rtptransportadapter.h"
#include "rtc_base/checks.h"

namespace {

void FillAudioSenderParameters(webrtc::RtpParameters* parameters) {
  for (webrtc::RtpCodecParameters& codec : parameters->codecs) {
    if (!codec.num_channels) {
      codec.num_channels = rtc::Optional<int>(1);
    }
  }
}

void FillVideoSenderParameters(webrtc::RtpParameters* parameters) {
  for (webrtc::RtpCodecParameters& codec : parameters->codecs) {
    if (!codec.clock_rate) {
      codec.clock_rate = rtc::Optional<int>(cricket::kVideoCodecClockrate);
    }
  }
}

}  // namespace

namespace webrtc {

BEGIN_OWNED_PROXY_MAP(OrtcRtpSender)
PROXY_SIGNALING_THREAD_DESTRUCTOR()
PROXY_METHOD1(RTCError, SetTrack, MediaStreamTrackInterface*)
PROXY_CONSTMETHOD0(rtc::scoped_refptr<MediaStreamTrackInterface>, GetTrack)
PROXY_METHOD1(RTCError, SetTransport, RtpTransportInterface*)
PROXY_CONSTMETHOD0(RtpTransportInterface*, GetTransport)
PROXY_METHOD1(RTCError, Send, const RtpParameters&)
PROXY_CONSTMETHOD0(RtpParameters, GetParameters)
PROXY_CONSTMETHOD0(cricket::MediaType, GetKind)
END_PROXY_MAP()

// static
std::unique_ptr<OrtcRtpSenderInterface> OrtcRtpSenderAdapter::CreateProxy(
    std::unique_ptr<OrtcRtpSenderAdapter> wrapped_sender) {
  RTC_DCHECK(wrapped_sender);
  rtc::Thread* signaling =
      wrapped_sender->rtp_transport_controller_->signaling_thread();
  rtc::Thread* worker =
      wrapped_sender->rtp_transport_controller_->worker_thread();
  return OrtcRtpSenderProxy::Create(signaling, worker,
                                    std::move(wrapped_sender));
}

OrtcRtpSenderAdapter::~OrtcRtpSenderAdapter() {
  internal_sender_ = nullptr;
  SignalDestroyed();
}

RTCError OrtcRtpSenderAdapter::SetTrack(MediaStreamTrackInterface* track) {
  if (track && cricket::MediaTypeFromString(track->kind()) != kind_) {
    LOG_AND_RETURN_ERROR(
        RTCErrorType::INVALID_PARAMETER,
        "Track kind (audio/video) doesn't match the kind of this sender.");
  }
  if (internal_sender_ && !internal_sender_->SetTrack(track)) {
    // Since we checked the track type above, this should never happen...
    RTC_NOTREACHED();
    LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
                         "Failed to set track on RtpSender.");
  }
  track_ = track;
  return RTCError::OK();
}

rtc::scoped_refptr<MediaStreamTrackInterface> OrtcRtpSenderAdapter::GetTrack()
    const {
  return track_;
}

RTCError OrtcRtpSenderAdapter::SetTransport(RtpTransportInterface* transport) {
  LOG_AND_RETURN_ERROR(
      RTCErrorType::UNSUPPORTED_OPERATION,
      "Changing the transport of an RtpSender is not yet supported.");
}

RtpTransportInterface* OrtcRtpSenderAdapter::GetTransport() const {
  return transport_;
}

RTCError OrtcRtpSenderAdapter::Send(const RtpParameters& parameters) {
  RtpParameters filled_parameters = parameters;
  RTCError err;
  uint32_t ssrc = 0;
  switch (kind_) {
    case cricket::MEDIA_TYPE_AUDIO:
      FillAudioSenderParameters(&filled_parameters);
      err = rtp_transport_controller_->ValidateAndApplyAudioSenderParameters(
          filled_parameters, &ssrc);
      if (!err.ok()) {
        return err;
      }
      break;
    case cricket::MEDIA_TYPE_VIDEO:
      FillVideoSenderParameters(&filled_parameters);
      err = rtp_transport_controller_->ValidateAndApplyVideoSenderParameters(
          filled_parameters, &ssrc);
      if (!err.ok()) {
        return err;
      }
      break;
    case cricket::MEDIA_TYPE_DATA:
      RTC_NOTREACHED();
      return webrtc::RTCError(webrtc::RTCErrorType::INTERNAL_ERROR);
  }
  last_applied_parameters_ = filled_parameters;

  // Now that parameters were applied, can call SetSsrc on the internal sender.
  // This is analogous to a PeerConnection calling SetSsrc after
  // SetLocalDescription is successful.
  //
  // If there were no encodings, this SSRC may be 0, which is valid.
  if (!internal_sender_) {
    CreateInternalSender();
  }
  internal_sender_->SetSsrc(ssrc);

  return RTCError::OK();
}

RtpParameters OrtcRtpSenderAdapter::GetParameters() const {
  return last_applied_parameters_;
}

cricket::MediaType OrtcRtpSenderAdapter::GetKind() const {
  return kind_;
}

OrtcRtpSenderAdapter::OrtcRtpSenderAdapter(
    cricket::MediaType kind,
    RtpTransportInterface* transport,
    RtpTransportControllerAdapter* rtp_transport_controller)
    : kind_(kind),
      transport_(transport),
      rtp_transport_controller_(rtp_transport_controller) {}

void OrtcRtpSenderAdapter::CreateInternalSender() {
  switch (kind_) {
    case cricket::MEDIA_TYPE_AUDIO:
      internal_sender_ = new AudioRtpSender(
          rtp_transport_controller_->voice_channel(), nullptr);
      break;
    case cricket::MEDIA_TYPE_VIDEO:
      internal_sender_ =
          new VideoRtpSender(rtp_transport_controller_->video_channel());
      break;
    case cricket::MEDIA_TYPE_DATA:
      RTC_NOTREACHED();
  }
  if (track_) {
    if (!internal_sender_->SetTrack(track_)) {
      // Since we checked the track type when it was set, this should never
      // happen...
      RTC_NOTREACHED();
    }
  }
}

}  // namespace webrtc
