/*
 *  Copyright (c) 2018 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 <utility>

#include "call/degraded_call.h"

#include "absl/memory/memory.h"

namespace webrtc {
DegradedCall::DegradedCall(
    std::unique_ptr<Call> call,
    absl::optional<DefaultNetworkSimulationConfig> send_config,
    absl::optional<DefaultNetworkSimulationConfig> receive_config)
    : clock_(Clock::GetRealTimeClock()),
      call_(std::move(call)),
      send_config_(send_config),
      send_process_thread_(
          send_config_ ? ProcessThread::Create("DegradedSendThread") : nullptr),
      num_send_streams_(0),
      receive_config_(receive_config) {
  if (receive_config_) {
    auto network = absl::make_unique<SimulatedNetwork>(*receive_config_);
    receive_simulated_network_ = network.get();
    receive_pipe_ =
        absl::make_unique<webrtc::FakeNetworkPipe>(clock_, std::move(network));
    receive_pipe_->SetReceiver(call_->Receiver());
  }
  if (send_process_thread_) {
    send_process_thread_->Start();
  }
}

DegradedCall::~DegradedCall() {
  if (send_pipe_) {
    send_process_thread_->DeRegisterModule(send_pipe_.get());
  }
  if (send_process_thread_) {
    send_process_thread_->Stop();
  }
}

AudioSendStream* DegradedCall::CreateAudioSendStream(
    const AudioSendStream::Config& config) {
  return call_->CreateAudioSendStream(config);
}

void DegradedCall::DestroyAudioSendStream(AudioSendStream* send_stream) {
  call_->DestroyAudioSendStream(send_stream);
}

AudioReceiveStream* DegradedCall::CreateAudioReceiveStream(
    const AudioReceiveStream::Config& config) {
  return call_->CreateAudioReceiveStream(config);
}

void DegradedCall::DestroyAudioReceiveStream(
    AudioReceiveStream* receive_stream) {
  call_->DestroyAudioReceiveStream(receive_stream);
}

VideoSendStream* DegradedCall::CreateVideoSendStream(
    VideoSendStream::Config config,
    VideoEncoderConfig encoder_config) {
  if (send_config_ && !send_pipe_) {
    auto network = absl::make_unique<SimulatedNetwork>(*send_config_);
    send_simulated_network_ = network.get();
    send_pipe_ = absl::make_unique<FakeNetworkPipe>(clock_, std::move(network),
                                                    config.send_transport);
    config.send_transport = this;
    send_process_thread_->RegisterModule(send_pipe_.get(), RTC_FROM_HERE);
  }
  ++num_send_streams_;
  return call_->CreateVideoSendStream(std::move(config),
                                      std::move(encoder_config));
}

VideoSendStream* DegradedCall::CreateVideoSendStream(
    VideoSendStream::Config config,
    VideoEncoderConfig encoder_config,
    std::unique_ptr<FecController> fec_controller) {
  if (send_config_ && !send_pipe_) {
    auto network = absl::make_unique<SimulatedNetwork>(*send_config_);
    send_simulated_network_ = network.get();
    send_pipe_ = absl::make_unique<FakeNetworkPipe>(clock_, std::move(network),
                                                    config.send_transport);
    config.send_transport = this;
    send_process_thread_->RegisterModule(send_pipe_.get(), RTC_FROM_HERE);
  }
  ++num_send_streams_;
  return call_->CreateVideoSendStream(
      std::move(config), std::move(encoder_config), std::move(fec_controller));
}

void DegradedCall::DestroyVideoSendStream(VideoSendStream* send_stream) {
  call_->DestroyVideoSendStream(send_stream);
  if (send_pipe_ && num_send_streams_ > 0) {
    --num_send_streams_;
    if (num_send_streams_ == 0) {
      send_process_thread_->DeRegisterModule(send_pipe_.get());
      send_pipe_.reset();
    }
  }
}

VideoReceiveStream* DegradedCall::CreateVideoReceiveStream(
    VideoReceiveStream::Config configuration) {
  return call_->CreateVideoReceiveStream(std::move(configuration));
}

void DegradedCall::DestroyVideoReceiveStream(
    VideoReceiveStream* receive_stream) {
  call_->DestroyVideoReceiveStream(receive_stream);
}

FlexfecReceiveStream* DegradedCall::CreateFlexfecReceiveStream(
    const FlexfecReceiveStream::Config& config) {
  return call_->CreateFlexfecReceiveStream(config);
}

void DegradedCall::DestroyFlexfecReceiveStream(
    FlexfecReceiveStream* receive_stream) {
  call_->DestroyFlexfecReceiveStream(receive_stream);
}

PacketReceiver* DegradedCall::Receiver() {
  if (receive_config_) {
    return this;
  }
  return call_->Receiver();
}

RtpTransportControllerSendInterface*
DegradedCall::GetTransportControllerSend() {
  return call_->GetTransportControllerSend();
}

Call::Stats DegradedCall::GetStats() const {
  return call_->GetStats();
}

void DegradedCall::SetBitrateAllocationStrategy(
    std::unique_ptr<rtc::BitrateAllocationStrategy>
        bitrate_allocation_strategy) {
  call_->SetBitrateAllocationStrategy(std::move(bitrate_allocation_strategy));
}

void DegradedCall::SignalChannelNetworkState(MediaType media,
                                             NetworkState state) {
  call_->SignalChannelNetworkState(media, state);
}

void DegradedCall::OnTransportOverheadChanged(
    MediaType media,
    int transport_overhead_per_packet) {
  call_->OnTransportOverheadChanged(media, transport_overhead_per_packet);
}

void DegradedCall::OnSentPacket(const rtc::SentPacket& sent_packet) {
  if (send_config_) {
    // If we have a degraded send-transport, we have already notified call
    // about the supposed network send time. Discard the actual network send
    // time in order to properly fool the BWE.
    return;
  }
  call_->OnSentPacket(sent_packet);
}

bool DegradedCall::SendRtp(const uint8_t* packet,
                           size_t length,
                           const PacketOptions& options) {
  // A call here comes from the RTP stack (probably pacer). We intercept it and
  // put it in the fake network pipe instead, but report to Call that is has
  // been sent, so that the bandwidth estimator sees the delay we add.
  send_pipe_->SendRtp(packet, length, options);
  if (options.packet_id != -1) {
    rtc::SentPacket packet_info;
    packet_info.packet_id = options.packet_id;
    packet_info.send_time_ms = clock_->TimeInMilliseconds();
    call_->OnSentPacket(packet_info);
  }
  return true;
}

bool DegradedCall::SendRtcp(const uint8_t* packet, size_t length) {
  send_pipe_->SendRtcp(packet, length);
  return true;
}

PacketReceiver::DeliveryStatus DegradedCall::DeliverPacket(
    MediaType media_type,
    rtc::CopyOnWriteBuffer packet,
    int64_t packet_time_us) {
  PacketReceiver::DeliveryStatus status = receive_pipe_->DeliverPacket(
      media_type, std::move(packet), packet_time_us);
  // This is not optimal, but there are many places where there are thread
  // checks that fail if we're not using the worker thread call into this
  // method. If we want to fix this we probably need a task queue to do handover
  // of all overriden methods, which feels like overikill for the current use
  // case.
  // By just having this thread call out via the Process() method we work around
  // that, with the tradeoff that a non-zero delay may become a little larger
  // than anticipated at very low packet rates.
  receive_pipe_->Process();
  return status;
}

}  // namespace webrtc
