/*
 *  Copyright 2018 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/scenario/network_node.h"

#include <cstdint>
#include <functional>
#include <memory>
#include <span>
#include <utility>

#include "absl/cleanup/cleanup.h"
#include "api/call/transport.h"
#include "api/sequence_checker.h"
#include "api/test/network_emulation/network_emulation_interfaces.h"
#include "api/units/data_size.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "call/call.h"
#include "rtc_base/checks.h"
#include "rtc_base/copy_on_write_buffer.h"
#include "rtc_base/event.h"
#include "rtc_base/net_helper.h"
#include "rtc_base/net_helpers.h"
#include "rtc_base/network/sent_packet.h"
#include "rtc_base/network_constants.h"
#include "rtc_base/network_route.h"
#include "rtc_base/socket_address.h"
#include "rtc_base/strings/string_builder.h"
#include "rtc_base/synchronization/mutex.h"
#include "system_wrappers/include/clock.h"
#include "test/network/network_emulation.h"
#include "test/network/simulated_network.h"
#include "test/scenario/column_printer.h"
#include "test/scenario/scenario_config.h"

namespace webrtc {
namespace test {
namespace {
constexpr char kDummyTransportName[] = "dummy";
SimulatedNetwork::Config CreateSimulationConfig(
    NetworkSimulationConfig config) {
  SimulatedNetwork::Config sim_config;
  sim_config.link_capacity = config.bandwidth;
  sim_config.loss_percent = config.loss_rate * 100;
  sim_config.queue_delay_ms = config.delay.ms();
  sim_config.delay_standard_deviation_ms = config.delay_std_dev.ms();
  sim_config.packet_overhead = config.packet_overhead.bytes<int>();
  sim_config.queue_length_packets =
      config.packet_queue_length_limit.value_or(0);
  return sim_config;
}

RouteEndpoint CreateRouteEndpoint(uint16_t network_id, uint16_t adapter_id) {
  return RouteEndpoint(ADAPTER_TYPE_UNKNOWN, adapter_id, network_id,
                       /* uses_turn = */ false);
}
}  // namespace

SimulationNode::SimulationNode(NetworkSimulationConfig config,
                               SimulatedNetwork* behavior,
                               EmulatedNetworkNode* network_node)
    : config_(config), simulation_(behavior), network_node_(network_node) {}

std::unique_ptr<SimulatedNetwork> SimulationNode::CreateBehavior(
    NetworkSimulationConfig config) {
  SimulatedNetwork::Config sim_config = CreateSimulationConfig(config);
  return std::make_unique<SimulatedNetwork>(sim_config);
}

void SimulationNode::UpdateConfig(
    std::function<void(NetworkSimulationConfig*)> modifier) {
  modifier(&config_);
  SimulatedNetwork::Config sim_config = CreateSimulationConfig(config_);
  simulation_->SetConfig(sim_config);
}

void SimulationNode::PauseTransmissionUntil(Timestamp until) {
  simulation_->PauseTransmissionUntil(until.us());
}

ColumnPrinter SimulationNode::ConfigPrinter() const {
  return ColumnPrinter::Lambda(
      "propagation_delay capacity loss_rate", [this](SimpleStringBuilder& sb) {
        sb.AppendFormat("%.3lf %.0lf %.2lf", config_.delay.seconds<double>(),
                        config_.bandwidth.bps() / 8.0, config_.loss_rate);
      });
}

NetworkNodeTransport::NetworkNodeTransport(Clock* sender_clock,
                                           Call* sender_call)
    : sender_clock_(sender_clock), sender_call_(sender_call) {
  sequence_checker_.Detach();
}

NetworkNodeTransport::~NetworkNodeTransport() = default;

bool NetworkNodeTransport::SendRtp(std::span<const uint8_t> packet,
                                   const PacketOptions& options) {
  int64_t send_time_ms = sender_clock_->TimeInMilliseconds();
  SentPacketInfo sent_packet;
  sent_packet.packet_id = options.packet_id;
  sent_packet.info.included_in_feedback = options.included_in_feedback;
  sent_packet.info.included_in_allocation = options.included_in_allocation;
  sent_packet.send_time_ms = send_time_ms;
  sent_packet.info.packet_size_bytes = packet.size();
  sent_packet.info.packet_type = PacketType::kData;
  sender_call_->OnSentPacket(sent_packet);

  MutexLock lock(&mutex_);
  if (!endpoint_)
    return false;
  CopyOnWriteBuffer buffer(packet);
  endpoint_->SendPacket(local_address_, remote_address_, buffer,
                        packet_overhead_.bytes());
  return true;
}

bool NetworkNodeTransport::SendRtcp(std::span<const uint8_t> packet,
                                    const PacketOptions& options) {
  CopyOnWriteBuffer buffer(packet);
  MutexLock lock(&mutex_);
  if (!endpoint_)
    return false;
  endpoint_->SendPacket(local_address_, remote_address_, buffer,
                        packet_overhead_.bytes());
  return true;
}

void NetworkNodeTransport::UpdateAdapterId(int adapter_id) {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  adapter_id_ = adapter_id;
}

void NetworkNodeTransport::Connect(EmulatedEndpoint* endpoint,
                                   const SocketAddress& receiver_address,
                                   DataSize packet_overhead) {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  NetworkRoute route;
  route.connected = true;
  // We assume that the address will be unique in the lower bytes.
  route.local = CreateRouteEndpoint(
      static_cast<uint16_t>(
          receiver_address.ipaddr().v4AddressAsHostOrderInteger()),
      adapter_id_);
  route.remote = CreateRouteEndpoint(
      static_cast<uint16_t>(
          receiver_address.ipaddr().v4AddressAsHostOrderInteger()),
      adapter_id_);
  route.packet_overhead = packet_overhead.bytes() +
                          receiver_address.ipaddr().overhead() + kUdpHeaderSize;
  {
    // Only IPv4 address is supported.
    RTC_CHECK_EQ(receiver_address.family(), AF_INET);
    MutexLock lock(&mutex_);
    endpoint_ = endpoint;
    local_address_ = SocketAddress(endpoint_->GetPeerLocalAddress(), 0);
    remote_address_ = receiver_address;
    packet_overhead_ = packet_overhead;
    current_network_route_ = route;
  }

  // Must be called from the worker thread.
  Event event;
  auto cleanup = absl::MakeCleanup([&event] { event.Set(); });
  auto&& task = [this, &route, cleanup = std::move(cleanup)] {
    sender_call_->GetTransportControllerSend()->OnNetworkRouteChanged(
        kDummyTransportName, route);
  };
  if (!sender_call_->worker_thread()->IsCurrent()) {
    sender_call_->worker_thread()->PostTask(std::move(task));
  } else {
    std::move(task)();
  }
  event.Wait(TimeDelta::Seconds(1));
}

void NetworkNodeTransport::Disconnect() {
  MutexLock lock(&mutex_);
  current_network_route_.connected = false;

  sender_call_->GetTransportControllerSend()->OnNetworkRouteChanged(
      kDummyTransportName, current_network_route_);
  current_network_route_ = {};
  endpoint_ = nullptr;
}

}  // namespace test
}  // namespace webrtc
