// 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/bmff/box_header.h"

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

#include "absl/container/flat_hash_map.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/match.h"
#include "absl/strings/string_view.h"
#include "constants/labels.h"
#include "formats/bmff/constants.h"
#include "formats/bmff/xpath.h"
#include "formats/byte_range.h"
#include "riegeli/bytes/reader.h"
#include "riegeli/bytes/writer.h"
#include "riegeli/endian/endian_reading.h"
#include "riegeli/endian/endian_writing.h"

namespace credentio {

namespace {

// Returns true if the given type is "uuid".
inline bool IsUuid(absl::string_view type) { return type == "uuid"; }

// ISOBMFF and QTFF define "meta" boxes differently. ISOBMFF defines it
// as a full box with flags and version (see 4.2 'Object Structure' in ISO/IEC
// 14496-12:2005), while QuickTime does not have such a full box structure.
// Here, we check the 8 bytes and see if it is the "hdlr" box, as defined by
// https://developer.apple.com/documentation/quicktime-file-format/metadata_atom.
bool IsQuickTimeMetaBox(const BmffBoxHeader& header, riegeli::Reader& input) {
  if (header.type != "meta") {
    return false;
  }
  // The next 8 bytes can be either:
  // (iso) [1 byte version + 3 bytes flags][4 byte size of next atom]
  // (qt)  [4 byte size of next atom      ][4 byte hdlr atom type   ]
  auto pin = input.pos();
  bool success = input.Seek(pin + 4);
  std::string type;
  success &= input.Read(4, type);
  success &= input.Seek(pin);
  return success && type == "hdlr";
};

constexpr int kAtomTypeSize = 4;
constexpr int kVersionFlagsSize = 4;
constexpr int kSizeOf32BitSize = 4;
constexpr int kSizeOf64BitSize = 8;

bool ShouldWriteSize64Bits(uint64_t box_size) {
  return box_size > std::numeric_limits<uint32_t>::max();
}

bool ShouldWriteUserType(const BmffBox& box) { return IsUuid(box.type); }

bool ShouldWriteVersionFlags(const BmffBox& box) {
  return IsBmffFullBox(box.type) || IsUuid(box.type);
}

constexpr int kMaxBmffDepth = 64;

void SetInsertionPoint(std::optional<ByteRange> candidate, int64_t c2pa_offset,
                       std::optional<ByteRange>& result) {
  if (!candidate.has_value()) {
    // No candidate
    return;
  }

  if (!result.has_value()) {
    // No existing
    result = candidate;
    return;
  }

  if (c2pa_offset == -1) {
    // No C2PA range found yet, use the larger range
    if (result->length < candidate->length) {
      // Existing is smaller and no C2PA range to account for
      result = candidate;
    }
    return;
  }

  if (c2pa_offset >= candidate->offset &&
      c2pa_offset <= candidate->offset + candidate->length) {
    // C2PA is contained within the candidate, use it.
    result = candidate;
  }
}

absl::StatusOr<bool> CanOverwrite(const BmffBoxHeader& box,
                                  riegeli::Reader& reader) {
  if (box.type == "free") {
    // Free boxes are always overwritable.
    return true;
  }
  if (box.type != "uuid" || box.user_type != kC2paBmffBoxUuid) {
    // The only other overwritable box is a C2PA uuid box.
    return false;
  }

  std::string purpose;
  if (!reader.Read(8, purpose)) {
    return reader.StatusOrAnnotate(
        absl::DataLossError("kUnexpectedEof; purpose"));
  }

  if (absl::StartsWith(purpose, kBmffC2paBoxPurposeMerkle)) {
    // Merkle boxes are not overwritable, we replace them with a free box.
    return false;
  }
  if (absl::StartsWith(purpose, kBmffC2paBoxPurposeUpdate)) {
    // Update boxes are not overwritable, we remove them.
    return false;
  }

  // Original and Manifest boxes are overwritable.
  return true;
}

absl::StatusOr<bool> IterateOverBmffBoxesInternal(XPath* parent,
                                                  riegeli::Reader& reader,
                                                  uint64_t end_offset,
                                                  BmffBoxProcessor processor,
                                                  int depth = 0) {
  if (depth > kMaxBmffDepth) {
    return absl::InvalidArgumentError("Too many nested BMFF boxes");
  }
  absl::flat_hash_map<std::string, int> count_by_type;
  while (reader.pos() < (end_offset - kBmffMinSizeofBoxHeader)) {
    BmffBoxHeader box;
    if (auto box_or = ReadBmffBoxHeader(reader); box_or.ok()) {
      box = std::move(box_or.value());
    } else {
      return box_or.status();
    }

    if (box.start > (std::numeric_limits<uint64_t>::max() - box.box_size)) {
      return reader.StatusOrAnnotate(
          absl::DataLossError("Final box offset exceeds uint64_t::max"));
    }
    uint64_t box_end_offset = box.start + box.box_size;

    // If the box extends beyond the end of the input, it's invalid.
    if (box_end_offset > end_offset) {
      if (parent == nullptr) {
        return reader.StatusOrAnnotate(
            absl::DataLossError("truncated BMFF box"));
      }
      return reader.StatusOrAnnotate(
          absl::DataLossError("sub-box extends beyond the parent"));
    }

    XPath xpath(parent, box.type);
    xpath.SetPosition(++count_by_type[box.type]);
    box.xpath = xpath.ToString();

    // If it fails during processing, we can't continue.
    bool continue_processing;
    if (auto result = processor(box); result.ok()) {
      continue_processing = *result;
    } else {
      return result.status();
    }
    if (!continue_processing) {
      return false;
    }

    if (reader.pos() < box_end_offset && box.IsContainerBox()) {
      if (auto sub_continue_or = IterateOverBmffBoxesInternal(
              &xpath, reader, box_end_offset, processor, depth + 1);
          sub_continue_or.ok()) {
        continue_processing = *sub_continue_or;
      } else {
        return sub_continue_or.status();
      }
      if (!continue_processing) {
        return false;
      }
    }

    reader.Seek(box_end_offset);
  }
  return true;
}

}  // namespace

bool BmffBoxHeader::IsContainerBox() const {
  // This list mirrors the C2PA SDK's implementation:
  // https://github.com/contentauth/c2pa-rs/blob/main/sdk/src/asset_handlers/bmff_io.rs#L982.
  return type == "moov" || type == "trak" || type == "mdia" || type == "minf" ||
         type == "stbl" || type == "moof" || type == "traf" || type == "edts" ||
         type == "udta" || type == "dinf" || type == "tref" || type == "treg" ||
         type == "mvex" || type == "mfra" || type == "meta" || type == "schi";
}

absl::StatusOr<BmffBoxHeader> ReadBmffBoxHeader(riegeli::Reader& input) {
  BmffBoxHeader header;

  header.start = input.pos();

  uint32_t box_size32;
  if (!riegeli::ReadBigEndian<uint32_t>(input, box_size32)) {
    return input.StatusOrAnnotate(
        absl::DataLossError("kUnexpectedEof; box_size32"));
  }
  if (!input.Read(4, header.type)) {
    return input.StatusOrAnnotate(absl::DataLossError("kUnexpectedEof; type"));
  }
  header.header_size = 8;

  if (box_size32 == 1) {
    if (!riegeli::ReadBigEndian<uint64_t>(input, header.box_size)) {
      return input.StatusOrAnnotate(
          absl::DataLossError("kUnexpectedEof; box_size64"));
    }
    header.header_size = 16;
  } else {
    header.box_size = box_size32;
  }

  if (header.box_size < kBmffMinSizeofBoxHeader) {
    // Unsupported box size.
    return input.StatusOrAnnotate(
        absl::DataLossError("kInvalidData; unsupported box size"));
  }

  if (IsUuid(header.type)) {
    if (!input.Read(kBmffUserTypeSize, header.user_type)) {
      return input.StatusOrAnnotate(
          absl::DataLossError("kUnexpectedEof; user_type"));
    }
    header.header_size += kBmffUserTypeSize;
  }
  if ((IsBmffFullBox(header.type) ||
       (IsUuid(header.type) && header.user_type == kC2paBmffBoxUuid)) &&
      !IsQuickTimeMetaBox(header, input)) {
    header.version_and_flags_size = 4;
    if (!input.ReadByte(header.version)) {
      return input.StatusOrAnnotate(
          absl::DataLossError("kUnexpectedEof; version"));
    }
    if (!input.Read(3, header.flags)) {
      return input.StatusOrAnnotate(
          absl::DataLossError("kUnexpectedEof; flags"));
    }
  }
  if (header.box_size < header.header_size + header.version_and_flags_size) {
    return input.StatusOrAnnotate(
        absl::DataLossError("kInvalidData; box size too small for header"));
  }
  return header;
}

int64_t BmffBoxHeaderSize(const BmffBox& box) {
  uint64_t header_size = kSizeOf32BitSize + kAtomTypeSize;
  if (ShouldWriteUserType(box)) {
    header_size += kBmffUserTypeSize;
  }
  if (ShouldWriteVersionFlags(box)) {
    header_size += kVersionFlagsSize;
  }
  if (ShouldWriteSize64Bits(header_size + box.data_size)) {
    header_size += kSizeOf64BitSize;
  }
  return header_size;
}

absl::StatusOr<int64_t> WriteBmffBoxHeader(const BmffBox& box,
                                           riegeli::Writer& destination) {
  bool success = true;

  uint64_t header_size = BmffBoxHeaderSize(box);
  uint64_t box_size = header_size + box.data_size;
  bool should_write_size_64bits = ShouldWriteSize64Bits(box_size);
  uint32_t box_size32 = should_write_size_64bits ? 1 : box_size;

  success &= riegeli::WriteBigEndian<uint32_t>(box_size32, destination);
  success &= box.type.size() == kAtomTypeSize && destination.Write(box.type);
  if (should_write_size_64bits) {
    success &= riegeli::WriteBigEndian<uint64_t>(box_size, destination);
  }
  if (ShouldWriteUserType(box)) {
    success &= box.user_type.size() == kBmffUserTypeSize &&
               destination.Write(box.user_type);
  }
  if (ShouldWriteVersionFlags(box)) {
    success &= destination.WriteByte(box.version);
    success &= box.flags.size() == (kVersionFlagsSize - 1) &&
               destination.Write(box.flags);
  }
  if (!success) {
    return absl::InternalError("failed to write box header");
  }
  return header_size;
}

absl::StatusOr<std::vector<BmffBoxHeader>> ReadBmffBoxHeaders(
    riegeli::Reader& input) {
  std::vector<BmffBoxHeader> result;
  if (!input.Seek(0) || input.pos() != 0) {
    return input.StatusOrAnnotate(
        absl::DataLossError("failed to seek to start of input"));
  }
  auto result_status =
      IterateOverBmffBoxes(input, [&result](const BmffBoxHeader& box) {
        result.push_back(std::move(box));
        return true;
      });
  if (result_status.ok()) {
    return std::move(result);
  }
  return result_status;
}

absl::Status IterateOverBmffBoxes(riegeli::Reader& reader,
                                  BmffBoxProcessor processor) {
  if (!reader.SupportsSize() || !reader.Size().has_value()) {
    return absl::InvalidArgumentError(
        "manifest store not embedded: reader size cannot be determined");
  }
  if ((*reader.Size() - reader.pos()) == 0) {
    return absl::OkStatus();
  }

  return IterateOverBmffBoxesInternal(nullptr, reader, *reader.Size(),
                                      processor)
      .status();
}

absl::StatusOr<ByteRange> LocateManifestInsertionPoint(
    riegeli::Reader& reader) {
  std::optional<ByteRange> result = std::nullopt;
  std::optional<ByteRange> range = std::nullopt;

  int64_t c2pa_offset = -1;
  std::string last_atom_type_processed = "";
  auto iterate_status = IterateOverBmffBoxes(
      reader,
      [&reader, &range, &c2pa_offset, &last_atom_type_processed,
       &result](const BmffBoxHeader& box) -> absl::StatusOr<bool> {
        ABSL_ASSIGN_OR_RETURN(bool overwritable, CanOverwrite(box, reader));

        // We only care about the top level boxes, so skip all sub-boxes.
        reader.Seek(box.start + box.box_size);
        last_atom_type_processed = box.type;

        if (!overwritable) {
          SetInsertionPoint(range, c2pa_offset, result);
          range = std::nullopt;

          if (box.type == "mdat" || box.type == "moov") {
            SetInsertionPoint(ByteRange{.offset = box.start, .length = 0},
                              c2pa_offset, result);
            return false;  // Terminate loop
          }
          return true;  // Continue
        }

        if (box.type == "uuid") {
          c2pa_offset = box.start;
        }

        if (!range.has_value()) {
          range = ByteRange{.offset = box.start, .length = 0};
        }
        range->length += box.box_size;

        return true;  // Continue
      });
  ABSL_RETURN_IF_ERROR(iterate_status);
  if (last_atom_type_processed != "mdat" &&
      last_atom_type_processed != "moov") {
    return absl::InvalidArgumentError("no mdat/moov box found");
  }
  SetInsertionPoint(range, c2pa_offset, result);
  return result.value_or(ByteRange{.offset = 0, .length = 0});
}

}  // namespace credentio
