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

#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"
#include "third_party/base/ptr_util.h"

namespace {

std::string Walk(CPDF_Object* object) {
  std::ostringstream result;
  CPDF_ObjectWalker walker(object);
  while (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(CPDF_ObjectWalkerTest, Simple) {
  EXPECT_EQ(Walk(pdfium::MakeRetain<CPDF_Null>().Get()), "Null");
  EXPECT_EQ(Walk(pdfium::MakeRetain<CPDF_Dictionary>().Get()), "Dict");
  EXPECT_EQ(Walk(pdfium::MakeRetain<CPDF_Array>().Get()), "Arr");
  EXPECT_EQ(Walk(pdfium::MakeRetain<CPDF_String>().Get()), "Str");
  EXPECT_EQ(Walk(pdfium::MakeRetain<CPDF_Boolean>().Get()), "Bool");
  EXPECT_EQ(Walk(pdfium::MakeRetain<CPDF_Stream>().Get()), "Stream");
  EXPECT_EQ(Walk(pdfium::MakeRetain<CPDF_Reference>(nullptr, 0).Get()), "Ref");
}

TEST(CPDF_ObjectWalkerTest, CombinedObject) {
  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->Add(pdfium::MakeRetain<CPDF_Reference>(nullptr, 0));
  array->Add(pdfium::MakeRetain<CPDF_Null>());
  array->Add(pdfium::MakeRetain<CPDF_Stream>(
      nullptr, 0, pdfium::MakeRetain<CPDF_Dictionary>()));
  dict->SetFor("3", std::move(array));
  // The last number for stream length.
  EXPECT_EQ(Walk(dict.Get()), "Dict Str Bool Arr Ref Null Stream Dict Num");
}

TEST(CPDF_ObjectWalkerTest, GetParent) {
  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 =
      pdfium::MakeRetain<CPDF_Stream>(nullptr, 0, std::move(level_3));
  auto level_1 = pdfium::MakeRetain<CPDF_Array>();
  level_1->Add(std::move(level_2));
  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.
  const CPDF_Object* cur_parent = nullptr;
  CPDF_ObjectWalker walker(level_0.Get());
  while (const CPDF_Object* obj = walker.GetNext()) {
    EXPECT_EQ(cur_parent, walker.GetParent());
    cur_parent = obj;
  }
}

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

  int non_array_objects = 0;
  CPDF_ObjectWalker walker(root_array.Get());
  while (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(CPDF_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.Get());
  while (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);
  }
}
