/*
 *  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 = 1;
    }
  }
}

void FillVideoSenderParameters(webrtc::RtpParameters* parameters) {
  for (webrtc::RtpCodecParameters& codec : parameters->codecs) {
    if (!codec.clock_rate) {
      codec.clock_rate = 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: {
      auto* audio_sender = new AudioRtpSender(
          rtp_transport_controller_->worker_thread(), nullptr);
      auto* voice_channel = rtp_transport_controller_->voice_channel();
      RTC_DCHECK(voice_channel);
      audio_sender->SetVoiceMediaChannel(voice_channel->media_channel());
      internal_sender_ = audio_sender;
      break;
    }
    case cricket::MEDIA_TYPE_VIDEO: {
      auto* video_sender =
          new VideoRtpSender(rtp_transport_controller_->worker_thread());
      auto* video_channel = rtp_transport_controller_->video_channel();
      RTC_DCHECK(video_channel);
      video_sender->SetVideoMediaChannel(video_channel->media_channel());
      internal_sender_ = video_sender;
      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
