// Copyright (c) 2023 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "quiche/quic/moqt/moqt_framer.h"

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <optional>
#include <string>
#include <utility>
#include <variant>

#include "absl/container/fixed_array.h"
#include "absl/functional/overload.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include "quiche/quic/core/quic_time.h"
#include "quiche/quic/moqt/moqt_error.h"
#include "quiche/quic/moqt/moqt_key_value_pair.h"
#include "quiche/quic/moqt/moqt_messages.h"
#include "quiche/quic/moqt/moqt_names.h"
#include "quiche/quic/moqt/moqt_object.h"
#include "quiche/quic/moqt/moqt_priority.h"
#include "quiche/quic/moqt/moqt_types.h"
#include "quiche/common/platform/api/quiche_bug_tracker.h"
#include "quiche/common/platform/api/quiche_logging.h"
#include "quiche/common/quiche_buffer_allocator.h"
#include "quiche/common/quiche_data_writer.h"
#include "quiche/common/simple_buffer_allocator.h"
#include "quiche/common/wire_serialization.h"

namespace moqt {

namespace {

using ::quiche::QuicheBuffer;
using ::quiche::WireBytes;
using ::quiche::WireMoqVarInt;
using ::quiche::WireOptional;
using ::quiche::WireSpan;
using ::quiche::WireStringWithMoqVarIntLength;
using ::quiche::WireUint8;

class WireKeyVarIntPair {
 public:
  explicit WireKeyVarIntPair(uint64_t key, uint64_t value)
      : key_(key), value_(value) {}

  size_t GetLengthOnWire() {
    return quiche::ComputeLengthOnWire(WireMoqVarInt(key_),
                                       WireMoqVarInt(value_));
  }
  absl::Status SerializeIntoWriter(quiche::QuicheDataWriter& writer) {
    return quiche::SerializeIntoWriter(writer, WireMoqVarInt(key_),
                                       WireMoqVarInt(value_));
  }

 private:
  const uint64_t key_;
  const uint64_t value_;
};

class WireKeyStringPair {
 public:
  explicit WireKeyStringPair(uint64_t key, absl::string_view value)
      : key_(key), value_(value) {}
  size_t GetLengthOnWire() {
    return quiche::ComputeLengthOnWire(WireMoqVarInt(key_),
                                       WireStringWithMoqVarIntLength(value_));
  }
  absl::Status SerializeIntoWriter(quiche::QuicheDataWriter& writer) {
    return quiche::SerializeIntoWriter(writer, WireMoqVarInt(key_),
                                       WireStringWithMoqVarIntLength(value_));
  }

 private:
  const uint64_t key_;
  const absl::string_view value_;
};

class WireKeyValuePairList {
 public:
  explicit WireKeyValuePairList(const KeyValuePairList& list,
                                bool length_prefix = true)
      : list_(list), length_prefix_(length_prefix) {}

  size_t GetLengthOnWire() {
    size_t total =
        length_prefix_ ? WireMoqVarInt(list_.size()).GetLengthOnWire() : 0;
    uint64_t last_key = 0;
    list_.ForEach([&](uint64_t key,
                      std::variant<uint64_t, absl::string_view> value) {
      total += std::visit(
          absl::Overload{
              [&](uint64_t val) {
                return WireKeyVarIntPair(key - last_key, val).GetLengthOnWire();
              },
              [&](absl::string_view val) {
                return WireKeyStringPair(key - last_key, val).GetLengthOnWire();
              }},
          value);
      last_key = key;
      return true;
    });
    return total;
  }
  absl::Status SerializeIntoWriter(quiche::QuicheDataWriter& writer) {
    if (length_prefix_) {
      WireMoqVarInt(list_.size()).SerializeIntoWriter(writer);
    }
    uint64_t last_key = 0;
    list_.ForEach(
        [&](uint64_t key, std::variant<uint64_t, absl::string_view> value) {
          absl::Status status = std::visit(
              absl::Overload{[&](uint64_t val) {
                               return WireKeyVarIntPair(key - last_key, val)
                                   .SerializeIntoWriter(writer);
                             },
                             [&](absl::string_view val) {
                               return WireKeyStringPair(key - last_key, val)
                                   .SerializeIntoWriter(writer);
                             }},
              value);
          last_key = key;
          return quiche::IsWriterStatusOk(status);
        });
    return absl::OkStatus();
  }

 private:
  const KeyValuePairList& list_;
  const bool length_prefix_;
};

class WireTrackNamespace {
 public:
  WireTrackNamespace(const TrackNamespace& name) : namespace_(name) {}

  size_t GetLengthOnWire() {
    absl::FixedArray<absl::string_view> tuple(namespace_.tuple().begin(),
                                              namespace_.tuple().end());
    return quiche::ComputeLengthOnWire(
        WireMoqVarInt(namespace_.number_of_elements()),
        WireSpan<WireStringWithMoqVarIntLength, absl::string_view>(
            absl::MakeSpan(tuple)));
  }
  absl::Status SerializeIntoWriter(quiche::QuicheDataWriter& writer) {
    absl::FixedArray<absl::string_view> tuple(namespace_.tuple().begin(),
                                              namespace_.tuple().end());
    return quiche::SerializeIntoWriter(
        writer, WireMoqVarInt(namespace_.number_of_elements()),
        WireSpan<WireStringWithMoqVarIntLength, absl::string_view>(
            absl::MakeSpan(tuple)));
  }

 private:
  const TrackNamespace& namespace_;
};

class WireFullTrackName {
 public:
  WireFullTrackName(const FullTrackName& name) : name_(name) {}

  size_t GetLengthOnWire() {
    return quiche::ComputeLengthOnWire(
        WireTrackNamespace(name_.track_namespace()),
        WireStringWithMoqVarIntLength(name_.name()));
  }
  absl::Status SerializeIntoWriter(quiche::QuicheDataWriter& writer) {
    return quiche::SerializeIntoWriter(
        writer, WireTrackNamespace(name_.track_namespace()),
        WireStringWithMoqVarIntLength(name_.name()));
  }

 private:
  const FullTrackName& name_;
};

// Serializes data into buffer using the default allocator.  Invokes QUICHE_BUG
// on failure.
template <typename... Ts>
QuicheBuffer Serialize(Ts... data) {
  absl::StatusOr<QuicheBuffer> buffer = quiche::SerializeIntoBuffer(
      quiche::SimpleBufferAllocator::Get(), data...);
  if (!buffer.ok()) {
    QUICHE_BUG(moqt_failed_serialization)
        << "Failed to serialize MoQT frame: " << buffer.status();
    return QuicheBuffer();
  }
  return *std::move(buffer);
}

// Serializes data into buffer using the default allocator.  Invokes QUICHE_BUG
// on failure.
template <typename... Ts>
QuicheBuffer SerializeControlMessage(MoqtMessageType type, Ts... data) {
  uint64_t message_type = static_cast<uint64_t>(type);
  size_t payload_size = quiche::ComputeLengthOnWire(data...);
  size_t buffer_size = sizeof(uint16_t) + payload_size +
                       quiche::ComputeLengthOnWire(WireMoqVarInt(message_type));
  if (buffer_size == 0) {
    return QuicheBuffer();
  }

  QuicheBuffer buffer(quiche::SimpleBufferAllocator::Get(), buffer_size);
  quiche::QuicheDataWriter writer(buffer.size(), buffer.data());
  absl::Status status =
      SerializeIntoWriter(writer, WireMoqVarInt(message_type),
                          quiche::WireUint16(payload_size), data...);
  if (!status.ok() || writer.remaining() != 0) {
    QUICHE_BUG(moqt_failed_serialization)
        << "Failed to serialize MoQT frame: " << status;
    return QuicheBuffer();
  }
  return buffer;
}

[[maybe_unused]] WireUint8 WireDeliveryOrder(
    std::optional<MoqtDeliveryOrder> delivery_order) {
  if (!delivery_order.has_value()) {
    return WireUint8(0x00);
  }
  switch (*delivery_order) {
    case MoqtDeliveryOrder::kAscending:
      return WireUint8(0x01);
    case MoqtDeliveryOrder::kDescending:
      return WireUint8(0x02);
  }
  QUICHE_NOTREACHED();
  return WireUint8(0xff);
}

WireUint8 WireBoolean(bool value) { return WireUint8(value ? 0x01 : 0x00); }

uint64_t SignedVarintSerializedForm(int64_t value) {
  if (value < 0) {
    return ((-value) << 1) | 0x01;
  }
  return value << 1;
}

quiche::QuicheBuffer SerializeAuthToken(const AuthToken& token) {
  return Serialize(WireMoqVarInt(token.alias_type),
                   WireOptional<WireMoqVarInt>(token.alias),
                   WireOptional<WireMoqVarInt>(token.type),
                   WireOptional<WireBytes>(token.value));
}

quiche::QuicheBuffer SerializeSubscriptionFilter(
    const SubscriptionFilter& filter) {
  switch (filter.type()) {
    case MoqtFilterType::kNextGroupStart:
      return Serialize(WireMoqVarInt(filter.type()));
    case MoqtFilterType::kLargestObject:
      return Serialize(WireMoqVarInt(filter.type()));
    case MoqtFilterType::kAbsoluteStart:
      return Serialize(
          WireMoqVarInt(filter.type()),
          WireKeyVarIntPair(filter.start().group, filter.start().object));
    case MoqtFilterType::kAbsoluteRange:
      QUICHE_DCHECK_LE(filter.start().group, filter.end_group());
      return Serialize(
          WireMoqVarInt(filter.type()),
          WireKeyVarIntPair(filter.start().group, filter.start().object),
          WireMoqVarInt(filter.end_group() - filter.start().group));
  }
}

quiche::QuicheBuffer SerializeLocation(const Location& location) {
  return Serialize(WireKeyVarIntPair(location.group, location.object));
}

}  // namespace

KeyValuePairList SetupParameters::ToKeyValuePairList() const {
  KeyValuePairList out;
  if (max_auth_token_cache_size.has_value()) {
    out.insert(static_cast<uint64_t>(SetupParameter::kMaxAuthTokenCacheSize),
               *max_auth_token_cache_size);
  }
  if (path.has_value()) {
    out.insert(static_cast<uint64_t>(SetupParameter::kPath), *path);
  }
  for (const AuthToken& token : authorization_tokens) {
    out.insert(static_cast<uint64_t>(SetupParameter::kAuthorizationToken),
               SerializeAuthToken(token).AsStringView());
  }
  if (authority.has_value()) {
    out.insert(static_cast<uint64_t>(SetupParameter::kAuthority), *authority);
  }
  if (moqt_implementation.has_value()) {
    out.insert(static_cast<uint64_t>(SetupParameter::kMoqtImplementation),
               *moqt_implementation);
  }
  if (support_object_acks.has_value()) {
    out.insert(static_cast<uint64_t>(SetupParameter::kSupportObjectAcks),
               *support_object_acks ? 1ULL : 0ULL);
  }
  return out;
}

KeyValuePairList MessageParameters::ToKeyValuePairList() const {
  KeyValuePairList list;
  if (delivery_timeout.has_value()) {
    // Value cannot be zero.
    int64_t milliseconds =
        std::max(delivery_timeout->ToMilliseconds(), int64_t{1});
    list.insert(static_cast<uint64_t>(MessageParameter::kDeliveryTimeout),
                static_cast<uint64_t>(milliseconds));
  }
  for (const AuthToken& token : authorization_tokens) {
    list.insert(static_cast<uint64_t>(MessageParameter::kAuthorizationToken),
                SerializeAuthToken(token).AsStringView());
  }
  if (expires.has_value()) {
    list.insert(static_cast<uint64_t>(MessageParameter::kExpires),
                static_cast<uint64_t>(expires->ToMilliseconds()));
  }
  if (largest_object.has_value()) {
    list.insert(static_cast<uint64_t>(MessageParameter::kLargestObject),
                SerializeLocation(*largest_object).AsStringView());
  }
  if (forward_has_value()) {
    list.insert(static_cast<uint64_t>(MessageParameter::kForward),
                forward() ? 1ULL : 0ULL);
  }
  if (subscriber_priority.has_value()) {
    list.insert(static_cast<uint64_t>(MessageParameter::kSubscriberPriority),
                *subscriber_priority);
  }
  if (subscription_filter.has_value()) {
    list.insert(
        static_cast<uint64_t>(MessageParameter::kSubscriptionFilter),
        SerializeSubscriptionFilter(*subscription_filter).AsStringView());
  }
  if (group_order.has_value()) {
    list.insert(static_cast<uint64_t>(MessageParameter::kGroupOrder),
                static_cast<uint64_t>(*group_order));
  }
  if (new_group_request.has_value()) {
    list.insert(static_cast<uint64_t>(MessageParameter::kNewGroupRequest),
                *new_group_request);
  }
  if (oack_window_size.has_value()) {
    list.insert(static_cast<uint64_t>(MessageParameter::kOackWindowSize),
                static_cast<uint64_t>(oack_window_size->ToMicroseconds()));
  }
  return list;
}

quiche::QuicheBuffer MoqtFramer::SerializeObjectHeader(
    const MoqtObject& message, MoqtDataStreamType message_type,
    std::optional<PublishedObjectMetadata>& previous_object_in_stream) {
  if (!ValidateObjectMetadata(message)) {
    QUICHE_BUG(QUICHE_BUG_serialize_object_header_01)
        << "Object metadata is invalid";
    return quiche::QuicheBuffer();
  }
  // Many fields are optional because the stream type or Fetch serialization
  // omits them.
  std::optional<uint64_t> stream_type;
  std::optional<uint64_t> track_id;  // Track alias or FETCH ID.
  std::optional<uint64_t> group_id;
  std::optional<uint64_t> subgroup_id;
  std::optional<uint64_t> object_id;
  std::optional<uint8_t> publisher_priority;
  std::optional<absl::string_view> extension_headers;
  uint64_t payload_length = message.payload_length;
  bool is_first_in_stream = !previous_object_in_stream.has_value();
  if (is_first_in_stream) {
    stream_type = message_type.value();
    track_id = message.track_alias;
  }
  if (message_type.IsFetch()) {
    MoqtFetchSerialization serialization;
    if (is_first_in_stream) {
      serialization = MoqtFetchSerialization(message);
    } else {
      serialization =
          MoqtFetchSerialization(message, *previous_object_in_stream);
    }
    if (serialization.has_group_id()) {
      group_id = message.group_id;
    }
    if (serialization.has_subgroup_id()) {
      subgroup_id = message.subgroup_id;
    }
    if (serialization.has_object_id()) {
      object_id = message.object_id;
    }
    if (serialization.has_priority()) {
      publisher_priority = message.publisher_priority;
    }
    if (serialization.has_extensions()) {
      extension_headers = message.extension_headers;
    }
    return Serialize(
        WireOptional<WireMoqVarInt>(stream_type),
        WireOptional<WireMoqVarInt>(track_id),
        WireMoqVarInt(serialization.value()),
        WireOptional<WireMoqVarInt>(group_id),
        WireOptional<WireMoqVarInt>(subgroup_id),
        WireOptional<WireMoqVarInt>(object_id),
        WireOptional<WireUint8>(publisher_priority),
        WireOptional<WireStringWithMoqVarIntLength>(extension_headers),
        WireMoqVarInt(payload_length));
  }
  // Subgroup stream.
  if (!message.subgroup_id.has_value()) {
    QUICHE_BUG(QUICHE_BUG_serialize_object_header_02)
        << "Subgroup ID is missing";
    return quiche::QuicheBuffer();
  }
  if (is_first_in_stream) {
    group_id = message.group_id;
    if (message_type.IsSubgroupPresent()) {
      subgroup_id = message.subgroup_id;
    }
    if (!message_type.HasDefaultPriority()) {
      publisher_priority = message.publisher_priority;
    }
  }
  object_id = message.object_id;
  if (!is_first_in_stream) {
    *object_id -= (previous_object_in_stream->location.object + 1);
  }
  if (message_type.AreExtensionHeadersPresent()) {
    extension_headers = message.extension_headers;
  }
  std::optional<uint64_t> object_status;
  if (payload_length == 0) {
    object_status = static_cast<uint64_t>(message.object_status);
  }
  return Serialize(
      WireOptional<WireMoqVarInt>(stream_type),
      WireOptional<WireMoqVarInt>(track_id),
      WireOptional<WireMoqVarInt>(group_id),
      WireOptional<WireMoqVarInt>(subgroup_id),
      WireOptional<WireUint8>(publisher_priority), WireMoqVarInt(*object_id),
      WireOptional<WireStringWithMoqVarIntLength>(extension_headers),
      WireMoqVarInt(message.payload_length),
      WireOptional<WireMoqVarInt>(object_status));
}

quiche::QuicheBuffer MoqtFramer::SerializeObjectDatagram(
    const MoqtObject& message, absl::string_view payload,
    MoqtPriority default_priority) {
  if (!ValidateObjectMetadata(message) || message.subgroup_id.has_value()) {
    QUICHE_BUG(QUICHE_BUG_serialize_object_datagram_01)
        << "Object metadata is invalid";
    return quiche::QuicheBuffer();
  }
  if (message.payload_length != payload.length()) {
    QUICHE_BUG(QUICHE_BUG_serialize_object_datagram_03)
        << "Payload length does not match payload";
    return quiche::QuicheBuffer();
  }
  MoqtDatagramType datagram_type(
      !payload.empty(), !message.extension_headers.empty(),
      message.object_status == MoqtObjectStatus::kEndOfGroup,
      message.publisher_priority == default_priority, message.object_id == 0);
  std::optional<uint64_t> object_id =
      datagram_type.has_object_id() ? std::optional<uint64_t>(message.object_id)
                                    : std::nullopt;
  std::optional<uint8_t> publisher_priority =
      datagram_type.has_default_priority()
          ? std::nullopt
          : std::optional<uint8_t>(message.publisher_priority);
  std::optional<absl::string_view> extensions =
      datagram_type.has_extension()
          ? std::optional<absl::string_view>(message.extension_headers)
          : std::nullopt;
  std::optional<uint64_t> object_status =
      payload.empty() ? std::optional<uint64_t>(
                            static_cast<uint64_t>(message.object_status))
                      : std::nullopt;
  std::optional<absl::string_view> raw_payload =
      payload.empty() ? std::nullopt
                      : std::optional<absl::string_view>(payload);
  return Serialize(
      WireMoqVarInt(datagram_type.value()), WireMoqVarInt(message.track_alias),
      WireMoqVarInt(message.group_id), WireOptional<WireMoqVarInt>(object_id),
      WireOptional<WireUint8>(publisher_priority),
      WireOptional<WireStringWithMoqVarIntLength>(extensions),
      WireOptional<WireMoqVarInt>(object_status),
      WireOptional<WireBytes>(raw_payload));
}

quiche::QuicheBuffer MoqtFramer::SerializeSetup(const MoqtSetup& message) {
  KeyValuePairList parameters;
  if (!FillAndValidateSetupParameters(message.parameters, parameters)) {
    return quiche::QuicheBuffer();
  }
  return SerializeControlMessage(MoqtMessageType::kSetup,
                                 WireKeyValuePairList(parameters));
}

quiche::QuicheBuffer MoqtFramer::SerializeRequestOk(
    const MoqtRequestOk& message) {
  return SerializeControlMessage(
      MoqtMessageType::kRequestOk, WireMoqVarInt(message.request_id),
      WireKeyValuePairList(message.parameters.ToKeyValuePairList()));
}

quiche::QuicheBuffer MoqtFramer::SerializeSubscribe(
    const MoqtSubscribe& message, MoqtMessageType message_type) {
  return SerializeControlMessage(
      message_type, WireMoqVarInt(message.request_id),
      WireFullTrackName(message.full_track_name),
      WireKeyValuePairList(message.parameters.ToKeyValuePairList()));
}

quiche::QuicheBuffer MoqtFramer::SerializeSubscribeOk(
    const MoqtSubscribeOk& message, MoqtMessageType message_type) {
  if (!message.extensions.Validate()) {
    QUICHE_BUG(QUICHE_BUG_serialize_subscribe_ok_01)
        << "Subscribe OK extensions are ill-formed";
    return quiche::QuicheBuffer();
  }
  return SerializeControlMessage(
      message_type, WireMoqVarInt(message.request_id),
      WireMoqVarInt(message.track_alias),
      WireKeyValuePairList(message.parameters.ToKeyValuePairList()),
      WireKeyValuePairList(message.extensions, false));
}

quiche::QuicheBuffer MoqtFramer::SerializeRequestError(
    const MoqtRequestError& message) {
  return SerializeControlMessage(
      MoqtMessageType::kRequestError, WireMoqVarInt(message.request_id),
      WireMoqVarInt(message.error_code),
      WireMoqVarInt(message.retry_interval.has_value()
                        ? message.retry_interval->ToMilliseconds() + 1
                        : 0),
      WireStringWithMoqVarIntLength(message.reason_phrase));
}

quiche::QuicheBuffer MoqtFramer::SerializePublishDone(
    const MoqtPublishDone& message) {
  return SerializeControlMessage(
      MoqtMessageType::kPublishDone, WireMoqVarInt(message.request_id),
      WireMoqVarInt(message.status_code), WireMoqVarInt(message.stream_count),
      WireStringWithMoqVarIntLength(message.error_reason));
}

quiche::QuicheBuffer MoqtFramer::SerializeRequestUpdate(
    const MoqtRequestUpdate& message) {
  return SerializeControlMessage(
      MoqtMessageType::kRequestUpdate, WireMoqVarInt(message.request_id),
      WireMoqVarInt(message.existing_request_id),
      WireKeyValuePairList(message.parameters.ToKeyValuePairList()));
}

quiche::QuicheBuffer MoqtFramer::SerializePublishNamespace(
    const MoqtPublishNamespace& message) {
  return SerializeControlMessage(
      MoqtMessageType::kPublishNamespace, WireMoqVarInt(message.request_id),
      WireTrackNamespace(message.track_namespace),
      WireKeyValuePairList(message.parameters.ToKeyValuePairList()));
}

quiche::QuicheBuffer MoqtFramer::SerializeNamespace(
    const MoqtNamespace& message) {
  return SerializeControlMessage(
      MoqtMessageType::kNamespace,
      WireTrackNamespace(message.track_namespace_suffix));
}

quiche::QuicheBuffer MoqtFramer::SerializeNamespaceDone(
    const MoqtNamespaceDone& message) {
  return SerializeControlMessage(
      MoqtMessageType::kNamespaceDone,
      WireTrackNamespace(message.track_namespace_suffix));
}

quiche::QuicheBuffer MoqtFramer::SerializeTrackStatus(
    const MoqtTrackStatus& message) {
  return SerializeSubscribe(message, MoqtMessageType::kTrackStatus);
}

quiche::QuicheBuffer MoqtFramer::SerializeGoAway(const MoqtGoAway& message) {
  return SerializeControlMessage(
      MoqtMessageType::kGoAway,
      WireStringWithMoqVarIntLength(message.new_session_uri));
}

quiche::QuicheBuffer MoqtFramer::SerializeSubscribeNamespace(
    const MoqtSubscribeNamespace& message) {
  return SerializeControlMessage(
      MoqtMessageType::kSubscribeNamespace, WireMoqVarInt(message.request_id),
      WireTrackNamespace(message.track_namespace_prefix),
      WireKeyValuePairList(message.parameters.ToKeyValuePairList()));
}

quiche::QuicheBuffer MoqtFramer::SerializeSubscribeTracks(
    const MoqtSubscribeTracks& message) {
  return SerializeControlMessage(
      MoqtMessageType::kSubscribeTracks, WireMoqVarInt(message.request_id),
      WireTrackNamespace(message.track_namespace_prefix),
      WireKeyValuePairList(message.parameters.ToKeyValuePairList()));
}

quiche::QuicheBuffer MoqtFramer::SerializeFetch(const MoqtFetch& message) {
  if (std::holds_alternative<StandaloneFetch>(message.fetch)) {
    const StandaloneFetch& standalone_fetch =
        std::get<StandaloneFetch>(message.fetch);
    if (standalone_fetch.end_location < standalone_fetch.start_location) {
      QUICHE_BUG(MoqtFramer_invalid_fetch) << "Invalid FETCH object range";
      return quiche::QuicheBuffer();
    }
  }
  if (std::holds_alternative<StandaloneFetch>(message.fetch)) {
    const StandaloneFetch& standalone_fetch =
        std::get<StandaloneFetch>(message.fetch);
    return SerializeControlMessage(
        MoqtMessageType::kFetch, WireMoqVarInt(message.request_id),
        WireMoqVarInt(FetchType::kStandalone),
        WireFullTrackName(standalone_fetch.full_track_name),
        WireMoqVarInt(standalone_fetch.start_location.group),
        WireMoqVarInt(standalone_fetch.start_location.object),
        WireMoqVarInt(standalone_fetch.end_location.group),
        WireMoqVarInt(standalone_fetch.end_location.object == kMaxObjectId
                          ? 0
                          : standalone_fetch.end_location.object + 1),
        WireKeyValuePairList(message.parameters.ToKeyValuePairList()));
  }
  uint64_t request_id, joining_start;
  if (std::holds_alternative<JoiningFetchRelative>(message.fetch)) {
    const JoiningFetchRelative& joining_fetch =
        std::get<JoiningFetchRelative>(message.fetch);
    request_id = joining_fetch.joining_request_id;
    joining_start = joining_fetch.joining_start;
  } else {
    const JoiningFetchAbsolute& joining_fetch =
        std::get<JoiningFetchAbsolute>(message.fetch);
    request_id = joining_fetch.joining_request_id;
    joining_start = joining_fetch.joining_start;
  }
  return SerializeControlMessage(
      MoqtMessageType::kFetch, WireMoqVarInt(message.request_id),
      WireMoqVarInt(message.fetch.index() + 1), WireMoqVarInt(request_id),
      WireMoqVarInt(joining_start),
      WireKeyValuePairList(message.parameters.ToKeyValuePairList()));
}

quiche::QuicheBuffer MoqtFramer::SerializeFetchOk(const MoqtFetchOk& message) {
  return SerializeControlMessage(
      MoqtMessageType::kFetchOk, WireMoqVarInt(message.request_id),
      WireBoolean(message.end_of_track),
      WireMoqVarInt(message.end_location.group),
      WireMoqVarInt(message.end_location.object == kMaxObjectId
                        ? 0
                        : (message.end_location.object + 1)),
      WireKeyValuePairList(message.parameters.ToKeyValuePairList()),
      WireKeyValuePairList(message.extensions, false));
}

quiche::QuicheBuffer MoqtFramer::SerializeFetchCancel(
    const MoqtFetchCancel& message) {
  return SerializeControlMessage(MoqtMessageType::kFetchCancel,
                                 WireMoqVarInt(message.request_id));
}

quiche::QuicheBuffer MoqtFramer::SerializePublish(const MoqtPublish& message) {
  return SerializeControlMessage(
      MoqtMessageType::kPublish, WireMoqVarInt(message.request_id),
      WireFullTrackName(message.full_track_name),
      WireMoqVarInt(message.track_alias),
      WireKeyValuePairList(message.parameters.ToKeyValuePairList()),
      WireKeyValuePairList(message.extensions, false));
}

quiche::QuicheBuffer MoqtFramer::SerializeObjectAck(
    const MoqtObjectAck& message) {
  return SerializeControlMessage(
      MoqtMessageType::kObjectAck, WireMoqVarInt(message.group_id),
      WireMoqVarInt(message.object_id),
      WireMoqVarInt(SignedVarintSerializedForm(
          message.delta_from_deadline.ToMicroseconds())));
}

bool MoqtFramer::FillAndValidateSetupParameters(
    const SetupParameters& parameters, KeyValuePairList& out) {
  if (SetupParametersAllowedByMessage(parameters, perspective_,
                                      using_webtrans_) != MoqtError::kNoError) {
    QUICHE_BUG(QUICHE_BUG_invalid_setup_parameters)
        << "Invalid setup parameters for "
        << MoqtMessageTypeToString(MoqtMessageType::kSetup);
    return false;
  }
  out = parameters.ToKeyValuePairList();
  return true;
}

// static
bool MoqtFramer::ValidateObjectMetadata(const MoqtObject& object) {
  return (object.object_status == MoqtObjectStatus::kNormal ||
          object.object_status == MoqtObjectStatus::kEndOfGroup ||
          object.payload_length == 0);
}

}  // namespace moqt
