// Copyright 2019 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 "quic/core/congestion_control/uber_loss_algorithm.h"

#include <algorithm>

#include "quic/core/crypto/crypto_protocol.h"
#include "quic/platform/api/quic_bug_tracker.h"

namespace quic {

UberLossAlgorithm::UberLossAlgorithm() {
  for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
    general_loss_algorithms_[i].Initialize(static_cast<PacketNumberSpace>(i),
                                           this);
  }
}

void UberLossAlgorithm::SetFromConfig(const QuicConfig& config,
                                      Perspective perspective) {
  if (config.HasClientRequestedIndependentOption(kELDT, perspective) &&
      tuner_ != nullptr) {
    tuning_configured_ = true;
    MaybeStartTuning();
  }
}

LossDetectionInterface::DetectionStats UberLossAlgorithm::DetectLosses(
    const QuicUnackedPacketMap& unacked_packets,
    QuicTime time,
    const RttStats& rtt_stats,
    QuicPacketNumber /*largest_newly_acked*/,
    const AckedPacketVector& packets_acked,
    LostPacketVector* packets_lost) {
  DetectionStats overall_stats;

  for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
    const QuicPacketNumber largest_acked =
        unacked_packets.GetLargestAckedOfPacketNumberSpace(
            static_cast<PacketNumberSpace>(i));
    if (!largest_acked.IsInitialized() ||
        unacked_packets.GetLeastUnacked() > largest_acked) {
      // Skip detecting losses if no packet has been received for this packet
      // number space or the least_unacked is greater than largest_acked.
      continue;
    }

    DetectionStats stats = general_loss_algorithms_[i].DetectLosses(
        unacked_packets, time, rtt_stats, largest_acked, packets_acked,
        packets_lost);

    overall_stats.sent_packets_max_sequence_reordering =
        std::max(overall_stats.sent_packets_max_sequence_reordering,
                 stats.sent_packets_max_sequence_reordering);
    overall_stats.sent_packets_num_borderline_time_reorderings +=
        stats.sent_packets_num_borderline_time_reorderings;
    overall_stats.total_loss_detection_response_time +=
        stats.total_loss_detection_response_time;
  }

  return overall_stats;
}

QuicTime UberLossAlgorithm::GetLossTimeout() const {
  QuicTime loss_timeout = QuicTime::Zero();
  // Returns the earliest non-zero loss timeout.
  for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
    const QuicTime timeout = general_loss_algorithms_[i].GetLossTimeout();
    if (!loss_timeout.IsInitialized()) {
      loss_timeout = timeout;
      continue;
    }
    if (timeout.IsInitialized()) {
      loss_timeout = std::min(loss_timeout, timeout);
    }
  }
  return loss_timeout;
}

void UberLossAlgorithm::SpuriousLossDetected(
    const QuicUnackedPacketMap& unacked_packets,
    const RttStats& rtt_stats,
    QuicTime ack_receive_time,
    QuicPacketNumber packet_number,
    QuicPacketNumber previous_largest_acked) {
  general_loss_algorithms_[unacked_packets.GetPacketNumberSpace(packet_number)]
      .SpuriousLossDetected(unacked_packets, rtt_stats, ack_receive_time,
                            packet_number, previous_largest_acked);
}

void UberLossAlgorithm::SetLossDetectionTuner(
    std::unique_ptr<LossDetectionTunerInterface> tuner) {
  if (tuner_ != nullptr) {
    QUIC_BUG(quic_bug_10469_1)
        << "LossDetectionTuner can only be set once when session begins.";
    return;
  }
  tuner_ = std::move(tuner);
}

void UberLossAlgorithm::MaybeStartTuning() {
  if (tuner_started_ || !tuning_configured_ || !min_rtt_available_ ||
      !user_agent_known_ || !reorder_happened_) {
    return;
  }

  tuner_started_ = tuner_->Start(&tuned_parameters_);
  if (!tuner_started_) {
    return;
  }

  if (tuned_parameters_.reordering_shift.has_value() &&
      tuned_parameters_.reordering_threshold.has_value()) {
    QUIC_DLOG(INFO) << "Setting reordering shift to "
                    << *tuned_parameters_.reordering_shift
                    << ", and reordering threshold to "
                    << *tuned_parameters_.reordering_threshold;
    SetReorderingShift(*tuned_parameters_.reordering_shift);
    SetReorderingThreshold(*tuned_parameters_.reordering_threshold);
  } else {
    QUIC_BUG(quic_bug_10469_2)
        << "Tuner started but some parameters are missing";
  }
}

void UberLossAlgorithm::OnConfigNegotiated() {}

void UberLossAlgorithm::OnMinRttAvailable() {
  min_rtt_available_ = true;
  MaybeStartTuning();
}

void UberLossAlgorithm::OnUserAgentIdKnown() {
  user_agent_known_ = true;
  MaybeStartTuning();
}

void UberLossAlgorithm::OnConnectionClosed() {
  if (tuner_ != nullptr && tuner_started_) {
    tuner_->Finish(tuned_parameters_);
  }
}

void UberLossAlgorithm::OnReorderingDetected() {
  const bool tuner_started_before = tuner_started_;
  const bool reorder_happened_before = reorder_happened_;

  reorder_happened_ = true;
  MaybeStartTuning();

  if (!tuner_started_before && tuner_started_) {
    if (reorder_happened_before) {
      QUIC_CODE_COUNT(quic_loss_tuner_started_after_first_reorder);
    } else {
      QUIC_CODE_COUNT(quic_loss_tuner_started_on_first_reorder);
    }
  }
}

void UberLossAlgorithm::SetReorderingShift(int reordering_shift) {
  for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
    general_loss_algorithms_[i].set_reordering_shift(reordering_shift);
  }
}

void UberLossAlgorithm::SetReorderingThreshold(
    QuicPacketCount reordering_threshold) {
  for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
    general_loss_algorithms_[i].set_reordering_threshold(reordering_threshold);
  }
}

void UberLossAlgorithm::EnableAdaptiveReorderingThreshold() {
  for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
    general_loss_algorithms_[i].set_use_adaptive_reordering_threshold(true);
  }
}

void UberLossAlgorithm::DisableAdaptiveReorderingThreshold() {
  for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
    general_loss_algorithms_[i].set_use_adaptive_reordering_threshold(false);
  }
}

void UberLossAlgorithm::EnableAdaptiveTimeThreshold() {
  for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
    general_loss_algorithms_[i].enable_adaptive_time_threshold();
  }
}

QuicPacketCount UberLossAlgorithm::GetPacketReorderingThreshold() const {
  return general_loss_algorithms_[APPLICATION_DATA].reordering_threshold();
}

int UberLossAlgorithm::GetPacketReorderingShift() const {
  return general_loss_algorithms_[APPLICATION_DATA].reordering_shift();
}

void UberLossAlgorithm::DisablePacketThresholdForRuntPackets() {
  for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
    general_loss_algorithms_[i].disable_packet_threshold_for_runt_packets();
  }
}

void UberLossAlgorithm::ResetLossDetection(PacketNumberSpace space) {
  if (space >= NUM_PACKET_NUMBER_SPACES) {
    QUIC_BUG(quic_bug_10469_3) << "Invalid packet number space: " << space;
    return;
  }
  general_loss_algorithms_[space].Reset();
}

}  // namespace quic
