/*
 *  Copyright (c) 2015 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 "modules/remote_bitrate_estimator/test/estimators/send_side.h"

#include <algorithm>

#include "modules/congestion_controller/delay_based_bwe.h"
#include "modules/remote_bitrate_estimator/test/bwe_test_logging.h"
#include "rtc_base/logging.h"
#include "rtc_base/ptr_util.h"

namespace webrtc {
namespace testing {
namespace bwe {

const int kFeedbackIntervalMs = 50;

SendSideBweSender::SendSideBweSender(int kbps,
                                     BitrateObserver* observer,
                                     Clock* clock)
    : bitrate_controller_(
          BitrateController::CreateBitrateController(clock,
                                                     observer,
                                                     &event_log_)),
      acknowledged_bitrate_estimator_(
          rtc::MakeUnique<AcknowledgedBitrateEstimator>()),
      bwe_(new DelayBasedBwe(nullptr)),
      feedback_observer_(bitrate_controller_.get()),
      clock_(clock),
      send_time_history_(clock_, 10000),
      has_received_ack_(false),
      last_acked_seq_num_(0),
      last_log_time_ms_(0) {
  assert(kbps >= kMinBitrateKbps);
  assert(kbps <= kMaxBitrateKbps);
  bitrate_controller_->SetStartBitrate(1000 * kbps);
  bitrate_controller_->SetMinMaxBitrate(1000 * kMinBitrateKbps,
                                        1000 * kMaxBitrateKbps);
  bwe_->SetMinBitrate(1000 * kMinBitrateKbps);
}

SendSideBweSender::~SendSideBweSender() {}

int SendSideBweSender::GetFeedbackIntervalMs() const {
  return kFeedbackIntervalMs;
}

void SendSideBweSender::GiveFeedback(const FeedbackPacket& feedback) {
  const SendSideBweFeedback& fb =
      static_cast<const SendSideBweFeedback&>(feedback);
  if (fb.packet_feedback_vector().empty())
    return;
  std::vector<PacketFeedback> packet_feedback_vector(
      fb.packet_feedback_vector());
  for (PacketFeedback& packet_feedback : packet_feedback_vector) {
    if (!send_time_history_.GetFeedback(&packet_feedback, true)) {
      int64_t now_ms = clock_->TimeInMilliseconds();
      if (now_ms - last_log_time_ms_ > 5000) {
        RTC_LOG(LS_WARNING) << "Ack arrived too late.";
        last_log_time_ms_ = now_ms;
      }
    }
  }

  int64_t rtt_ms =
      clock_->TimeInMilliseconds() - feedback.latest_send_time_ms();
  bwe_->OnRttUpdate(rtt_ms);
  BWE_TEST_LOGGING_PLOT(1, "RTT", clock_->TimeInMilliseconds(), rtt_ms);

  std::sort(packet_feedback_vector.begin(), packet_feedback_vector.end(),
            PacketFeedbackComparator());
  acknowledged_bitrate_estimator_->IncomingPacketFeedbackVector(
      packet_feedback_vector);
  DelayBasedBwe::Result result = bwe_->IncomingPacketFeedbackVector(
      packet_feedback_vector, acknowledged_bitrate_estimator_->bitrate_bps(),
      clock_->TimeInMilliseconds());
  if (result.updated)
    bitrate_controller_->OnDelayBasedBweResult(result);

  if (has_received_ack_) {
    int expected_packets = fb.packet_feedback_vector().back().sequence_number -
                           last_acked_seq_num_;
    // Assuming no reordering for now.
    if (expected_packets > 0) {
      int lost_packets = expected_packets -
                         static_cast<int>(fb.packet_feedback_vector().size());
      report_block_.fraction_lost = (lost_packets << 8) / expected_packets;
      report_block_.packets_lost += lost_packets;
      uint32_t unwrapped = seq_num_unwrapper_.Unwrap(
          packet_feedback_vector.back().sequence_number);
      report_block_.extended_highest_sequence_number =
          std::max(unwrapped, report_block_.extended_highest_sequence_number);
      ReportBlockList report_blocks;
      report_blocks.push_back(report_block_);
      feedback_observer_->OnReceivedRtcpReceiverReport(
          report_blocks, rtt_ms, clock_->TimeInMilliseconds());
    }
    bitrate_controller_->Process();

    last_acked_seq_num_ = LatestSequenceNumber(
        packet_feedback_vector.back().sequence_number, last_acked_seq_num_);
  } else {
    last_acked_seq_num_ = packet_feedback_vector.back().sequence_number;
    has_received_ack_ = true;
  }
}

void SendSideBweSender::OnPacketsSent(const Packets& packets) {
  for (Packet* packet : packets) {
    if (packet->GetPacketType() == Packet::kMedia) {
      MediaPacket* media_packet = static_cast<MediaPacket*>(packet);
      // TODO(philipel): Add probe_cluster_id to Packet class in order
      //                 to create tests for probing using cluster ids.
      PacketFeedback packet_feedback(
          clock_->TimeInMilliseconds(), media_packet->header().sequenceNumber,
          media_packet->payload_size(), 0, 0, PacedPacketInfo());
      send_time_history_.AddAndRemoveOld(packet_feedback);
      send_time_history_.OnSentPacket(media_packet->header().sequenceNumber,
                                      media_packet->sender_timestamp_ms());
    }
  }
}

void SendSideBweSender::OnReceiveBitrateChanged(
    const std::vector<uint32_t>& ssrcs,
    uint32_t bitrate) {
  feedback_observer_->OnReceivedEstimatedBitrate(bitrate);
}

int64_t SendSideBweSender::TimeUntilNextProcess() {
  return bitrate_controller_->TimeUntilNextProcess();
}

void SendSideBweSender::Process() {
  bitrate_controller_->Process();
}

SendSideBweReceiver::SendSideBweReceiver(int flow_id)
    : BweReceiver(flow_id), last_feedback_ms_(0) {
}

SendSideBweReceiver::~SendSideBweReceiver() {
}

void SendSideBweReceiver::ReceivePacket(int64_t arrival_time_ms,
                                        const MediaPacket& media_packet) {
  packet_feedback_vector_.push_back(
      PacketFeedback(-1, arrival_time_ms, media_packet.sender_timestamp_ms(),
                     media_packet.header().sequenceNumber,
                     media_packet.payload_size(), 0, 0, PacedPacketInfo()));

  // Log received packet information.
  BweReceiver::ReceivePacket(arrival_time_ms, media_packet);
}

FeedbackPacket* SendSideBweReceiver::GetFeedback(int64_t now_ms) {
  if (now_ms - last_feedback_ms_ < kFeedbackIntervalMs)
    return NULL;
  last_feedback_ms_ = now_ms;
  int64_t corrected_send_time_ms =
      packet_feedback_vector_.back().send_time_ms + now_ms -
      packet_feedback_vector_.back().arrival_time_ms;
  FeedbackPacket* fb = new SendSideBweFeedback(
      flow_id_, now_ms * 1000, corrected_send_time_ms, packet_feedback_vector_);
  packet_feedback_vector_.clear();
  return fb;
}

}  // namespace bwe
}  // namespace testing
}  // namespace webrtc
