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

#include <utility>

#include "webrtc/media/base/mediaconstants.h"
#include "webrtc/ortc/rtptransportadapter.h"
#include "webrtc/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
