/*
 *  Copyright (c) 2015 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.
 */

#ifndef MODULES_PACING_PACKET_ROUTER_H_
#define MODULES_PACING_PACKET_ROUTER_H_

#include <stddef.h>
#include <stdint.h>

#include <cstdint>
#include <list>
#include <memory>
#include <optional>
#include <set>
#include <span>
#include <unordered_map>
#include <vector>

#include "absl/functional/any_invocable.h"
#include "api/sequence_checker.h"
#include "api/transport/network_types.h"
#include "api/units/data_size.h"
#include "modules/pacing/pacing_controller.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "modules/rtp_rtcp/source/rtcp_packet.h"
#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
#include "rtc_base/thread_annotations.h"

namespace webrtc {

class RtpRtcpInterface;

// PacketRouter keeps track of rtp send modules to support the pacer.
// In addition, it handles feedback messages, which are sent on a send
// module if possible (sender report), otherwise on receive module
// (receiver report). For the latter case, we also keep track of the
// receive modules.
class PacketRouter : public PacingController::PacketSender {
 public:
  PacketRouter();
  ~PacketRouter() override;

  PacketRouter(const PacketRouter&) = delete;
  PacketRouter& operator=(const PacketRouter&) = delete;

  // Callback is invoked after pacing, before a packet is forwarded to the
  // sending rtp module.
  void RegisterNotifyBweCallback(
      absl::AnyInvocable<void(const RtpPacketToSend& packet,
                              const PacedPacketInfo& pacing_info)> callback);

  // If `generate` is true, PacketRouter generates transport sequence numbers
  // for all RTP packets even if transport sequence number header extension has
  // not been negotiated.
  void SetGenerateTransportSequenceNumbers(bool generate);

  // If `send_as_ect1` is true, packets will be requested to be sent as ECT(1).
  void SetSendPacketsAsEct1(bool send_as_ect1);

  void AddSendRtpModule(RtpRtcpInterface* rtp_module, bool remb_candidate);
  void RemoveSendRtpModule(RtpRtcpInterface* rtp_module);

  bool SupportsRtxPayloadPadding() const;

  void AddReceiveRtpModule(RtcpFeedbackSenderInterface* rtcp_sender,
                           bool remb_candidate);
  void RemoveReceiveRtpModule(RtcpFeedbackSenderInterface* rtcp_sender);

  void SendPacket(std::unique_ptr<RtpPacketToSend> packet,
                  const PacedPacketInfo& cluster_info) override;
  std::vector<std::unique_ptr<RtpPacketToSend>> FetchFec() override;
  std::vector<std::unique_ptr<RtpPacketToSend>> GeneratePadding(
      DataSize size) override;
  void OnAbortedRetransmissions(
      uint32_t ssrc,
      std::span<const uint16_t> sequence_numbers) override;
  std::optional<uint32_t> GetRtxSsrcForMedia(uint32_t ssrc) const override;
  void OnBatchComplete() override;

  // Send REMB feedback.
  void SendRemb(int64_t bitrate_bps, std::vector<uint32_t> ssrcs);

  // Sends `packets` in one or more IP packets.
  void SendCombinedRtcpPacket(
      std::vector<std::unique_ptr<rtcp::RtcpPacket>> packets);

  // Gives the SSRC of a sender associated with this packet router that
  // can be used for sending RTCP messages. std::nullopt if no sender exists.
  std::optional<uint32_t> SsrcOfFirstSender();

 private:
  void AddRembModuleCandidate(RtcpFeedbackSenderInterface* candidate_module,
                              bool media_sender);
  void MaybeRemoveRembModuleCandidate(
      RtcpFeedbackSenderInterface* candidate_module,
      bool media_sender);
  void UnsetActiveRembModule();
  void DetermineActiveRembModule();
  void AddSendRtpModuleToMap(RtpRtcpInterface* rtp_module, uint32_t ssrc);
  void RemoveSendRtpModuleFromMap(uint32_t ssrc);

  SequenceChecker thread_checker_;
  // Ssrc to RtpRtcpInterface module;
  std::unordered_map<uint32_t, RtpRtcpInterface*> send_modules_map_
      RTC_GUARDED_BY(thread_checker_);
  std::list<RtpRtcpInterface*> send_modules_list_
      RTC_GUARDED_BY(thread_checker_);
  // The last module used to send media.
  RtpRtcpInterface* last_send_module_ RTC_GUARDED_BY(thread_checker_);
  // Rtcp modules of the rtp receivers.
  std::vector<RtcpFeedbackSenderInterface*> rtcp_feedback_senders_
      RTC_GUARDED_BY(thread_checker_);

  // Candidates for the REMB module can be RTP sender/receiver modules, with
  // the sender modules taking precedence.
  std::vector<RtcpFeedbackSenderInterface*> sender_remb_candidates_
      RTC_GUARDED_BY(thread_checker_);
  std::vector<RtcpFeedbackSenderInterface*> receiver_remb_candidates_
      RTC_GUARDED_BY(thread_checker_);
  RtcpFeedbackSenderInterface* active_remb_module_
      RTC_GUARDED_BY(thread_checker_);

  uint64_t transport_seq_ RTC_GUARDED_BY(thread_checker_);
  // If `set_transport_seq_` is true, a transport sequence number is created per
  // packet even if it is not sent in a header extension.
  bool set_transport_seq_ RTC_GUARDED_BY(thread_checker_) = false;
  bool send_rtp_packets_as_ect1_ RTC_GUARDED_BY(thread_checker_) = false;
  absl::AnyInvocable<void(RtpPacketToSend& packet,
                          const PacedPacketInfo& pacing_info)>
      notify_bwe_callback_ RTC_GUARDED_BY(thread_checker_) = nullptr;

  std::vector<std::unique_ptr<RtpPacketToSend>> pending_fec_packets_
      RTC_GUARDED_BY(thread_checker_);
  std::set<RtpRtcpInterface*> modules_used_in_current_batch_
      RTC_GUARDED_BY(thread_checker_);
};
}  // namespace webrtc
#endif  // MODULES_PACING_PACKET_ROUTER_H_
