// Copyright 2016 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.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

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

#include <algorithm>
#include <utility>

#include "core/fpdfapi/parser/cpdf_object.h"
#include "core/fpdfapi/parser/cpdf_parser.h"
#include "third_party/base/logging.h"

namespace {

CPDF_Object* FilterInvalidObjNum(CPDF_Object* obj) {
  return obj && obj->GetObjNum() != CPDF_Object::kInvalidObjNum ? obj : nullptr;
}

}  // namespace

CPDF_IndirectObjectHolder::CPDF_IndirectObjectHolder()
    : m_LastObjNum(0),
      m_pByteStringPool(pdfium::MakeUnique<CFX_ByteStringPool>()) {}

CPDF_IndirectObjectHolder::~CPDF_IndirectObjectHolder() {
  m_pByteStringPool.DeleteObject();  // Make weak.
}

CPDF_Object* CPDF_IndirectObjectHolder::GetIndirectObject(
    uint32_t objnum) const {
  auto it = m_IndirectObjs.find(objnum);
  return (it != m_IndirectObjs.end()) ? FilterInvalidObjNum(it->second.get())
                                      : nullptr;
}

CPDF_Object* CPDF_IndirectObjectHolder::GetOrParseIndirectObject(
    uint32_t objnum) {
  if (objnum == 0 || objnum == CPDF_Object::kInvalidObjNum)
    return nullptr;

  // Add item anyway to prevent recursively parsing of same object.
  auto insert_result = m_IndirectObjs.insert(std::make_pair(objnum, nullptr));
  if (!insert_result.second)
    return FilterInvalidObjNum(insert_result.first->second.get());

  std::unique_ptr<CPDF_Object> pNewObj = ParseIndirectObject(objnum);
  if (!pNewObj) {
    m_IndirectObjs.erase(insert_result.first);
    return nullptr;
  }

  pNewObj->m_ObjNum = objnum;
  m_LastObjNum = std::max(m_LastObjNum, objnum);
  insert_result.first->second = std::move(pNewObj);
  return insert_result.first->second.get();
}

std::unique_ptr<CPDF_Object> CPDF_IndirectObjectHolder::ParseIndirectObject(
    uint32_t objnum) {
  return nullptr;
}

CPDF_Object* CPDF_IndirectObjectHolder::AddIndirectObject(
    std::unique_ptr<CPDF_Object> pObj) {
  CHECK(!pObj->m_ObjNum);
  pObj->m_ObjNum = ++m_LastObjNum;

  auto& obj_holder = m_IndirectObjs[m_LastObjNum];
  if (obj_holder)
    m_OrphanObjs.push_back(std::move(obj_holder));

  obj_holder = std::move(pObj);
  return obj_holder.get();
}

bool CPDF_IndirectObjectHolder::ReplaceIndirectObjectIfHigherGeneration(
    uint32_t objnum,
    std::unique_ptr<CPDF_Object> pObj) {
  ASSERT(objnum);
  if (!pObj || objnum == CPDF_Object::kInvalidObjNum)
    return false;

  auto& obj_holder = m_IndirectObjs[objnum];

  const CPDF_Object* old_object = FilterInvalidObjNum(obj_holder.get());

  if (old_object && pObj->GetGenNum() <= old_object->GetGenNum())
    return false;

  pObj->m_ObjNum = objnum;
  if (obj_holder)
    m_OrphanObjs.push_back(std::move(obj_holder));

  obj_holder = std::move(pObj);
  m_LastObjNum = std::max(m_LastObjNum, objnum);
  return true;
}

void CPDF_IndirectObjectHolder::DeleteIndirectObject(uint32_t objnum) {
  auto it = m_IndirectObjs.find(objnum);
  if (it == m_IndirectObjs.end() || !FilterInvalidObjNum(it->second.get()))
    return;

  m_IndirectObjs.erase(it);
}
