// Copyright 2018 The PDFium Authors
// 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_cross_ref_table.h"

#include <utility>

#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_parser.h"
#include "core/fxcrt/check_op.h"
#include "core/fxcrt/containers/contains.h"

// static
std::unique_ptr<CPDF_CrossRefTable> CPDF_CrossRefTable::MergeUp(
    std::unique_ptr<CPDF_CrossRefTable> current,
    std::unique_ptr<CPDF_CrossRefTable> top) {
  if (!current)
    return top;

  if (!top)
    return current;

  current->Update(std::move(top));
  return current;
}

CPDF_CrossRefTable::CPDF_CrossRefTable() = default;

CPDF_CrossRefTable::CPDF_CrossRefTable(RetainPtr<CPDF_Dictionary> trailer,
                                       uint32_t trailer_object_number)
    : trailer_(std::move(trailer)),
      trailer_object_number_(trailer_object_number) {}

CPDF_CrossRefTable::~CPDF_CrossRefTable() = default;

void CPDF_CrossRefTable::AddCompressed(uint32_t obj_num,
                                       uint32_t archive_obj_num,
                                       uint32_t archive_obj_index) {
  CHECK_LT(obj_num, CPDF_Parser::kMaxObjectNumber);
  CHECK_LT(archive_obj_num, CPDF_Parser::kMaxObjectNumber);

  auto& info = objects_info_[obj_num];
  if (info.gennum > 0)
    return;

  // Don't add known object streams to object streams.
  if (info.is_object_stream_flag) {
    return;
  }

  info.type = ObjectType::kCompressed;
  info.archive.obj_num = archive_obj_num;
  info.archive.obj_index = archive_obj_index;
  info.gennum = 0;

  objects_info_[archive_obj_num].is_object_stream_flag = true;
}

void CPDF_CrossRefTable::AddNormal(uint32_t obj_num,
                                   uint16_t gen_num,
                                   bool is_object_stream,
                                   FX_FILESIZE pos) {
  CHECK_LT(obj_num, CPDF_Parser::kMaxObjectNumber);

  auto& info = objects_info_[obj_num];
  if (info.gennum > gen_num)
    return;

  info.type = ObjectType::kNormal;
  info.is_object_stream_flag |= is_object_stream;
  info.gennum = gen_num;
  info.pos = pos;
}

void CPDF_CrossRefTable::SetFree(uint32_t obj_num) {
  CHECK_LT(obj_num, CPDF_Parser::kMaxObjectNumber);

  auto& info = objects_info_[obj_num];
  info.type = ObjectType::kFree;
  info.gennum = 0xFFFF;
  info.pos = 0;
}

void CPDF_CrossRefTable::SetTrailer(RetainPtr<CPDF_Dictionary> trailer,
                                    uint32_t trailer_object_number) {
  trailer_ = std::move(trailer);
  trailer_object_number_ = trailer_object_number;
}

const CPDF_CrossRefTable::ObjectInfo* CPDF_CrossRefTable::GetObjectInfo(
    uint32_t obj_num) const {
  const auto it = objects_info_.find(obj_num);
  return it != objects_info_.end() ? &it->second : nullptr;
}

void CPDF_CrossRefTable::Update(
    std::unique_ptr<CPDF_CrossRefTable> new_cross_ref) {
  UpdateInfo(std::move(new_cross_ref->objects_info_));
  UpdateTrailer(std::move(new_cross_ref->trailer_));
}

void CPDF_CrossRefTable::SetObjectMapSize(uint32_t size) {
  if (size == 0) {
    objects_info_.clear();
    return;
  }

  objects_info_.erase(objects_info_.lower_bound(size), objects_info_.end());

  if (!pdfium::Contains(objects_info_, size - 1)) {
    objects_info_[size - 1].pos = 0;
  }
}

void CPDF_CrossRefTable::UpdateInfo(
    std::map<uint32_t, ObjectInfo> new_objects_info) {
  if (new_objects_info.empty()) {
    return;
  }

  if (objects_info_.empty()) {
    objects_info_ = std::move(new_objects_info);
    return;
  }

  auto cur_it = objects_info_.begin();
  auto new_it = new_objects_info.begin();
  while (cur_it != objects_info_.end() && new_it != new_objects_info.end()) {
    if (cur_it->first == new_it->first) {
      if (new_it->second.type == ObjectType::kNormal &&
          cur_it->second.type == ObjectType::kNormal &&
          cur_it->second.is_object_stream_flag) {
        new_it->second.is_object_stream_flag = true;
      }
      ++cur_it;
      ++new_it;
    } else if (cur_it->first < new_it->first) {
      new_objects_info.insert(new_it, *cur_it);
      ++cur_it;
    } else {
      new_it = new_objects_info.lower_bound(cur_it->first);
    }
  }
  for (; cur_it != objects_info_.end(); ++cur_it) {
    new_objects_info.insert(new_objects_info.end(), *cur_it);
  }
  objects_info_ = std::move(new_objects_info);
}

void CPDF_CrossRefTable::UpdateTrailer(RetainPtr<CPDF_Dictionary> new_trailer) {
  if (!new_trailer)
    return;

  if (!trailer_) {
    trailer_ = std::move(new_trailer);
    return;
  }

  new_trailer->SetFor("XRefStm", trailer_->RemoveFor("XRefStm"));
  new_trailer->SetFor("Prev", trailer_->RemoveFor("Prev"));

  for (const auto& key : new_trailer->GetKeys())
    trailer_->SetFor(key, new_trailer->RemoveFor(key.AsStringView()));
}
