// 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 "formats/jpeg/testing/jumbf_creator.h"

#include <sys/stat.h>

#include <cstdint>
#include <optional>
#include <string>
#include <vector>

#include "absl/strings/string_view.h"
#include "utils/byte_writers.h"

namespace credentio {
namespace {

std::string CreateJumbfDescriptionBox(const JumbfCreatorParams& params) {
  std::vector<uint8_t> box;

  // 4 bytes for Lbox
  // 4 bytes for Tbox
  // Maybe 8 bytes for XLBox (if forced)
  // 8 bytes for UUID High
  // 8 bytes for UUID Low
  // 1 byte for Toggles
  // X bytes for Label
  // 1 byte for 0x00 terminator
  // ---
  // 26 + label.length() + 8?
  uint32_t size = 26 + params.label.length() + (params.force_xlbox ? 8 : 0);
  box.reserve(size);

  uint32_t lbox = size;
  std::optional<uint64_t> xlbox = std::nullopt;
  if (params.force_xlbox) {
    lbox = 1;
    xlbox = static_cast<uint64_t>(size);
  }

  // Lbox
  WriteUint32NetworkOrder(lbox, &box);

  // Tbox
  WriteUint32NetworkOrder(params.description_box_identifier, &box);

  // Xlbox
  if (xlbox.has_value()) {
    WriteUint64NetworkOrder(*xlbox, &box);
  }

  // Type
  WriteUint64NetworkOrder(params.uuid_high, &box);
  WriteUint64NetworkOrder(params.uuid_low, &box);

  // Toggles
  box.push_back(params.toggles);

  // Label
  for (const auto& c : params.label) {
    box.push_back(c);
  }
  box.push_back(params.label_terminator);  // End of label

  return std::string(box.begin(), box.end());
}

std::string CreateJumbfContentBox(absl::string_view payload) {
  std::vector<uint8_t> box;

  // 4 bytes for Lbox
  // 4 bytes for Tbox
  // ---
  // 8 + payload.length()
  uint32_t size = 8 + payload.size();
  box.reserve(size);

  // Lbox
  WriteUint32NetworkOrder(size, &box);

  // Tbox??
  box.push_back('a');
  box.push_back('a');
  box.push_back('a');
  box.push_back('a');

  // Payload
  for (const auto& c : payload) {
    box.push_back(c);
  }

  return std::string(box.begin(), box.end());
}
}  // namespace

std::string CreateJumbf(const JumbfCreatorParams& params) {
  std::string description_box = CreateJumbfDescriptionBox(params);
  std::string content_box = CreateJumbfContentBox(params.payload);

  std::vector<uint8_t> box;

  // 4 bytes for Lbox
  // 4 bytes for Tbox
  // Maybe 8 bytes for XLBox (if forced)
  // Description Box
  // Content Box
  // ---
  // 26 + label.length() + 8?
  uint32_t size = 8 + (params.force_xlbox ? 8 : 0) + description_box.size() +
                  content_box.size();
  box.reserve(size);

  uint32_t lbox = size;
  std::optional<uint64_t> xlbox = std::nullopt;
  if (params.force_xlbox) {
    lbox = 1;
    xlbox = static_cast<uint64_t>(size);
  }

  // Lbox
  WriteUint32NetworkOrder(lbox, &box);

  // Tbox
  WriteUint32NetworkOrder(params.super_box_identifier, &box);

  // Xlbox
  if (xlbox.has_value()) {
    WriteUint64NetworkOrder(*xlbox, &box);
  }

  // Description Box
  for (const auto& c : description_box) {
    box.push_back(c);
  }

  // Content Box
  for (const auto& c : content_box) {
    box.push_back(c);
  }

  return std::string(box.begin(), box.end());
}

}  // namespace credentio
