// Copyright 2017 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "core/fpdfapi/parser/cpdf_object_avail.h"

#include <utility>

#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_indirect_object_holder.h"
#include "core/fpdfapi/parser/cpdf_object_walker.h"
#include "core/fpdfapi/parser/cpdf_read_validator.h"
#include "core/fpdfapi/parser/cpdf_reference.h"
#include "third_party/base/ptr_util.h"

CPDF_ObjectAvail::CPDF_ObjectAvail(
    const RetainPtr<CPDF_ReadValidator>& validator,
    CPDF_IndirectObjectHolder* holder,
    CPDF_Object* root)
    : validator_(validator), holder_(holder), root_(root) {
  ASSERT(validator_);
  ASSERT(holder);
  ASSERT(root_);
  if (!root_->IsInline())
    parsed_objnums_.insert(root_->GetObjNum());
}

CPDF_ObjectAvail::CPDF_ObjectAvail(
    const RetainPtr<CPDF_ReadValidator>& validator,
    CPDF_IndirectObjectHolder* holder,
    uint32_t obj_num)
    : validator_(validator),
      holder_(holder),
      root_(pdfium::MakeRetain<CPDF_Reference>(holder, obj_num)) {
  ASSERT(validator_);
  ASSERT(holder);
}

CPDF_ObjectAvail::~CPDF_ObjectAvail() {}

CPDF_DataAvail::DocAvailStatus CPDF_ObjectAvail::CheckAvail() {
  if (!LoadRootObject())
    return CPDF_DataAvail::DocAvailStatus::DataNotAvailable;

  if (CheckObjects()) {
    CleanMemory();
    return CPDF_DataAvail::DocAvailStatus::DataAvailable;
  }
  return CPDF_DataAvail::DocAvailStatus::DataNotAvailable;
}

bool CPDF_ObjectAvail::LoadRootObject() {
  if (!non_parsed_objects_.empty())
    return true;

  while (root_ && root_->IsReference()) {
    const uint32_t ref_obj_num = root_->AsReference()->GetRefObjNum();
    if (HasObjectParsed(ref_obj_num)) {
      root_ = nullptr;
      return true;
    }

    const CPDF_ReadValidator::Session parse_session(validator_);
    CPDF_Object* direct = holder_->GetOrParseIndirectObject(ref_obj_num);
    if (validator_->has_read_problems())
      return false;

    parsed_objnums_.insert(ref_obj_num);
    root_.Reset(direct);
  }
  std::stack<uint32_t> non_parsed_objects_in_root;
  if (AppendObjectSubRefs(root_.Get(), &non_parsed_objects_in_root)) {
    non_parsed_objects_ = std::move(non_parsed_objects_in_root);
    return true;
  }
  return false;
}

bool CPDF_ObjectAvail::CheckObjects() {
  std::set<uint32_t> checked_objects;
  std::stack<uint32_t> objects_to_check = std::move(non_parsed_objects_);
  non_parsed_objects_ = std::stack<uint32_t>();
  while (!objects_to_check.empty()) {
    const uint32_t obj_num = objects_to_check.top();
    objects_to_check.pop();

    if (HasObjectParsed(obj_num))
      continue;

    if (!checked_objects.insert(obj_num).second)
      continue;

    const CPDF_ReadValidator::Session parse_session(validator_);
    const CPDF_Object* direct = holder_->GetOrParseIndirectObject(obj_num);
    if (direct == root_)
      continue;

    if (validator_->has_read_problems() ||
        !AppendObjectSubRefs(direct, &objects_to_check)) {
      non_parsed_objects_.push(obj_num);
      continue;
    }
    parsed_objnums_.insert(obj_num);
  }
  return non_parsed_objects_.empty();
}

bool CPDF_ObjectAvail::AppendObjectSubRefs(const CPDF_Object* object,
                                           std::stack<uint32_t>* refs) const {
  ASSERT(refs);
  if (!object)
    return true;

  CPDF_ObjectWalker walker(object);
  while (const CPDF_Object* obj = walker.GetNext()) {
    const CPDF_ReadValidator::Session parse_session(validator_);

    // Skip if this object if it's an inlined root, the parent object or
    // explicitily excluded.
    const bool skip = (walker.GetParent() && obj == root_) ||
                      walker.dictionary_key() == "Parent" ||
                      (obj != root_ && ExcludeObject(obj));

    // We need to parse the object before we can do the exclusion check.
    // This is because the exclusion check may check against a referenced
    // field of the object which we need to make sure is loaded.
    if (validator_->has_read_problems())
      return false;

    if (skip) {
      walker.SkipWalkIntoCurrentObject();
      continue;
    }

    if (obj->IsReference())
      refs->push(obj->AsReference()->GetRefObjNum());
  }
  return true;
}

void CPDF_ObjectAvail::CleanMemory() {
  root_.Reset();
  parsed_objnums_.clear();
}

bool CPDF_ObjectAvail::ExcludeObject(const CPDF_Object* object) const {
  return false;
}

bool CPDF_ObjectAvail::HasObjectParsed(uint32_t obj_num) const {
  return parsed_objnums_.count(obj_num) > 0;
}
