/*
 *  Copyright (c) 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/scream_network_controller.h"

#include <memory>

#include "api/transport/bandwidth_usage.h"
#include "api/transport/network_control.h"
#include "api/transport/network_types.h"
#include "api/units/data_rate.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h"
#include "modules/congestion_controller/scream/scream_v2.h"
#include "rtc_base/logging.h"
namespace webrtc {

static constexpr DataRate kDefaultStartRate = DataRate::KilobitsPerSec(300);

ScreamNetworkController::ScreamNetworkController(NetworkControllerConfig config)
    : env_(config.env),
      scream_(std::make_unique<ScreamV2>(env_)),
      target_rate_constraints_(config.constraints) {
  if (config.constraints.min_data_rate.has_value() ||
      config.constraints.max_data_rate.has_value()) {
    scream_->SetTargetBitrateConstraints(
        config.constraints.min_data_rate.value_or(DataRate::Zero()),
        config.constraints.max_data_rate.value_or(DataRate::PlusInfinity()));
  }
}

NetworkControlUpdate ScreamNetworkController::OnNetworkAvailability(
    NetworkAvailability msg) {
  RTC_LOG(LS_INFO) << " OnNetworkAvailability network_available:"
                   << msg.network_available;
  if (msg.network_available) {
    // TODO: bugs.webrtc.org/447037083 - rtt must currently be set on every
    // update. But here it is not yet known.
    return CreateUpdate(
        msg.at_time,
        target_rate_constraints_.starting_rate.value_or(kDefaultStartRate),
        /*rtt*/ TimeDelta::Zero());
  }
  return NetworkControlUpdate();
}

NetworkControlUpdate ScreamNetworkController::OnNetworkRouteChange(
    NetworkRouteChange msg) {
  RTC_LOG(LS_INFO) << " OnNetworkRouteChange, resetting ScreamV2.";
  target_rate_constraints_ = msg.constraints;
  scream_ = std::make_unique<ScreamV2>(env_);
  // TODO: bugs.webrtc.org/447037083 - We should use the minimum rate from
  // constraints, REMB and remote network state estimates.
  scream_->SetTargetBitrateConstraints(
      target_rate_constraints_.min_data_rate.value_or(DataRate::Zero()),
      target_rate_constraints_.max_data_rate.value_or(
          DataRate::PlusInfinity()));
  // TODO: bugs.webrtc.org/447037083 - rtt must currently be set on every
  // update. But here it is not yet known.
  return CreateUpdate(
      msg.at_time,
      target_rate_constraints_.starting_rate.value_or(kDefaultStartRate),
      /*rtt*/ TimeDelta::Zero());
}

NetworkControlUpdate ScreamNetworkController::OnProcessInterval(
    ProcessInterval msg) {
  // Scream currently has no need for periodic processing.
  return NetworkControlUpdate();
}

NetworkControlUpdate ScreamNetworkController::OnRemoteBitrateReport(
    RemoteBitrateReport msg) {
  // TODO: bugs.webrtc.org/447037083 - Implement;
  return NetworkControlUpdate();
}

NetworkControlUpdate ScreamNetworkController::OnRoundTripTimeUpdate(
    RoundTripTimeUpdate msg) {
  // Scream uses Smoothed RTT from TransportFeedback.
  return NetworkControlUpdate();
}

NetworkControlUpdate ScreamNetworkController::OnSentPacket(SentPacket msg) {
  // Scream does not have to know about sent packets.
  return NetworkControlUpdate();
}

NetworkControlUpdate ScreamNetworkController::OnReceivedPacket(
    ReceivedPacket msg) {
  // Scream does not have to know about received packets.
  return NetworkControlUpdate();
}

NetworkControlUpdate ScreamNetworkController::OnStreamsConfig(
    StreamsConfig msg) {
  // TODO: bugs.webrtc.org/447037083 - Implement;
  RTC_LOG_F(LS_INFO) << "Not implemented";
  return NetworkControlUpdate();
}

NetworkControlUpdate ScreamNetworkController::OnTargetRateConstraints(
    TargetRateConstraints msg) {
  target_rate_constraints_ = msg;

  // TODO: bugs.webrtc.org/447037083 - We should use the minimum rate from
  // constraints, REMB and remote network state estimates.
  scream_->SetTargetBitrateConstraints(
      target_rate_constraints_.min_data_rate.value_or(DataRate::Zero()),
      target_rate_constraints_.max_data_rate.value_or(
          DataRate::PlusInfinity()));
  // No need to change target rate immediately. Wait until next feedback.
  return NetworkControlUpdate();
}

NetworkControlUpdate ScreamNetworkController::OnTransportLossReport(
    TransportLossReport msg) {
  return NetworkControlUpdate();
}

NetworkControlUpdate ScreamNetworkController::OnNetworkStateEstimate(
    NetworkStateEstimate msg) {
  // TODO: bugs.webrtc.org/447037083 - Implement;
  RTC_LOG_F(LS_INFO) << "Not implemented";
  return NetworkControlUpdate();
}

NetworkControlUpdate ScreamNetworkController::OnTransportPacketsFeedback(
    TransportPacketsFeedback msg) {
  DataRate target_rate = scream_->OnTransportPacketsFeedback(msg);

  // TODO: bugs.webrtc.org/447037083 - Should we add separate event for Scream?
  env_.event_log().Log(std::make_unique<RtcEventBweUpdateDelayBased>(
      target_rate.bps(), BandwidthUsage::kBwNormal));
  return CreateUpdate(msg.feedback_time, target_rate, msg.smoothed_rtt);
}

NetworkControlUpdate ScreamNetworkController::CreateUpdate(Timestamp now,
                                                           DataRate target_rate,
                                                           TimeDelta rtt) {
  TargetTransferRate target_rate_msg;
  target_rate_msg.at_time = now;
  target_rate_msg.target_rate = target_rate;

  target_rate_msg.network_estimate.at_time = now;
  target_rate_msg.network_estimate.round_trip_time = rtt;
  // TODO: bugs.webrtc.org/447037083 - bwe_period must currently be set but
  // it seems like it is not used for anything sensible. Try to remove it.
  target_rate_msg.network_estimate.bwe_period = TimeDelta::Millis(25);

  NetworkControlUpdate update;
  update.target_rate = target_rate_msg;
  update.pacer_config = GetPacerConfig(target_rate);

  return update;
}

PacerConfig ScreamNetworkController::GetPacerConfig(
    DataRate target_rate) const {
  const double kPacingRateFactor = 1.5;
  // TODO: bugs.webrtc.org/447037083 - Currently, pacer will allow sending
  // bursts of packets with a total size up to 40ms * pacing rate.
  return {
      .data_window = kPacingRateFactor * target_rate * TimeDelta::Seconds(1),
      .time_window = TimeDelta::Seconds(1),
  };
}

}  // namespace webrtc
