// Copyright 2017 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_object_walker.h"

#include <sstream>
#include <string>
#include <utility>

#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_boolean.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_name.h"
#include "core/fpdfapi/parser/cpdf_null.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 "testing/gtest/include/gtest/gtest.h"

namespace {

std::string Walk(RetainPtr<CPDF_Object> object) {
  std::ostringstream result;
  CPDF_ObjectWalker walker(std::move(object));
  while (RetainPtr<const CPDF_Object> obj = walker.GetNext()) {
    if (obj->IsDictionary())
      result << " Dict";
    else if (obj->IsArray())
      result << " Arr";
    else if (obj->IsString())
      result << " Str";
    else if (obj->IsBoolean())
      result << " Bool";
    else if (obj->IsStream())
      result << " Stream";
    else if (obj->IsReference())
      result << " Ref";
    else if (obj->IsNumber())
      result << " Num";
    else if (obj->IsNull())
      result << " Null";
    else
      result << " Unknown";
  }
  std::string result_str = result.str();
  if (!result_str.empty()) {
    result_str.erase(result_str.begin());  // remove start space
  }
  return result_str;
}

}  // namespace

TEST(ObjectWalkerTest, Simple) {
  EXPECT_EQ(Walk(pdfium::MakeRetain<CPDF_Null>()), "Null");
  EXPECT_EQ(Walk(pdfium::MakeRetain<CPDF_Dictionary>()), "Dict");
  EXPECT_EQ(Walk(pdfium::MakeRetain<CPDF_Array>()), "Arr");
  EXPECT_EQ(Walk(pdfium::MakeRetain<CPDF_String>()), "Str");
  EXPECT_EQ(Walk(pdfium::MakeRetain<CPDF_Boolean>()), "Bool");
  EXPECT_EQ(Walk(pdfium::MakeRetain<CPDF_Stream>(
                pdfium::MakeRetain<CPDF_Dictionary>())),
            "Stream Dict Num");
  EXPECT_EQ(Walk(pdfium::MakeRetain<CPDF_Reference>(nullptr, 0)), "Ref");
}

TEST(ObjectWalkerTest, CombinedObject) {
  CPDF_IndirectObjectHolder holder;
  auto dict = pdfium::MakeRetain<CPDF_Dictionary>();
  dict->SetFor("1", pdfium::MakeRetain<CPDF_String>());
  dict->SetFor("2", pdfium::MakeRetain<CPDF_Boolean>());
  auto array = pdfium::MakeRetain<CPDF_Array>();
  array->Append(pdfium::MakeRetain<CPDF_Reference>(nullptr, 0));
  array->Append(pdfium::MakeRetain<CPDF_Null>());
  auto stream =
      holder.NewIndirect<CPDF_Stream>(pdfium::MakeRetain<CPDF_Dictionary>());
  ASSERT_TRUE(stream);
  const uint32_t stream_object_number = stream->GetObjNum();
  ASSERT_GT(stream_object_number, 0u);
  array->Append(
      pdfium::MakeRetain<CPDF_Reference>(&holder, stream_object_number));
  dict->SetFor("3", std::move(array));
  EXPECT_EQ(Walk(dict), "Dict Str Bool Arr Ref Null Ref");
}

TEST(ObjectWalkerTest, GetParent) {
  CPDF_IndirectObjectHolder holder;
  auto level_4 = pdfium::MakeRetain<CPDF_Number>(0);
  auto level_3 = pdfium::MakeRetain<CPDF_Dictionary>();
  level_3->SetFor("Length", std::move(level_4));
  auto level_2 = holder.NewIndirect<CPDF_Stream>(std::move(level_3));
  ASSERT_TRUE(level_2);
  const uint32_t level_2_object_number = level_2->GetObjNum();
  ASSERT_GT(level_2_object_number, 0u);
  auto level_1 = pdfium::MakeRetain<CPDF_Array>();
  level_1->Append(
      pdfium::MakeRetain<CPDF_Reference>(&holder, level_2_object_number));
  auto level_0 = pdfium::MakeRetain<CPDF_Dictionary>();
  level_0->SetFor("Array", std::move(level_1));

  // We have <</Array [ stream( << /Length 0 >>) ]>>
  // In this case each step will increase depth.
  // And on each step the prev object should be parent for current.
  RetainPtr<const CPDF_Object> cur_parent;
  CPDF_ObjectWalker walker(level_0);
  while (RetainPtr<const CPDF_Object> obj = walker.GetNext()) {
    EXPECT_EQ(cur_parent, walker.GetParent());
    cur_parent = std::move(obj);
  }
}

TEST(ObjectWalkerTest, SkipWalkIntoCurrentObject) {
  auto root_array = pdfium::MakeRetain<CPDF_Array>();
  // Add 2 null objects into |root_array|. [ null1, null2 ]
  root_array->AppendNew<CPDF_Null>();
  root_array->AppendNew<CPDF_Null>();
  // |root_array| will contain 4 null objects after this.
  // [ null1, null2, [ null3, null4 ] ]
  root_array->Append(root_array->Clone());

  int non_array_objects = 0;
  CPDF_ObjectWalker walker(root_array);
  while (RetainPtr<const CPDF_Object> obj = walker.GetNext()) {
    if (obj != root_array && obj->IsArray()) {
      // skip other array except root.
      walker.SkipWalkIntoCurrentObject();
    }
    if (!obj->IsArray())
      ++non_array_objects;
  }
  // 2 objects from child array should be skipped.
  EXPECT_EQ(2, non_array_objects);
}

TEST(ObjectWalkerTest, DictionaryKey) {
  auto dict = pdfium::MakeRetain<CPDF_Dictionary>();
  dict->SetFor("1", pdfium::MakeRetain<CPDF_Null>());
  dict->SetFor("2", pdfium::MakeRetain<CPDF_Null>());
  dict->SetFor("3", pdfium::MakeRetain<CPDF_Null>());
  dict->SetFor("4", pdfium::MakeRetain<CPDF_Null>());
  dict->SetFor("5", pdfium::MakeRetain<CPDF_Null>());

  CPDF_ObjectWalker walker(dict);
  while (RetainPtr<const CPDF_Object> obj = walker.GetNext()) {
    if (dict == obj) {
      // Ignore root dictinary object
      continue;
    }
    // Test that, dictionary key is correct.
    EXPECT_EQ(walker.GetParent()->AsDictionary()->GetObjectFor(
                  walker.dictionary_key()),
              obj);
  }
}
