/*
 *  Copyright 2025 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/congestion_controller/scream/delay_based_congestion_control.h"

#include <algorithm>
#include <vector>

#include "api/transport/network_types.h"
#include "api/units/data_rate.h"
#include "api/units/data_size.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "modules/congestion_controller/scream/scream_v2_parameters.h"
#include "rtc_base/checks.h"

namespace webrtc {

DelayBasedCongestionControl::DelayBasedCongestionControl(
    ScreamV2Parameters params)
    : params_(params),
      base_delay_history_(params_.base_delay_window_length.Get()) {
  ResetQueueDelay();
}

void DelayBasedCongestionControl::OnTransportPacketsFeedback(
    const TransportPacketsFeedback& msg) {
  if (msg.PacketsWithFeedback().empty()) {
    return;
  }
  std::vector<PacketResult> received_packets = msg.SortedByReceiveTime();
  if (received_packets.empty()) {
    return;
  }

  TimeDelta min_one_way_delay = TimeDelta::PlusInfinity();
  TimeDelta max_one_way_delay = TimeDelta::Zero();

  for (const PacketResult& packet : received_packets) {
    TimeDelta one_way_delay =
        packet.receive_time - packet.sent_packet.send_time;
    next_base_delay_ = std::min(next_base_delay_, one_way_delay);
    min_one_way_delay = std::min(min_one_way_delay, one_way_delay);
    max_one_way_delay = std::max(max_one_way_delay, one_way_delay);
  }
  // `arrival_time_offset` is null if TWCC is used. We assume feedback was sent
  // when the last sent packet was received.
  TimeDelta rtt_sample = std::max(
      msg.feedback_time - received_packets.back().sent_packet.send_time -
          received_packets.back().arrival_time_offset.value_or(
              TimeDelta::Zero()),
      TimeDelta::Zero());
  UpdateSmoothedRtt(rtt_sample);

  TimeDelta min_queue_delay = min_one_way_delay - min_base_delay();
  if (min_queue_delay > params_.queue_delay_drain_threshold.Get()) {
    if (min_queue_delay_above_threshold_start_.IsInfinite()) {
      min_queue_delay_above_threshold_start_ = msg.feedback_time;
    }
  } else {
    min_queue_delay_above_threshold_start_ = Timestamp::MinusInfinity();
  }
  UpdateQueueDelayAverage(std::min(min_queue_delay, last_queue_delay_sample_));
  last_queue_delay_sample_ = min_queue_delay;
  UpdateQueueDelayMinAverage(min_queue_delay);
  UpdateLatencyDifferenceAverage(min_one_way_delay.IsFinite()
                                     ? max_one_way_delay - min_one_way_delay
                                     : TimeDelta::Zero());

  if (msg.feedback_time - last_base_delay_update_ >=
      params_.base_delay_history_update_interval.Get()) {
    base_delay_history_.Insert(next_base_delay_);
    last_base_delay_update_ = msg.feedback_time;
    next_base_delay_ = TimeDelta::PlusInfinity();
  }
}

void DelayBasedCongestionControl::UpdateQueueDelayAverage(
    TimeDelta min_qdelay_in_feedback) {
  // `queue_delay_avg_` is updated with a slow attack,fast decay EWMA
  // filter.
  if (min_qdelay_in_feedback < queue_delay_avg_) {
    queue_delay_avg_ = min_qdelay_in_feedback;
  } else {
    queue_delay_avg_ =
        params_.queue_delay_avg_g.Get() * min_qdelay_in_feedback +
        (1.0 - params_.queue_delay_avg_g.Get()) * queue_delay_avg_;
  }
}

void DelayBasedCongestionControl::UpdateQueueDelayMinAverage(
    TimeDelta packet_qdelay) {
  RTC_DCHECK(packet_qdelay >= TimeDelta::Zero());
  queue_delay_min_avg_ =
      (1.0 - params_.delay_min_and_latency_diff_avg_g.Get()) *
          queue_delay_min_avg_ +
      params_.delay_min_and_latency_diff_avg_g.Get() *
          std::min(packet_qdelay, 2 * params_.queue_delay_min_threshold.Get());
}

void DelayBasedCongestionControl::UpdateLatencyDifferenceAverage(
    TimeDelta packet_latency_diff) {
  RTC_DCHECK(packet_latency_diff >= TimeDelta::Zero());
  latency_difference_avg_ =
      (1.0 - params_.delay_min_and_latency_diff_avg_g.Get()) *
          latency_difference_avg_ +
      params_.delay_min_and_latency_diff_avg_g.Get() *
          std::min(packet_latency_diff,
                   2 * params_.latency_diff_threshold.Get());
}

void DelayBasedCongestionControl::UpdateSmoothedRtt(TimeDelta rtt_sample) {
  RTC_DCHECK(rtt_sample >= TimeDelta::Zero());
  if (last_smoothed_rtt_.IsZero()) {
    last_smoothed_rtt_ = rtt_sample;
  } else {
    double g = params_.smoothed_rtt_avg_g_up.Get();
    if (rtt_sample < last_smoothed_rtt_) {
      g = params_.smoothed_rtt_avg_g_down.Get();
    }
    last_smoothed_rtt_ = rtt_sample * g + last_smoothed_rtt_ * (1.0 - g);
  }
}

void DelayBasedCongestionControl::ResetQueueDelay() {
  last_base_delay_update_ = Timestamp::MinusInfinity();
  next_base_delay_ = TimeDelta::PlusInfinity();
  base_delay_history_.Reset();
  // Insert a start value to ensure GetMin returns a sensible value when empty.
  base_delay_history_.Insert(TimeDelta::PlusInfinity());

  min_queue_delay_above_threshold_start_ = Timestamp::MinusInfinity();
  last_update_qdelay_avg_time_ = Timestamp::MinusInfinity();
  queue_delay_avg_ = TimeDelta::PlusInfinity();
  queue_delay_min_avg_ = TimeDelta::Zero();
  latency_difference_avg_ = TimeDelta::Zero();
}

double
DelayBasedCongestionControl::ref_window_scale_factor_due_to_avg_min_delay(
    bool allow_zero) const {
  TimeDelta norm = params_.queue_delay_min_threshold.Get();
  // Reaches 0.1 at norm, and 1.0 at norm / 4
  return std::clamp(0.1 + 1.2 * (norm - queue_delay_min_avg_) / norm,
                    allow_zero ? 0.0 : 0.1, 1.0);
}

double
DelayBasedCongestionControl::ref_window_scale_factor_due_to_latency_difference()
    const {
  TimeDelta norm = params_.latency_diff_threshold.Get();
  // Reaches 0.1 at norm, and 1.0 at norm / 4
  return std::clamp(0.1 + 1.2 * (norm - latency_difference_avg_) / norm, 0.1,
                    1.0);
}

DataSize DelayBasedCongestionControl::UpdateReferenceWindow(
    DataSize ref_window,
    double ref_window_mss_ratio) const {
  // `min_delay_based_bwe_`put a lower bound on the reference window.
  DataSize min_allowed_reference_window =
      min_delay_based_bwe_ * last_smoothed_rtt_;

  if (ref_window < min_allowed_reference_window) {
    return min_allowed_reference_window;
  }

  double backoff = l4s_alpha_v() / 2.0;  // Reduce by 50% if l4s_alpha_v = 1.0;
  backoff /= std::max(1.0, last_smoothed_rtt_ / params_.virtual_rtt);
  return std::max(min_allowed_reference_window, (1 - backoff) * ref_window);
}

double DelayBasedCongestionControl::l4s_alpha_v() const {
  // 4.2.2.1
  double l4s_alpha_v =
      (queue_delay_avg_ - params_.queue_delay_target.Get() / 2) /
      (params_.queue_delay_target.Get() / 2);
  return std::clamp(l4s_alpha_v, 0.0, 1.0);
}

}  // namespace webrtc
