/*
 *  Copyright (c) 2016 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 WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_PACKET_H_
#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_PACKET_H_

#include <vector>

#include "webrtc/base/basictypes.h"
#include "webrtc/base/buffer.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"

namespace webrtc {
struct RTPHeader;
class RtpHeaderExtensionMap;
class Random;

namespace rtp {
class Packet {
 public:
  using ExtensionType = RTPExtensionType;
  using ExtensionManager = RtpHeaderExtensionMap;
  static constexpr size_t kMaxExtensionHeaders = 14;

  // Parse and copy given buffer into Packet.
  bool Parse(const uint8_t* buffer, size_t size);

  // Parse and move given buffer into Packet.
  bool Parse(rtc::Buffer packet);

  // Maps parsed extensions to their types to allow use of GetExtension.
  // Used after parsing when |extensions| can't be provided until base rtp
  // header is parsed.
  void IdentifyExtensions(const ExtensionManager* extensions);

  // Header.
  bool Marker() const;
  uint8_t PayloadType() const;
  uint16_t SequenceNumber() const;
  uint32_t Timestamp() const;
  uint32_t Ssrc() const;
  std::vector<uint32_t> Csrcs() const;

  // TODO(danilchap): Remove this function when all code update to use RtpPacket
  // directly. Function is there just for easier backward compatibilty.
  void GetHeader(RTPHeader* header) const;

  size_t headers_size() const;

  // Payload.
  size_t payload_size() const;
  size_t padding_size() const;
  const uint8_t* payload() const;

  // Buffer.
  size_t capacity() const;
  size_t size() const;
  const uint8_t* data() const;
  size_t FreeCapacity() const;
  size_t MaxPayloadSize() const;

  // Reset fields and buffer.
  void Clear();

  // Header setters.
  void CopyHeader(const Packet& packet);
  void SetMarker(bool marker_bit);
  void SetPayloadType(uint8_t payload_type);
  void SetSequenceNumber(uint16_t seq_no);
  void SetTimestamp(uint32_t timestamp);
  void SetSsrc(uint32_t ssrc);

  // Writes csrc list. Assumes:
  // a) There is enough room left in buffer.
  // b) Extension headers, payload or padding data has not already been added.
  void SetCsrcs(const std::vector<uint32_t>& csrcs);

  // Header extensions.
  template <typename Extension, typename... Values>
  bool GetExtension(Values...) const;

  template <typename Extension, typename... Values>
  bool SetExtension(Values...);

  template <typename Extension>
  bool ReserveExtension();

  // Reserve size_bytes for payload. Returns nullptr on failure.
  uint8_t* AllocatePayload(size_t size_bytes);
  void SetPayloadSize(size_t size_bytes);
  bool SetPadding(uint8_t size_bytes, Random* random);

 protected:
  // |extensions| required for SetExtension/ReserveExtension functions during
  // packet creating and used if available in Parse function.
  // Adding and getting extensions will fail until |extensions| is
  // provided via constructor or IdentifyExtensions function.
  explicit Packet(const ExtensionManager* extensions);
  Packet(const ExtensionManager* extensions, size_t capacity);
  virtual ~Packet();

 private:
  struct ExtensionInfo {
    ExtensionType type;
    uint16_t offset;
    uint8_t length;
  };

  // Helper function for Parse. Fill header fields using data in given buffer,
  // but does not touch packet own buffer, leaving packet in invalid state.
  bool ParseBuffer(const uint8_t* buffer, size_t size);

  // Find an extension based on the type field of the parameter.
  // If found, length field would be validated, the offset field will be set
  // and true returned,
  // otherwise the parameter will be unchanged and false is returned.
  bool FindExtension(ExtensionType type,
                     uint8_t length,
                     uint16_t* offset) const;

  // Find or allocate an extension, based on the type field of the parameter.
  // If found, the length field be checked against what is already registered
  // and the offset field will be set, then true is returned. If allocated, the
  // length field will be used for allocation and the offset update to indicate
  // position, the true is returned.
  // If not found and allocations fails, false is returned and parameter remains
  // unchanged.
  bool AllocateExtension(ExtensionType type, uint8_t length, uint16_t* offset);

  uint8_t* WriteAt(size_t offset);
  void WriteAt(size_t offset, uint8_t byte);

  const ExtensionManager* extensions_;

  // Header.
  bool marker_;
  uint8_t payload_type_;
  uint8_t padding_size_;
  uint16_t sequence_number_;
  uint32_t timestamp_;
  uint32_t ssrc_;
  size_t payload_offset_;  // Match header size with csrcs and extensions.
  size_t payload_size_;

  uint8_t num_extensions_ = 0;
  ExtensionInfo extension_entries_[kMaxExtensionHeaders];
  uint16_t extensions_size_ = 0;  // Unaligned.
  rtc::Buffer buffer_;

  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Packet);
};

template <typename Extension, typename... Values>
bool Packet::GetExtension(Values... values) const {
  uint16_t offset = 0;
  if (!FindExtension(Extension::kId, Extension::kValueSizeBytes, &offset))
    return false;
  return Extension::Parse(data() + offset, values...);
}

template <typename Extension, typename... Values>
bool Packet::SetExtension(Values... values) {
  uint16_t offset = 0;
  if (!AllocateExtension(Extension::kId, Extension::kValueSizeBytes, &offset))
    return false;
  return Extension::Write(WriteAt(offset), values...);
}

template <typename Extension>
bool Packet::ReserveExtension() {
  uint16_t offset = 0;
  if (!AllocateExtension(Extension::kId, Extension::kValueSizeBytes, &offset))
    return false;
  memset(WriteAt(offset), 0, Extension::kValueSizeBytes);
  return true;
}
}  // namespace rtp
}  // namespace webrtc

#endif  // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_PACKET_H_
