/*
 *  Copyright (c) 2024 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 "test/network/schedulable_network_behavior.h"

#include <algorithm>
#include <cstdint>
#include <memory>
#include <utility>

#include "absl/functional/any_invocable.h"
#include "api/sequence_checker.h"
#include "api/task_queue/task_queue_base.h"
#include "api/test/network_emulation/network_config_schedule.pb.h"
#include "api/test/network_emulation/network_queue.h"
#include "api/test/simulated_network.h"
#include "api/units/data_rate.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "rtc_base/checks.h"
#include "rtc_base/task_utils/repeating_task.h"
#include "system_wrappers/include/clock.h"
#include "test/network/simulated_network.h"

namespace webrtc {

namespace {


void UpdateConfigFromSchedule(
    const network_behaviour::NetworkConfigScheduleItem& schedule_item,
    BuiltInNetworkBehaviorConfig& config) {
  if (schedule_item.has_queue_length_packets()) {
    config.queue_length_packets = schedule_item.queue_length_packets();
  }
  if (schedule_item.has_queue_delay_ms()) {
    config.queue_delay_ms = schedule_item.queue_delay_ms();
  }
  if (schedule_item.has_link_capacity_kbps()) {
    config.link_capacity =
        DataRate::KilobitsPerSec(schedule_item.link_capacity_kbps());
  }
  if (schedule_item.has_loss_percent()) {
    config.loss_percent = schedule_item.loss_percent();
  }
  if (schedule_item.has_delay_standard_deviation_ms()) {
    config.delay_standard_deviation_ms =
        schedule_item.delay_standard_deviation_ms();
  }
  if (schedule_item.has_allow_reordering()) {
    config.allow_reordering = schedule_item.allow_reordering();
  }
  if (schedule_item.has_avg_burst_loss_length()) {
    config.avg_burst_loss_length = schedule_item.avg_burst_loss_length();
  }
  if (schedule_item.has_packet_overhead()) {
    config.packet_overhead = schedule_item.packet_overhead();
  }
}

BuiltInNetworkBehaviorConfig GetInitialConfig(
    const network_behaviour::NetworkConfigSchedule& schedule) {
  BuiltInNetworkBehaviorConfig config;
  if (!schedule.item().empty()) {
    UpdateConfigFromSchedule(schedule.item(0), config);
  }
  return config;
}

}  // namespace

SchedulableNetworkBehavior::SchedulableNetworkBehavior(
    network_behaviour::NetworkConfigSchedule schedule,
    uint64_t random_seed,
    Clock& clock,
    absl::AnyInvocable<bool(Timestamp)> start_condition,
    std::unique_ptr<NetworkQueue> queue)
    : SimulatedNetwork(GetInitialConfig(schedule),
                       random_seed,
                       std::move(queue)),
      schedule_(std::move(schedule)),
      start_condition_(std::move(start_condition)),
      clock_(clock),
      config_(GetInitialConfig(schedule_)) {
  if (schedule_.item().size() > 1) {
    next_schedule_index_ = 1;
  }
  sequence_checker_.Detach();
}

bool SchedulableNetworkBehavior::EnqueuePacket(PacketInFlightInfo packet_info) {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  if (first_send_time_.IsInfinite() &&
      start_condition_(Timestamp::Micros(packet_info.send_time_us))) {
    first_send_time_ = Timestamp::Micros(packet_info.send_time_us);
    if (schedule_.item().size() > 1) {
      RTC_CHECK_LT(next_schedule_index_, schedule_.item().size());
      TimeDelta delay =
          TimeDelta::Millis(schedule_.item()[next_schedule_index_]
                                .time_since_first_sent_packet_ms());
      schedule_task_ = RepeatingTaskHandle::DelayedStart(
          TaskQueueBase::Current(), delay,
          [this] { return UpdateConfigAndReschedule(); });
    }
  }
  return SimulatedNetwork::EnqueuePacket(packet_info);
}

TimeDelta SchedulableNetworkBehavior::UpdateConfigAndReschedule() {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  Timestamp reschedule_time = clock_.CurrentTime();
  RTC_CHECK_LT(next_schedule_index_, schedule_.item().size());

  auto next_config = schedule_.item()[next_schedule_index_];
  UpdateConfigFromSchedule(next_config, config_);
  SimulatedNetwork::SetConfig(config_, reschedule_time);
  next_schedule_index_ = ++next_schedule_index_ % schedule_.item().size();
  TimeDelta delay = TimeDelta::Zero();
  TimeDelta time_since_first_sent_packet = reschedule_time - first_send_time_;
  if (next_schedule_index_ != 0) {
    delay = std::max(TimeDelta::Millis(schedule_.item()[next_schedule_index_]
                                           .time_since_first_sent_packet_ms()) -
                         (time_since_first_sent_packet - wrap_time_delta_),
                     TimeDelta::Zero());
  } else if (!schedule_.has_repeat_schedule_after_last_ms()) {
    // No more schedule items.
    schedule_task_.Stop();
    return TimeDelta::Zero();  // This is ignored.
  } else {
    // Wrap around to the first schedule item.
    wrap_time_delta_ +=
        TimeDelta::Millis(schedule_.repeat_schedule_after_last_ms()) +
        TimeDelta::Millis(schedule_.item()[schedule_.item().size() - 1]
                              .time_since_first_sent_packet_ms());
    delay = TimeDelta::Millis(schedule_.repeat_schedule_after_last_ms());
    RTC_DCHECK_GE(delay, TimeDelta::Zero());
  }

  return delay;
}

}  // namespace webrtc
