// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "jumbf/test_utils.h"

#include <cstdint>
#include <cstring>
#include <optional>
#include <string>

#include "absl/log/check.h"
#include "absl/strings/cord.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include "jumbf/constants.h"
#include "riegeli/endian/endian_writing.h"
#include "uuid/uuid.h"

namespace jumbf {

std::string WrapBox(absl::string_view content, uint32_t tbox) {
  const uint32_t lbox = content.length() + /*lbox*/ 4 + /*tbox*/ 4;
  std::string serialized(lbox, '\0');
  char* cursor = serialized.data();
  riegeli::WriteBigEndian<uint32_t>(lbox, cursor);
  cursor += sizeof(uint32_t);
  riegeli::WriteBigEndian<uint32_t>(tbox, cursor);
  cursor += sizeof(uint32_t);
  // This is safe because the length of `serialized` has been calculated above
  // to always have enough room for `content`.
  memcpy(cursor, content.data(), content.length());
  return serialized;
}

std::string WrapUndeterminedLengthBox(absl::string_view content,
                                      uint32_t tbox) {
  const uint32_t box_length = content.length() + /*lbox*/ 4 + /*tbox*/ 4;
  std::string serialized(box_length, '\0');
  char* cursor = serialized.data();
  // LBox value
  riegeli::WriteBigEndian<uint32_t>(0, cursor);
  cursor += sizeof(uint32_t);
  riegeli::WriteBigEndian<uint32_t>(tbox, cursor);
  cursor += sizeof(uint32_t);
  // This is safe because the length of `serialized` has been calculated above
  // to always have enough room for `content`.
  memcpy(cursor, content.data(), content.length());
  return serialized;
}

void SerializeUuid(char** dest, credentio::Uuid uuid) {
  const std::string bytes = uuid.ToProtoBytes();
  if (bytes.size() == 16) {
    memcpy(*dest, bytes.data(), 16);
  } else {
    memset(*dest, 0, 16);
  }
  *dest += 16;
}

std::string EncodeDescriptionBox(credentio::Uuid uuid,
                                 std::optional<absl::string_view> label,
                                 bool requestable) {
  if (label.has_value()) {
    CHECK(!absl::StrContains(*label, '\0'));
    const size_t description_content_length = /*uuid*/ 16 + /*toggles*/ 1 +
                                              label->size() +
                                              /*label NUL terminator*/ 1;
    std::string description_content(description_content_length, '\0');
    char* content_cursor = description_content.data();

    jumbf::SerializeUuid(&content_cursor, uuid);
    uint8_t toggles = kDescriptionToggleLabelPresent;
    if (requestable) {
      toggles |= kDescriptionToggleRequestable;
    }
    riegeli::WriteBigEndian<uint8_t>(toggles, content_cursor);
    content_cursor += sizeof(uint8_t);
    memcpy(content_cursor, label->data(), label->size());
    content_cursor += label->size();
    *content_cursor++ = '\0';
    return WrapBox(description_content, kDescriptionBoxType);
  }
  const size_t description_content_length = /*uuid*/ 16 + /*toggles*/ 1 +
                                            /*label NUL terminator*/ 1;
  std::string description_content(description_content_length, '\0');
  char* content_cursor = description_content.data();

  jumbf::SerializeUuid(&content_cursor, uuid);
  uint8_t toggles = kDescriptionToggleEmpty;
  riegeli::WriteBigEndian<uint8_t>(toggles, content_cursor);
  content_cursor += sizeof(uint8_t);
  *content_cursor++ = '\0';
  return WrapBox(description_content, kDescriptionBoxType);
}

std::string EncodeCborBox(absl::string_view contents) {
  return WrapBox(contents, kCborBoxType);
}

std::string EncodeSuperBox(credentio::Uuid uuid,
                           std::optional<absl::string_view> label,
                           absl::Span<const absl::string_view> contents,
                           bool requestable) {
  return jumbf::WrapBox(
      absl::StrCat(EncodeDescriptionBox(uuid, label, requestable),
                   absl::StrJoin(contents, "")),
      jumbf::kSuperBoxType);
}

absl::Cord CordFromConstexpr(absl::string_view data) {
  return absl::MakeCordFromExternal(data, [](absl::string_view data) {});
}

}  // namespace jumbf
