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

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

#include "absl/types/optional.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_minmax.h"

namespace webrtc {
namespace test {
namespace {

class NullReceiver : public EmulatedNetworkReceiverInterface {
 public:
  void OnPacketReceived(EmulatedIpPacket packet) override {}
};

class ActionReceiver : public EmulatedNetworkReceiverInterface {
 public:
  ActionReceiver(std::function<void()> action, EmulatedEndpoint* endpoint)
      : action_(action), endpoint_(endpoint) {}
  ~ActionReceiver() override = default;

  void OnPacketReceived(EmulatedIpPacket packet) override {
    RTC_DCHECK(port_);
    action_();
    endpoint_->UnbindReceiver(port_.value());
  }

  // We can't set port in constructor, because port will be provided by
  // endpoint, when this receiver will be binded to that endpoint.
  void SetPort(uint16_t port) { port_ = port; }

 private:
  std::function<void()> action_;
  // Endpoint and port will be used to free port in the endpoint after action
  // will be done.
  EmulatedEndpoint* endpoint_;
  absl::optional<uint16_t> port_ = absl::nullopt;
};

}  // namespace

CrossTrafficRouteImpl::CrossTrafficRouteImpl(
    Clock* clock,
    EmulatedNetworkReceiverInterface* receiver,
    EmulatedEndpoint* endpoint)
    : clock_(clock), receiver_(receiver), endpoint_(endpoint) {
  null_receiver_ = std::make_unique<NullReceiver>();
  absl::optional<uint16_t> port =
      endpoint_->BindReceiver(0, null_receiver_.get());
  RTC_DCHECK(port);
  null_receiver_port_ = port.value();
}
CrossTrafficRouteImpl::~CrossTrafficRouteImpl() = default;

void CrossTrafficRouteImpl::TriggerPacketBurst(size_t num_packets,
                                               size_t packet_size) {
  for (size_t i = 0; i < num_packets; ++i) {
    SendPacket(packet_size);
  }
}

void CrossTrafficRouteImpl::NetworkDelayedAction(size_t packet_size,
                                                 std::function<void()> action) {
  auto action_receiver = std::make_unique<ActionReceiver>(action, endpoint_);
  absl::optional<uint16_t> port =
      endpoint_->BindReceiver(0, action_receiver.get());
  RTC_DCHECK(port);
  action_receiver->SetPort(port.value());
  actions_.push_back(std::move(action_receiver));
  SendPacket(packet_size, port.value());
}

void CrossTrafficRouteImpl::SendPacket(size_t packet_size) {
  SendPacket(packet_size, null_receiver_port_);
}

void CrossTrafficRouteImpl::SendPacket(size_t packet_size, uint16_t dest_port) {
  rtc::CopyOnWriteBuffer data(packet_size);
  std::fill_n(data.MutableData(), data.size(), 0);
  receiver_->OnPacketReceived(EmulatedIpPacket(
      /*from=*/rtc::SocketAddress(),
      rtc::SocketAddress(endpoint_->GetPeerLocalAddress(), dest_port), data,
      clock_->CurrentTime()));
}

}  // namespace test
}  // namespace webrtc
