/*
 *  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 "p2p/base/packet_loss_estimator.h"

#include "rtc_base/checks.h"

namespace cricket {

PacketLossEstimator::PacketLossEstimator(int64_t consider_lost_after_ms,
                                         int64_t forget_after_ms)
    : consider_lost_after_ms_(consider_lost_after_ms),
      forget_after_ms_(forget_after_ms) {
  RTC_DCHECK_LT(consider_lost_after_ms, forget_after_ms);
}

PacketLossEstimator::~PacketLossEstimator() = default;

void PacketLossEstimator::ExpectResponse(std::string id, int64_t sent_time) {
  tracked_packets_[id] = PacketInfo{sent_time, false};

  // Called to free memory in case the client hasn't called UpdateResponseRate
  // in a while.
  MaybeForgetOldRequests(sent_time);
}

void PacketLossEstimator::ReceivedResponse(std::string id,
                                           int64_t received_time) {
  auto iter = tracked_packets_.find(id);
  if (iter != tracked_packets_.end()) {
    auto& packet_info = iter->second;
    packet_info.response_received = true;
  }

  // Called to free memory in case the client hasn't called UpdateResponseRate
  // in a while.
  MaybeForgetOldRequests(received_time);
}

void PacketLossEstimator::UpdateResponseRate(int64_t now) {
  int responses_expected = 0;
  int responses_received = 0;

  for (auto iter = tracked_packets_.begin(); iter != tracked_packets_.end();) {
    const auto& packet_info = iter->second;
    if (Forget(packet_info, now)) {
      iter = tracked_packets_.erase(iter);
      continue;
    }
    if (packet_info.response_received) {
      responses_expected += 1;
      responses_received += 1;
    } else if (ConsiderLost(packet_info, now)) {
      responses_expected += 1;
    }
    ++iter;
  }

  if (responses_expected > 0) {
    response_rate_ =
        static_cast<double>(responses_received) / responses_expected;
  } else {
    response_rate_ = 1.0;
  }

  last_forgot_at_ = now;
}

void PacketLossEstimator::MaybeForgetOldRequests(int64_t now) {
  if (now - last_forgot_at_ <= forget_after_ms_) {
    return;
  }

  for (auto iter = tracked_packets_.begin(); iter != tracked_packets_.end();) {
    const auto& packet_info = iter->second;
    if (Forget(packet_info, now)) {
      iter = tracked_packets_.erase(iter);
    } else {
      ++iter;
    }
  }

  last_forgot_at_ = now;
}

bool PacketLossEstimator::ConsiderLost(const PacketInfo& packet_info,
                                       int64_t now) const {
  return packet_info.sent_time < now - consider_lost_after_ms_;
}

bool PacketLossEstimator::Forget(const PacketInfo& packet_info,
                                 int64_t now) const {
  return now - packet_info.sent_time > forget_after_ms_;
}

std::size_t PacketLossEstimator::tracked_packet_count_for_testing() const {
  return tracked_packets_.size();
}

}  // namespace cricket
