// 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/pdf/embedder.h"

#include <cstdint>
#include <iterator>
#include <optional>
#include <string>
#include <tuple>
#include <utility>
#include <variant>
#include <vector>

#include "absl/algorithm/container.h"
#include "absl/container/btree_set.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/cord.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
#include "formats/pdf/constants.h"
#include "formats/pdf/extractor.h"
#include "formats/pdf/object_writer.h"
#include "formats/pdf/objects.h"
#include "formats/pdf/reader.h"
#include "riegeli/bytes/reader.h"
#include "riegeli/bytes/writer.h"

namespace credentio {
namespace {

using Dictionary = Object::Dictionary;

constexpr absl::string_view kPdfHeader = "%PDF-1.7\n%\x90\x91\xC2\x9A\n";

struct XrefTableEntry {
  uint32_t object_number;
  uint32_t generation_number;

  int64_t offset;
  bool in_use;

  friend bool operator<(const XrefTableEntry& lhs, const XrefTableEntry& rhs) {
    return std::tie(lhs.object_number, lhs.generation_number, lhs.offset,
                    lhs.in_use) < std::tie(rhs.object_number,
                                           rhs.generation_number, rhs.offset,
                                           rhs.in_use);
  }
};

template <typename T>
absl::StatusOr<T> DereferenceObject(const Object::IndirectReference& ref,
                                    PdfReader& reader) {
  ABSL_ASSIGN_OR_RETURN(
      const auto& indirect_obj,
      reader.GetObject(ref.object_number, ref.generation_number));
  return Object::As<T>(indirect_obj.object);
}

// Using the basic mechanism to form a linked list from the free entries.
// See ISO 32000-2 Section 7.5.4 for more details.
std::vector<XrefTableEntry> ReconstructXrefTableFreeEntries(
    const absl::btree_set<Object::IndirectReference>& free_entries) {
  if (free_entries.empty()) {
    return {};
  }
  std::vector<XrefTableEntry> xref_table_entries;
  xref_table_entries.reserve(free_entries.size());

  for (const auto& free_entry : free_entries) {
    xref_table_entries.push_back(
        XrefTableEntry{.object_number = free_entry.object_number,
                       .generation_number = free_entry.generation_number,
                       .offset = 0,
                       .in_use = false});
  }

  // Set the offset of each free entry to the object number of the next free
  // entry.
  for (int i = 0; i < xref_table_entries.size() - 1; ++i) {
    xref_table_entries[i].offset = xref_table_entries[i + 1].object_number;
  }

  // Signify the end of the list by having an offset value of 0.
  xref_table_entries.back().offset = 0;

  return xref_table_entries;
}

// Returns true if the object numbers in the given vector are consecutive,
// starting from 0. Assumes the vector is already sorted by object number.
bool AreObjectNumbersConsecutive(
    absl::Span<const XrefTableEntry> xref_table_entries) {
  for (auto i = 0; i < xref_table_entries.size(); i++) {
    if (xref_table_entries[i].object_number != i) {
      return false;
    }
  }
  return true;
}

absl::Status WritePdfHeader(riegeli::Writer& output) {
  if (!output.Write(kPdfHeader)) {
    return output.status();
  }
  return absl::OkStatus();
}

// See ISO 32000-2 Section 7.5.4 for the cross-reference table structure.
absl::Status WriteXrefTable(std::vector<XrefTableEntry>& xref_table_entries,
                            riegeli::Writer& output) {
  // Write the xref header.
  if (!output.Write("xref\n")) {
    return output.status();
  }

  absl::c_sort(xref_table_entries);
  if (!AreObjectNumbersConsecutive(xref_table_entries)) {
    return absl::UnimplementedError(
        "Non-consecutive object numbers in the xref table are not supported.");
  }

  // Write the object count section.
  if (!output.Write(absl::StrCat(0, " ", xref_table_entries.size(), "\n"))) {
    return output.status();
  }

  // Write the xref table entries.
  for (const auto& entry : xref_table_entries) {
    if (!output.Write(absl::StrFormat("%010d %05d %c \n", entry.offset,
                                      entry.generation_number,
                                      entry.in_use ? 'n' : 'f'))) {
      return output.status();
    }
  }
  return absl::OkStatus();
}

// See ISO 32000-2 Section 7.5.5 for the trailer structure.
absl::Status WriteTrailer(const Dictionary& trailer_dict,
                          int64_t xref_table_offset, riegeli::Writer& output) {
  // Write the trailer header.
  if (!output.Write("trailer\n")) {
    return output.status();
  }

  // Write the trailer dictionary object.
  Object obj = Object{.value = trailer_dict};
  ABSL_RETURN_IF_ERROR(WriteObject(obj, output));

  // Write the trailer footer and the offset to the last cross-reference table.
  if (!output.Write(
          absl::StrCat("\nstartxref\n", xref_table_offset, "\n%%EOF"))) {
    return output.status();
  }

  return absl::OkStatus();
}

absl::Status CopyObjects(
    PdfReader& reader,
    absl::Span<const std::optional<Object::IndirectReference>> objects_to_skip,
    int64_t start_offset, std::vector<XrefTableEntry>& xref_table_entries,
    riegeli::Writer& output) {
  while (reader.HasNext()) {
    ABSL_ASSIGN_OR_RETURN(auto obj, reader.Next());

    bool should_skip = absl::c_any_of(
        objects_to_skip,
        [&](const std::optional<Object::IndirectReference>& skip_ref) {
          return skip_ref.has_value() &&
                 obj.object_number == skip_ref->object_number &&
                 obj.generation_number == skip_ref->generation_number;
        });

    if (should_skip) continue;
    int64_t obj_offset = output.pos();
    ABSL_RETURN_IF_ERROR(WriteIndirectObject(obj, output));
    xref_table_entries.push_back(
        XrefTableEntry{.object_number = obj.object_number,
                       .generation_number = obj.generation_number,
                       .offset = obj_offset - start_offset,
                       .in_use = true});
  }
  return absl::OkStatus();
}

// Creates an indirect stream Object with a zero-filled manifest store.
IndirectObject BuildC2paManifestTemplate(uint32_t object_number,
                                         uint32_t generation_number,
                                         int64_t manifest_store_size) {
  IndirectObject store_template;
  store_template.object_number = object_number;
  store_template.generation_number = generation_number;

  std::string formatted_date = absl::FormatTime(
      "D:%Y%m%d%H%M%S+00'00'", absl::Now(), absl::UTCTimeZone());
  Dictionary params_dict{
      .entries = {
          {std::string(kPdfSizeKey),
           Object{.value = Object::Integer{.value = manifest_store_size}}},
          {std::string(kPdfModDateKey),
           Object{.value = Object::LiteralString{.raw_value = formatted_date}}},
      }};

  store_template.stream_dictionary = Dictionary{
      .entries = {
          {"Length",
           Object{.value = Object::Integer{.value = manifest_store_size}}},
          {std::string(kPdfSubtypeKey),
           Object{.value = Object::Name{.value = std::string(
                                            kPdfC2paManifestMimeType)}}},
          {std::string(kPdfParamsKey), Object{.value = std::move(params_dict)}},
      }};
  store_template.object =
      Object{.value = Object::Stream{
                 .raw_value = std::string(manifest_store_size, '\0')}};
  return store_template;
}

IndirectObject BuildC2paManifestFileSpec(
    uint32_t object_number, uint32_t generation_number,
    const IndirectObject& c2pa_manifest_store_obj) {
  IndirectObject file_spec;
  file_spec.object_number = object_number;
  file_spec.generation_number = generation_number;
  file_spec.object = Object{
      .value = Dictionary{
          .entries = {
              {std::string(kPdfTypeKey),
               Object{.value = Object::Name{.value = std::string(
                                                kPdfFileSpecType)}}},
              {std::string(kPdfAfRelationshipKey),
               Object{.value =
                          Object::Name{.value = std::string(
                                           kPdfC2paManifestAfRelationship)}}},
              {std::string(kPdfFKey),
               Object{.value =
                          Object::LiteralString{
                              .raw_value =
                                  std::string(kPdfC2paEmbeddedFileName)}}},
              {std::string(kPdfUfKey),
               Object{.value =
                          Object::LiteralString{
                              .raw_value =
                                  std::string(kPdfC2paEmbeddedFileName)}}},
              {std::string(kPdfEfKey),
               Object{
                   .value = Dictionary{
                       .entries = {
                           {std::string(kPdfFKey),
                            Object{.value = Object::IndirectReference{
                                       .object_number = c2pa_manifest_store_obj
                                                            .object_number,
                                       .generation_number =
                                           c2pa_manifest_store_obj
                                               .generation_number}}}}}}}}}};
  return file_spec;
}

absl::Status InsertNameTreePair(absl::string_view key,
                                const Object::IndirectReference& value,
                                Object::Array& name_tree_array) {
  if (name_tree_array.objects.size() % 2 != 0) {
    return absl::InternalError(
        "Name tree array must contain an even number of objects.");
  }

  // Find the correct position to insert the new key-value pair to maintain
  // lexicographical order of keys. The `name_tree_array` stores keys and
  // values interleaved, e.g., [key1, value1, key2, value2, ...].
  auto insertion_it = name_tree_array.objects.begin();
  while (insertion_it != name_tree_array.objects.end()) {
    // We only need to check the keys, which are at even indices.
    ABSL_ASSIGN_OR_RETURN(const auto& current_key,
                          Object::As<Object::LiteralString>(*insertion_it));
    if (key < current_key.raw_value) {
      // Found the position. The new key should be inserted before this one.
      break;
    }
    // Advance the iterator to the next key.
    insertion_it += 2;
  }

  name_tree_array.objects.insert(
      insertion_it,
      {Object{.value = Object::LiteralString{.raw_value = std::string(key)}},
       Object{.value = value}});

  return absl::OkStatus();
}

}  // namespace

absl::StatusOr<int64_t> PdfEmbedder::RewriteForEmbedding(
    riegeli::Reader& input, int64_t estimated_manifest_store_size,
    riegeli::Writer& output) const {
  ABSL_ASSIGN_OR_RETURN(auto reader, PdfReader::Create(&input));

  if (auto manifest_store = PdfExtractor().ExtractManifestStore(input);
      manifest_store.ok()) {
    return absl::AlreadyExistsError(
        "Rewriting failed because a C2PA manifest store already exists ");
  }

  // The start offset of the output stream.
  int64_t start_offset = output.pos();

  // Step 1:
  // Locate and identify objects that need to be updated/created for C2PA
  // embedding.
  auto file_trailer_dict = reader->file_trailer_dictionary();
  ABSL_ASSIGN_OR_RETURN(
      auto object_count_obj,
      FindObjectInDictionary<Object::Integer>(file_trailer_dict, kPdfSizeKey));
  uint32_t next_available_object_number = object_count_obj.value;

  // /Root
  ABSL_ASSIGN_OR_RETURN(auto doc_catalog_ref,
                        FindObjectInDictionary<Object::IndirectReference>(
                            file_trailer_dict, kPdfRootKey));
  ABSL_ASSIGN_OR_RETURN(auto doc_catalog_dict, DereferenceObject<Dictionary>(
                                                   doc_catalog_ref, *reader));

  // /Root/Names
  std::optional<Dictionary> catalog_names = std::nullopt;
  std::optional<Object::IndirectReference> catalog_names_ref = std::nullopt;
  if (auto it = doc_catalog_dict.entries.find(kPdfNamesKey);
      it != doc_catalog_dict.entries.end()) {
    if (std::holds_alternative<Dictionary>(it->second.value)) {
      // If we find the catalog names dictionary to be a direct object, move it
      // into an indirect object then update the document catalog dictionary to
      // point to it.
      catalog_names = std::move(std::get<Dictionary>(it->second.value));
      catalog_names_ref = Object::IndirectReference{
          .object_number = next_available_object_number++,
          .generation_number = 0};
      doc_catalog_dict.entries[kPdfNamesKey] =
          Object{.value = *catalog_names_ref};
    } else {
      ABSL_ASSIGN_OR_RETURN(catalog_names_ref,
                            Object::As<Object::IndirectReference>(it->second));
      ABSL_ASSIGN_OR_RETURN(
          catalog_names,
          DereferenceObject<Dictionary>(catalog_names_ref.value(), *reader));
    }
  }

  // /Root/Names/EmbeddedFiles
  std::optional<Dictionary> name_tree = std::nullopt;
  std::optional<Object::IndirectReference> name_tree_ref = std::nullopt;
  if (catalog_names.has_value()) {
    if (auto it = catalog_names->entries.find(kPdfEmbeddedFilesKey);
        it != catalog_names->entries.end()) {
      ABSL_ASSIGN_OR_RETURN(name_tree_ref,
                            Object::As<Object::IndirectReference>(it->second));
      ABSL_ASSIGN_OR_RETURN(name_tree, DereferenceObject<Dictionary>(
                                           name_tree_ref.value(), *reader));
    }
  }

  // Step 2: Write the header.
  ABSL_RETURN_IF_ERROR(WritePdfHeader(output));

  // Step 3: Copy the objects that can be written as-is from the input stream to
  // the output stream.

  // A list of xref table entries that will be written to the output stream,
  // including both in-use and free entries. In-use entry's offset is relative
  // to `start_offset`.
  std::vector<XrefTableEntry> xref_table_entries;
  ABSL_RETURN_IF_ERROR(CopyObjects(
      *reader,
      /*objects_to_skip=*/{doc_catalog_ref, catalog_names_ref, name_tree_ref},
      start_offset, xref_table_entries, output));

  // Step 4.1: Create the embedded file stream object that holds the C2PA
  // manifest store.
  IndirectObject c2pa_manifest_store_obj = BuildC2paManifestTemplate(
      /*object_number=*/next_available_object_number++,
      /*generation_number=*/0, estimated_manifest_store_size);

  int64_t c2pa_manifest_store_offset = output.pos();
  ABSL_RETURN_IF_ERROR(WriteIndirectObject(c2pa_manifest_store_obj, output));
  xref_table_entries.push_back(XrefTableEntry{
      .object_number = c2pa_manifest_store_obj.object_number,
      .generation_number = c2pa_manifest_store_obj.generation_number,
      .offset = c2pa_manifest_store_offset - start_offset,
      .in_use = true});

  // Step 4.2: Create a file specification object for the C2PA manifest
  // store.
  IndirectObject c2pa_manifest_store_file_spec = BuildC2paManifestFileSpec(
      /*object_number=*/next_available_object_number++,
      /*generation_number=*/0, c2pa_manifest_store_obj);

  int64_t c2pa_manifest_store_file_spec_offset = output.pos();
  ABSL_RETURN_IF_ERROR(
      WriteIndirectObject(c2pa_manifest_store_file_spec, output));
  xref_table_entries.push_back(XrefTableEntry{
      .object_number = c2pa_manifest_store_file_spec.object_number,
      .generation_number = c2pa_manifest_store_file_spec.generation_number,
      .offset = c2pa_manifest_store_file_spec_offset - start_offset,
      .in_use = true});

  // Step 4.3: Add/Update the embedded files name tree.
  if (!name_tree.has_value()) {
    // Since we don't find an existing name tree in the input PDF, we can safely
    // create a new one.
    name_tree = Dictionary{};
    name_tree_ref = Object::IndirectReference{
        .object_number = next_available_object_number++,
        .generation_number = 0};
  }
  auto name_tree_it = name_tree->entries.find(kPdfNamesKey);
  if (name_tree_it == name_tree->entries.end() ||
      !std::holds_alternative<Object::Array>(name_tree_it->second.value)) {
    name_tree_it =
        name_tree->entries
            .insert_or_assign(kPdfNamesKey, Object{.value = Object::Array{}})
            .first;
  }
  Object::Array& name_tree_array =
      std::get<Object::Array>(name_tree_it->second.value);
  ABSL_RETURN_IF_ERROR(InsertNameTreePair(
      kPdfC2paEmbeddedFileName,
      Object::IndirectReference{
          .object_number = c2pa_manifest_store_file_spec.object_number,
          .generation_number = c2pa_manifest_store_file_spec.generation_number},
      name_tree_array));

  int64_t name_tree_offset = output.pos();
  ABSL_RETURN_IF_ERROR(WriteIndirectObject(
      IndirectObject{.object_number = name_tree_ref->object_number,
                     .generation_number = name_tree_ref->generation_number,
                     .object = Object{.value = *name_tree}},
      output));
  xref_table_entries.push_back(
      XrefTableEntry{.object_number = name_tree_ref->object_number,
                     .generation_number = name_tree_ref->generation_number,
                     .offset = name_tree_offset - start_offset,
                     .in_use = true});

  // Step 4.4: Add/Update the catalog names dictionary.
  if (!catalog_names.has_value()) {
    // Since we don't find an existing catalog names dictionary in the input
    // PDF, we can safely create a new one.
    catalog_names = Dictionary{};
    catalog_names_ref = Object::IndirectReference{
        .object_number = next_available_object_number++,
        .generation_number = 0};
    doc_catalog_dict.entries[kPdfNamesKey] =
        Object{.value = *catalog_names_ref};
  }
  if (!catalog_names->entries.contains(kPdfEmbeddedFilesKey)) {
    catalog_names->entries[kPdfEmbeddedFilesKey] =
        Object{.value = *name_tree_ref};
  }

  int64_t catalog_names_offset = output.pos();
  ABSL_RETURN_IF_ERROR(WriteIndirectObject(
      IndirectObject{.object_number = catalog_names_ref->object_number,
                     .generation_number = catalog_names_ref->generation_number,
                     .object = Object{.value = *catalog_names}},
      output));
  xref_table_entries.push_back(
      XrefTableEntry{.object_number = catalog_names_ref->object_number,
                     .generation_number = catalog_names_ref->generation_number,
                     .offset = catalog_names_offset - start_offset,
                     .in_use = true});

  // Step 4.5: Update the document catalog dictionary.
  auto af_it = doc_catalog_dict.entries.find(kPdfAfKey);
  if (af_it == doc_catalog_dict.entries.end() ||
      !std::holds_alternative<Object::Array>(af_it->second.value)) {
    af_it = doc_catalog_dict.entries
                .insert_or_assign(kPdfAfKey, Object{.value = Object::Array{}})
                .first;
  }
  std::get<Object::Array>(af_it->second.value)
      .objects.push_back(Object{
          .value = Object::IndirectReference{
              .object_number = c2pa_manifest_store_file_spec.object_number,
              .generation_number =
                  c2pa_manifest_store_file_spec.generation_number}});
  int64_t doc_catalog_dict_offset = output.pos();
  ABSL_RETURN_IF_ERROR(WriteIndirectObject(
      IndirectObject{.object_number = doc_catalog_ref.object_number,
                     .generation_number = doc_catalog_ref.generation_number,
                     .object = Object{.value = doc_catalog_dict}},
      output));
  xref_table_entries.push_back(
      XrefTableEntry{.object_number = doc_catalog_ref.object_number,
                     .generation_number = doc_catalog_ref.generation_number,
                     .offset = doc_catalog_dict_offset - start_offset,
                     .in_use = true});

  // Step 5: Compute and write the xref table.
  int64_t xref_table_offset = output.pos() - start_offset;

  // Add all existing free entries to the xref table.
  auto xref_table_free_entries =
      ReconstructXrefTableFreeEntries(reader->free_entries());
  xref_table_entries.insert(
      xref_table_entries.end(),
      std::make_move_iterator(xref_table_free_entries.begin()),
      std::make_move_iterator(xref_table_free_entries.end()));

  ABSL_RETURN_IF_ERROR(WriteXrefTable(xref_table_entries, output));

  // Step 6: Write the trailer section, including the trailer dictionary and
  // startxref pointer.

  // Update the object count in the trailer dictionary.
  file_trailer_dict.entries[kPdfSizeKey] =
      Object{.value = Object::Integer{
                 .value = static_cast<int64_t>(xref_table_entries.size())}};
  ABSL_RETURN_IF_ERROR(
      WriteTrailer(file_trailer_dict, xref_table_offset, output));

  ABSL_ASSIGN_OR_RETURN(int64_t header_len, ComputeIndirectStreamHeaderByteSize(
                                                c2pa_manifest_store_obj));
  return c2pa_manifest_store_offset + header_len;
}

absl::Status PdfEmbedder::Embed(absl::string_view manifest_store,
                                int64_t insert_at_offset,
                                absl::Cord& embeddable_asset) const {
  absl::Cord result = embeddable_asset.Subcord(0, insert_at_offset);
  result.Append(manifest_store);
  result.Append(embeddable_asset.Subcord(
      insert_at_offset + manifest_store.size(), embeddable_asset.size()));
  embeddable_asset = std::move(result);
  return absl::OkStatus();
}
}  // namespace credentio
