// 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

#ifndef CORE_FPDFAPI_PARSER_CPDF_ARRAY_H_
#define CORE_FPDFAPI_PARSER_CPDF_ARRAY_H_

#include <memory>
#include <set>
#include <type_traits>
#include <utility>
#include <vector>

#include "core/fpdfapi/parser/cpdf_indirect_object_holder.h"
#include "core/fpdfapi/parser/cpdf_object.h"
#include "core/fxcrt/fx_coordinates.h"
#include "third_party/base/ptr_util.h"

class CPDF_Array : public CPDF_Object {
 public:
  using const_iterator =
      std::vector<std::unique_ptr<CPDF_Object>>::const_iterator;

  CPDF_Array();
  explicit CPDF_Array(const CFX_WeakPtr<ByteStringPool>& pPool);
  ~CPDF_Array() override;

  // CPDF_Object:
  Type GetType() const override;
  std::unique_ptr<CPDF_Object> Clone() const override;
  bool IsArray() const override;
  CPDF_Array* AsArray() override;
  const CPDF_Array* AsArray() const override;
  bool WriteTo(IFX_ArchiveStream* archive) const override;

  bool IsEmpty() const { return m_Objects.empty(); }
  size_t GetCount() const { return m_Objects.size(); }
  CPDF_Object* GetObjectAt(size_t index) const;
  CPDF_Object* GetDirectObjectAt(size_t index) const;
  ByteString GetStringAt(size_t index) const;
  WideString GetUnicodeTextAt(size_t index) const;
  int GetIntegerAt(size_t index) const;
  float GetNumberAt(size_t index) const;
  CPDF_Dictionary* GetDictAt(size_t index) const;
  CPDF_Stream* GetStreamAt(size_t index) const;
  CPDF_Array* GetArrayAt(size_t index) const;
  float GetFloatAt(size_t index) const { return GetNumberAt(index); }
  CFX_Matrix GetMatrix();
  CFX_FloatRect GetRect();

  // Takes ownership of |pObj|, returns unowned pointer to it.
  CPDF_Object* Add(std::unique_ptr<CPDF_Object> pObj);
  CPDF_Object* SetAt(size_t index, std::unique_ptr<CPDF_Object> pObj);
  CPDF_Object* InsertAt(size_t index, std::unique_ptr<CPDF_Object> pObj);

  // Creates object owned by the array, returns unowned pointer to it.
  // We have special cases for objects that can intern strings from
  // a ByteStringPool.
  template <typename T, typename... Args>
  typename std::enable_if<!CanInternStrings<T>::value, T*>::type AddNew(
      Args&&... args) {
    return static_cast<T*>(
        Add(pdfium::MakeUnique<T>(std::forward<Args>(args)...)));
  }
  template <typename T, typename... Args>
  typename std::enable_if<CanInternStrings<T>::value, T*>::type AddNew(
      Args&&... args) {
    return static_cast<T*>(
        Add(pdfium::MakeUnique<T>(m_pPool, std::forward<Args>(args)...)));
  }
  template <typename T, typename... Args>
  typename std::enable_if<!CanInternStrings<T>::value, T*>::type SetNewAt(
      size_t index,
      Args&&... args) {
    return static_cast<T*>(
        SetAt(index, pdfium::MakeUnique<T>(std::forward<Args>(args)...)));
  }
  template <typename T, typename... Args>
  typename std::enable_if<CanInternStrings<T>::value, T*>::type SetNewAt(
      size_t index,
      Args&&... args) {
    return static_cast<T*>(SetAt(
        index, pdfium::MakeUnique<T>(m_pPool, std::forward<Args>(args)...)));
  }
  template <typename T, typename... Args>
  typename std::enable_if<!CanInternStrings<T>::value, T*>::type InsertNewAt(
      size_t index,
      Args&&... args) {
    return static_cast<T*>(
        InsertAt(index, pdfium::MakeUnique<T>(std::forward<Args>(args)...)));
  }
  template <typename T, typename... Args>
  typename std::enable_if<CanInternStrings<T>::value, T*>::type InsertNewAt(
      size_t index,
      Args&&... args) {
    return static_cast<T*>(InsertAt(
        index, pdfium::MakeUnique<T>(m_pPool, std::forward<Args>(args)...)));
  }

  void Clear();
  void RemoveAt(size_t index);
  void ConvertToIndirectObjectAt(size_t index, CPDF_IndirectObjectHolder* pDoc);

  const_iterator begin() const { return m_Objects.begin(); }
  const_iterator end() const { return m_Objects.end(); }

 protected:
  std::unique_ptr<CPDF_Object> CloneNonCyclic(
      bool bDirect,
      std::set<const CPDF_Object*>* pVisited) const override;

  std::vector<std::unique_ptr<CPDF_Object>> m_Objects;
  CFX_WeakPtr<ByteStringPool> m_pPool;
};

inline CPDF_Array* ToArray(CPDF_Object* obj) {
  return obj ? obj->AsArray() : nullptr;
}

inline const CPDF_Array* ToArray(const CPDF_Object* obj) {
  return obj ? obj->AsArray() : nullptr;
}

inline std::unique_ptr<CPDF_Array> ToArray(std::unique_ptr<CPDF_Object> obj) {
  CPDF_Array* pArray = ToArray(obj.get());
  if (!pArray)
    return nullptr;
  obj.release();
  return std::unique_ptr<CPDF_Array>(pArray);
}

#endif  // CORE_FPDFAPI_PARSER_CPDF_ARRAY_H_
