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

#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <utility>

#include "absl/base/nullability.h"
#include "absl/container/btree_map.h"
#include "absl/container/btree_set.h"
#include "absl/container/flat_hash_set.h"
#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/substitute.h"
#include "formats/pdf/object_reader.h"
#include "formats/pdf/objects.h"
#include "re2/re2.h"
#include "riegeli/bytes/reader.h"

namespace credentio {
namespace {

// Matches the cross-reference table offset in the trailer. See ISO 32000-2
// Section 7.5.5. Any run of white-space is accepted around the offset: this
// covers CR LF end-of-line markers (Section 7.2.3), and readers may treat
// end-of-line markers like other white-space.
static constexpr LazyRE2 kXrefOffsetPattern = {R"(startxref\s+(\d+)\s+%%EOF)"};

// Matches a single cross-reference entry in the cross-reference table. See ISO
// 32000-2 Section 7.5.4
static constexpr LazyRE2 kXrefEntryPattern = {
    R"(^(\d{10}) (\d{5}) ([nf])(?: \r| \n|\r\n))"};

// Reads the first cross-reference table offset from the file trailer.
absl::StatusOr<uint64_t> GetFirstXrefTableOffset(riegeli::Reader& input) {
  // Scan the last 30 bytes for the cross-reference table offset. This allows
  // for the "startxref" keyword and an offset value large enough for a
  // multi-terabyte file.
  if (!input.Seek(input.Size().value_or(30) - 30)) {
    return input.StatusOrAnnotate(
        absl::DataLossError("Failed to seek to offset"));
  }

  std::string buffer;
  if (!input.Read(30, buffer)) {
    return input.StatusOrAnnotate(absl::DataLossError("Failed to read buffer"));
  }
  uint64_t offset;
  if (!RE2::PartialMatch(buffer, *kXrefOffsetPattern, &offset)) {
    return absl::InvalidArgumentError(
        absl::StrCat("Failed to find cross-reference table offset in the "
                     "following payload: ",
                     buffer));
  }
  return offset;
}

// Reads the offset to the next cross-reference table from the file trailer.
// Returns `std::nullopt` if the file trailer dictionary does not contain a
// "Prev" entry.
absl::StatusOr<std::optional<uint64_t>> GetPrevXrefTableOffset(
    const Object::Dictionary& file_trailer_dict) {
  if (const auto it = file_trailer_dict.entries.find("Prev");
      it != file_trailer_dict.entries.end()) {
    ABSL_ASSIGN_OR_RETURN(const auto prev_xref_offset,
                          Object::As<Object::Integer>(it->second));
    return prev_xref_offset.value;
  }
  return std::nullopt;
}

// Reads the standard cross-reference table and the file trailer from the input
// stream at the given offset.
absl::Status ReadXrefTableAndTrailer(
    riegeli::Reader& input, uint64_t xref_offset,
    absl::btree_map<Object::IndirectReference, uint64_t>& xref_table,
    absl::btree_set<Object::IndirectReference>& free_entries,
    Object::Dictionary& file_trailer_dict) {
  if (!input.Seek(xref_offset)) {
    return input.StatusOrAnnotate(
        absl::DataLossError("Failed to seek to offset"));
  }

  std::string buffer;
  if (!input.Read(4, buffer)) {
    return input.StatusOrAnnotate(absl::DataLossError("Failed to read buffer"));
  }
  if (buffer != "xref") {
    return absl::InvalidArgumentError(
        absl::StrCat("Malformed cross-reference table. Expected 'xref' but got "
                     "'",
                     buffer, "'"));
  }
  while (true) {
    ABSL_RETURN_IF_ERROR(SkipOverWhiteSpaces(input));
    if (!input.Read(7, buffer)) {
      return input.StatusOrAnnotate(
          absl::DataLossError("Failed to read buffer"));
    }
    if (buffer == "trailer") {
      break;
    }
    if (!input.Seek(input.pos() - 7)) {
      return input.StatusOrAnnotate(
          absl::DataLossError("Failed to seek to offset"));
    }

    Object int_obj;
    ABSL_RETURN_IF_ERROR(ReadObject(input, input.pos(), int_obj));
    ABSL_ASSIGN_OR_RETURN(const auto obj_num,
                          Object::As<Object::Integer>(int_obj));

    ABSL_RETURN_IF_ERROR(ReadObject(input, input.pos(), int_obj));
    ABSL_ASSIGN_OR_RETURN(const auto obj_count,
                          Object::As<Object::Integer>(int_obj));

    ABSL_RETURN_IF_ERROR(SkipOverWhiteSpaces(input));

    for (uint32_t i = 0; i < obj_count.value; ++i) {
      // Each cross-reference entry is expected to be exactly 20 bytes long.
      if (!input.Read(20, buffer)) {
        return input.StatusOrAnnotate(
            absl::DataLossError("Failed to read buffer"));
      }
      uint64_t obj_offset;
      uint32_t gen_num;
      std::string type;
      if (RE2::PartialMatch(buffer, *kXrefEntryPattern, &obj_offset, &gen_num,
                            &type)) {
        auto xref_entry_key = Object::IndirectReference{
            .object_number = static_cast<uint32_t>(obj_num.value + i),
            .generation_number = gen_num};
        if (type == "n") {  // 'n' represents an in-use entry.
          xref_table.insert({xref_entry_key, obj_offset});
        } else {  // 'f' represents a free entry.
          free_entries.insert(xref_entry_key);
        }
      } else {
        return absl::InvalidArgumentError(
            absl::StrCat("Failed to parse cross-reference table entry. Invalid "
                         "value: ",
                         buffer));
      }
    }
  }
  Object dict_obj;
  ABSL_RETURN_IF_ERROR(ReadObject(input, input.pos(), dict_obj));
  ABSL_ASSIGN_OR_RETURN(file_trailer_dict,
                        Object::As<Object::Dictionary>(dict_obj));

  return absl::OkStatus();
}

// Returns an error if `obj`, read at `offset`, is not the object `ref` that the
// cross-reference table lists at that offset.
absl::Status CheckObjectHeader(const IndirectObject& obj,
                               const Object::IndirectReference& ref,
                               uint64_t offset) {
  if (obj.object_number != ref.object_number ||
      obj.generation_number != ref.generation_number) {
    return absl::InvalidArgumentError(absl::Substitute(
        "Object mismatch at offset $0: the cross-reference table expects "
        "object $1 $2 but found object $3 $4",
        offset, ref.object_number, ref.generation_number, obj.object_number,
        obj.generation_number));
  }
  return absl::OkStatus();
}
}  // namespace

absl::StatusOr<std::unique_ptr<PdfReader>> PdfReader::Create(
    riegeli::Reader* absl_nonnull input) {
  if (input == nullptr) {
    return absl::InvalidArgumentError("input cannot be null");
  }
  absl::flat_hash_set<uint64_t> xref_offsets_visited;
  ABSL_ASSIGN_OR_RETURN(uint64_t xref_offset, GetFirstXrefTableOffset(*input));
  xref_offsets_visited.insert(xref_offset);

  absl::btree_map<Object::IndirectReference, uint64_t> xref_table;
  absl::btree_set<Object::IndirectReference> free_entries;
  Object::Dictionary file_trailer_dict;
  ABSL_RETURN_IF_ERROR(ReadXrefTableAndTrailer(
      *input, xref_offset, xref_table, free_entries, file_trailer_dict));

  ABSL_ASSIGN_OR_RETURN(std::optional<uint64_t> prev_xref_offset,
                        GetPrevXrefTableOffset(file_trailer_dict));
  while (prev_xref_offset.has_value()) {
    if (xref_offsets_visited.contains(*prev_xref_offset)) {
      return absl::InvalidArgumentError(
          "Initialization failed: Circular cross-reference table detected.");
    }
    xref_offsets_visited.insert(*prev_xref_offset);

    absl::btree_map<Object::IndirectReference, uint64_t> prev_xref_table;
    absl::btree_set<Object::IndirectReference> prev_free_entries;
    Object::Dictionary prev_file_trailer_dict;
    ABSL_RETURN_IF_ERROR(
        ReadXrefTableAndTrailer(*input, *prev_xref_offset, prev_xref_table,
                                prev_free_entries, prev_file_trailer_dict));
    ABSL_ASSIGN_OR_RETURN(prev_xref_offset,
                          GetPrevXrefTableOffset(prev_file_trailer_dict));

    // Xref tables are traversed backwards (newest to oldest via /Prev),
    // entries encountered earlier represent newer updates and override older
    // ones.
    for (const auto& [ref, offset] : prev_xref_table) {
      if (!free_entries.contains(ref)) {
        xref_table.try_emplace(ref, offset);
      }
    }
    for (const auto& ref : prev_free_entries) {
      if (!xref_table.contains(ref)) {
        free_entries.insert(ref);
      }
    }
  }
  auto reader = absl::WrapUnique(new PdfReader(input, std::move(xref_table),
                                               std::move(free_entries),
                                               std::move(file_trailer_dict)));
  return reader;
}

bool PdfReader::HasNext() { return current_it_ != xref_table_.end(); }

absl::StatusOr<IndirectObject> PdfReader::Next() {
  if (!HasNext()) {
    return absl::OutOfRangeError("No more objects to read.");
  }
  IndirectObject obj;
  if (absl::Status status = ReadIndirectObject(
          input_, current_it_->second,
          [this](const Object::IndirectReference& ref) {
            return this->GetObject(ref.object_number, ref.generation_number);
          },
          obj);
      !status.ok()) {
    return status;
  }
  ABSL_RETURN_IF_ERROR(
      CheckObjectHeader(obj, current_it_->first, current_it_->second));
  ++current_it_;
  return obj;
}

absl::StatusOr<uint64_t> PdfReader::GetObjectOffset(
    uint32_t object_number, uint32_t generation_number) {
  auto it = xref_table_.find(Object::IndirectReference{
      .object_number = object_number, .generation_number = generation_number});
  if (it == xref_table_.end()) {
    return absl::NotFoundError(absl::Substitute(
        "No offset found for object number: $0, generation number: $1",
        object_number, generation_number));
  }
  return it->second;
}

absl::StatusOr<IndirectObject> PdfReader::GetObject(
    uint32_t object_number, uint32_t generation_number) {
  Object::IndirectReference ref{.object_number = object_number,
                                .generation_number = generation_number};
  if (active_objects_.contains(ref)) {
    return absl::InvalidArgumentError(
        absl::StrCat("Circular reference detected for object: ", object_number,
                     " ", generation_number));
  }

  struct ActiveObjectGuard {
    absl::btree_set<Object::IndirectReference>& active_objects;
    Object::IndirectReference ref;
    ~ActiveObjectGuard() { active_objects.erase(ref); }
  };
  active_objects_.insert(ref);
  ActiveObjectGuard guard{active_objects_, ref};

  ABSL_ASSIGN_OR_RETURN(uint64_t offset,
                        GetObjectOffset(object_number, generation_number));
  IndirectObject obj;
  if (absl::Status status = ReadIndirectObject(
          input_, offset,
          [this](const Object::IndirectReference& ref) {
            return this->GetObject(ref.object_number, ref.generation_number);
          },
          obj);
      !status.ok()) {
    return status;
  }
  ABSL_RETURN_IF_ERROR(CheckObjectHeader(obj, ref, offset));
  return obj;
}

}  // namespace credentio
