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

#include <set>

#include "core/fpdfapi/parser/cpdf_name.h"
#include "core/fpdfapi/parser/cpdf_number.h"
#include "core/fpdfapi/parser/cpdf_reference.h"
#include "core/fpdfapi/parser/cpdf_stream.h"
#include "core/fpdfapi/parser/cpdf_string.h"
#include "third_party/base/logging.h"
#include "third_party/base/stl_util.h"

CPDF_Array::CPDF_Array() {}

CPDF_Array::~CPDF_Array() {
  // Mark the object as deleted so that it will not be deleted again
  // in case of cyclic references, then break cycles.
  m_ObjNum = kInvalidObjNum;
  for (auto& it : m_Objects) {
    if (it && it->GetObjNum() == kInvalidObjNum)
      it.release();
  }
}

CPDF_Object::Type CPDF_Array::GetType() const {
  return ARRAY;
}

bool CPDF_Array::IsArray() const {
  return true;
}

CPDF_Array* CPDF_Array::AsArray() {
  return this;
}

const CPDF_Array* CPDF_Array::AsArray() const {
  return this;
}

CPDF_Object* CPDF_Array::Clone() const {
  return CloneObjectNonCyclic(false);
}

CPDF_Object* CPDF_Array::CloneNonCyclic(
    bool bDirect,
    std::set<const CPDF_Object*>* pVisited) const {
  pVisited->insert(this);
  CPDF_Array* pCopy = new CPDF_Array();
  for (const auto& pObj : m_Objects) {
    if (!pdfium::ContainsKey(*pVisited, pObj.get())) {
      pCopy->m_Objects.push_back(
          UniqueObject(pObj->CloneNonCyclic(bDirect, pVisited)));
    }
  }
  return pCopy;
}

CFX_FloatRect CPDF_Array::GetRect() {
  CFX_FloatRect rect;
  if (!IsArray() || m_Objects.size() != 4)
    return rect;

  rect.left = GetNumberAt(0);
  rect.bottom = GetNumberAt(1);
  rect.right = GetNumberAt(2);
  rect.top = GetNumberAt(3);
  return rect;
}

CFX_Matrix CPDF_Array::GetMatrix() {
  CFX_Matrix matrix;
  if (!IsArray() || m_Objects.size() != 6)
    return matrix;

  matrix.Set(GetNumberAt(0), GetNumberAt(1), GetNumberAt(2), GetNumberAt(3),
             GetNumberAt(4), GetNumberAt(5));
  return matrix;
}

CPDF_Object* CPDF_Array::GetObjectAt(size_t i) const {
  if (i >= m_Objects.size())
    return nullptr;
  return m_Objects[i].get();
}

CPDF_Object* CPDF_Array::GetDirectObjectAt(size_t i) const {
  if (i >= m_Objects.size())
    return nullptr;
  return m_Objects[i]->GetDirect();
}

CFX_ByteString CPDF_Array::GetStringAt(size_t i) const {
  if (i >= m_Objects.size())
    return CFX_ByteString();
  return m_Objects[i]->GetString();
}

int CPDF_Array::GetIntegerAt(size_t i) const {
  if (i >= m_Objects.size())
    return 0;
  return m_Objects[i]->GetInteger();
}

FX_FLOAT CPDF_Array::GetNumberAt(size_t i) const {
  if (i >= m_Objects.size())
    return 0;
  return m_Objects[i]->GetNumber();
}

CPDF_Dictionary* CPDF_Array::GetDictAt(size_t i) const {
  CPDF_Object* p = GetDirectObjectAt(i);
  if (!p)
    return nullptr;
  if (CPDF_Dictionary* pDict = p->AsDictionary())
    return pDict;
  if (CPDF_Stream* pStream = p->AsStream())
    return pStream->GetDict();
  return nullptr;
}

CPDF_Stream* CPDF_Array::GetStreamAt(size_t i) const {
  return ToStream(GetDirectObjectAt(i));
}

CPDF_Array* CPDF_Array::GetArrayAt(size_t i) const {
  return ToArray(GetDirectObjectAt(i));
}

void CPDF_Array::RemoveAt(size_t i, size_t nCount) {
  if (i >= m_Objects.size())
    return;

  if (nCount <= 0 || nCount > m_Objects.size() - i)
    return;

  auto it = m_Objects.begin() + i;
  m_Objects.erase(it, it + nCount);
}

void CPDF_Array::ConvertToIndirectObjectAt(size_t i,
                                           CPDF_IndirectObjectHolder* pHolder) {
  if (i >= m_Objects.size())
    return;

  if (!m_Objects[i] || m_Objects[i]->IsReference())
    return;

  CPDF_Object* pUnowned = pHolder->AddIndirectObject(std::move(m_Objects[i]));
  m_Objects[i] =
      UniqueObject(new CPDF_Reference(pHolder, pUnowned->GetObjNum()));
}

void CPDF_Array::SetAt(size_t i, CPDF_Object* pObj) {
  ASSERT(IsArray());
  CHECK(!pObj || pObj->IsInline());
  if (i >= m_Objects.size()) {
    ASSERT(false);
    return;
  }
  m_Objects[i] = UniqueObject(pObj);
}

void CPDF_Array::InsertAt(size_t index, CPDF_Object* pObj) {
  ASSERT(IsArray());
  CHECK(!pObj || pObj->IsInline());
  if (index >= m_Objects.size()) {
    // Allocate space first.
    m_Objects.resize(index + 1);
    m_Objects[index] = UniqueObject(pObj);
  } else {
    // Directly insert.
    m_Objects.insert(m_Objects.begin() + index, UniqueObject(pObj));
  }
}

void CPDF_Array::Add(CPDF_Object* pObj) {
  ASSERT(IsArray());
  CHECK(!pObj || pObj->IsInline());
  m_Objects.push_back(UniqueObject(pObj));
}

void CPDF_Array::AddName(const CFX_ByteString& str) {
  Add(new CPDF_Name(str));
}

void CPDF_Array::AddString(const CFX_ByteString& str) {
  Add(new CPDF_String(str, FALSE));
}

void CPDF_Array::AddInteger(int i) {
  Add(new CPDF_Number(i));
}

void CPDF_Array::AddNumber(FX_FLOAT f) {
  Add(new CPDF_Number(f));
}

void CPDF_Array::AddReference(CPDF_IndirectObjectHolder* pDoc,
                              uint32_t objnum) {
  Add(new CPDF_Reference(pDoc, objnum));
}

void CPDF_Array::AddReference(CPDF_IndirectObjectHolder* pDoc,
                              const CPDF_Object* pObj) {
  AddReference(pDoc, pObj->GetObjNum());
}
