// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

#include "net/quic/congestion_control/quic_send_scheduler.h"

#include <algorithm>
#include <cmath>
#include <map>

#include "base/stl_util.h"
#include "base/time.h"
#include "net/quic/congestion_control/send_algorithm_interface.h"
//#include "util/gtl/map-util.h"

using std::map;
using std::max;

namespace net {

const int64 kNumMicrosPerSecond = base::Time::kMicrosecondsPerSecond;

QuicSendScheduler::QuicSendScheduler(
    const QuicClock* clock,
    CongestionFeedbackType type)
    : clock_(clock),
      current_estimated_bandwidth_(-1),
      max_estimated_bandwidth_(-1),
      last_sent_packet_(QuicTime::FromMicroseconds(0)),
      current_packet_bucket_(-1),
      first_packet_bucket_(-1),
      send_algorithm_(SendAlgorithmInterface::Create(clock, type)) {
  memset(packet_history_, 0, sizeof(packet_history_));
}

QuicSendScheduler::~QuicSendScheduler() {
  STLDeleteContainerPairSecondPointers(pending_packets_.begin(),
                                       pending_packets_.end());
}

int QuicSendScheduler::UpdatePacketHistory() {
  int timestamp_scaled = clock_->Now().ToMicroseconds() /
      kBitrateSmoothingPeriod;
  int bucket = timestamp_scaled % kBitrateSmoothingBuckets;
  if (!HasSentPacket()) {
    // First packet.
    current_packet_bucket_ = bucket;
    first_packet_bucket_ = bucket;
  }
  if (current_packet_bucket_ != bucket) {
    // We need to make sure to zero out any skipped buckets.
    // Max loop count is kBitrateSmoothingBuckets.
    do {
      current_packet_bucket_ =
          (1 + current_packet_bucket_) % kBitrateSmoothingBuckets;
      packet_history_[current_packet_bucket_] = 0;
      if (first_packet_bucket_ == current_packet_bucket_) {
        // We have filled the whole window, no need to keep track of first
        // bucket.
        first_packet_bucket_ = -1;
      }
    }  while (current_packet_bucket_ != bucket);
  }
  return bucket;
}

void QuicSendScheduler::SentPacket(QuicPacketSequenceNumber sequence_number,
                                   size_t bytes,
                                   bool retransmit) {
  int bucket = UpdatePacketHistory();
  packet_history_[bucket] += bytes;
  send_algorithm_->SentPacket(sequence_number, bytes, retransmit);
  if (!retransmit) {
    pending_packets_[sequence_number] =
        new PendingPacket(bytes, clock_->Now());
  }
  DVLOG(1) << "Sent sequence number:" << sequence_number;
}

void QuicSendScheduler::OnIncomingQuicCongestionFeedbackFrame(
    const QuicCongestionFeedbackFrame& congestion_feedback_frame) {
  send_algorithm_->OnIncomingQuicCongestionFeedbackFrame(
      congestion_feedback_frame);
  }

void QuicSendScheduler::OnIncomingAckFrame(const QuicAckFrame& ack_frame) {
  // We want to.
  // * Get all packets lower(including) than largest_received
  //   from pending_packets_.
  // * Remove all missing packets.
  // * Send each ACK in the list to send_algorithm_.
  QuicTime last_timestamp(QuicTime::FromMicroseconds(0));
  map<QuicPacketSequenceNumber, size_t> acked_packets;

  PendingPacketsMap::iterator it, it_upper;
  it = pending_packets_.begin();
  it_upper = pending_packets_.upper_bound(
      ack_frame.received_info.largest_received);

  while (it != it_upper) {
    QuicPacketSequenceNumber sequence_number = it->first;
    if (!ack_frame.received_info.IsAwaitingPacket(sequence_number)) {
      // Not missing, hence implicitly acked.
      scoped_ptr<PendingPacket> pending_packet_cleaner(it->second);
      acked_packets[sequence_number] = pending_packet_cleaner->BytesSent();
      last_timestamp = pending_packet_cleaner->SendTimestamp();
      pending_packets_.erase(it++);  // Must be incremented post to work.
    } else {
      ++it;
    }
  }
  // We calculate the RTT based on the highest ACKed sequence number, the lower
  // sequence numbers will include the ACK aggregation delay.
  QuicTime::Delta rtt = clock_->Now().Subtract(last_timestamp);

  map<QuicPacketSequenceNumber, size_t>::iterator it_acked_packets;
  for (it_acked_packets = acked_packets.begin();
      it_acked_packets != acked_packets.end();
      ++it_acked_packets) {
    send_algorithm_->OnIncomingAck(it_acked_packets->first,
                                   it_acked_packets->second,
                                   rtt);
    DVLOG(1) << "ACKed sequence number:" << it_acked_packets->first;
  }
}

QuicTime::Delta QuicSendScheduler::TimeUntilSend(bool retransmit) {
  return send_algorithm_->TimeUntilSend(retransmit);
}

size_t QuicSendScheduler::AvailableCongestionWindow() {
  return send_algorithm_->AvailableCongestionWindow();
}

int QuicSendScheduler::BandwidthEstimate() {
  int bandwidth_estimate = send_algorithm_->BandwidthEstimate();
  if (bandwidth_estimate == kNoValidEstimate) {
    // If we don't have a valid estimate use the send rate.
    return SentBandwidth();
  }
  return bandwidth_estimate;
}

bool QuicSendScheduler::HasSentPacket() {
  return (current_packet_bucket_ != -1);
}

// TODO(pwestin) add a timer to make this accurate even if not called.
int QuicSendScheduler::SentBandwidth() {
  UpdatePacketHistory();

  if (first_packet_bucket_ != -1) {
    // We don't have a full set of data.
    int number_of_buckets = (current_packet_bucket_ - first_packet_bucket_) + 1;
    if (number_of_buckets < 0) {
      // We have a wrap in bucket index.
      number_of_buckets = kBitrateSmoothingBuckets + number_of_buckets;
    }
    int64 sum = 0;
    int bucket = first_packet_bucket_;
    for (int n = 0; n < number_of_buckets; bucket++, n++) {
      bucket = bucket % kBitrateSmoothingBuckets;
      sum += packet_history_[bucket];
    }
    current_estimated_bandwidth_ = (sum *
        (kNumMicrosPerSecond / kBitrateSmoothingPeriod)) / number_of_buckets;
  } else {
    int64 sum = 0;
    for (uint32 bucket = 0; bucket < kBitrateSmoothingBuckets; ++bucket) {
      sum += packet_history_[bucket];
    }
    current_estimated_bandwidth_ = (sum * (kNumMicrosPerSecond /
        kBitrateSmoothingPeriod)) / kBitrateSmoothingBuckets;
  }
  max_estimated_bandwidth_ = max(max_estimated_bandwidth_,
                                 current_estimated_bandwidth_);
  return current_estimated_bandwidth_;
}

int QuicSendScheduler::PeakSustainedBandwidth() {
  // To make sure that we get the latest estimate we call SentBandwidth.
  if (HasSentPacket()) {
    SentBandwidth();
  }
  return max_estimated_bandwidth_;
}

}  // namespace net
