// Copyright 2019 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/fxcrt/retained_tree_node.h"

#include "core/fxcrt/observed_ptr.h"
#include "core/fxcrt/retain_ptr.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace fxcrt {
namespace {

class ObservableRetainedTreeNodeForTest
    : public RetainedTreeNode<ObservableRetainedTreeNodeForTest>,
      public Observable {
 public:
  CONSTRUCT_VIA_MAKE_RETAIN;

 private:
  ObservableRetainedTreeNodeForTest() = default;
};

void AddClutterToFront(
    const RetainPtr<ObservableRetainedTreeNodeForTest>& parent) {
  for (int i = 0; i < 4; ++i) {
    parent->AppendFirstChild(
        pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>());
  }
}

void AddClutterToBack(
    const RetainPtr<ObservableRetainedTreeNodeForTest>& parent) {
  for (int i = 0; i < 4; ++i) {
    parent->AppendLastChild(
        pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>());
  }
}

}  // namespace

TEST(RetainedTreeNode, NoParent) {
  ObservedPtr<ObservableRetainedTreeNodeForTest> watcher;
  {
    RetainPtr<ObservableRetainedTreeNodeForTest> ptr =
        pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
    EXPECT_FALSE(ptr->HasChild(ptr.Get()));
    watcher = ObservedPtr<ObservableRetainedTreeNodeForTest>(ptr.Get());
    EXPECT_TRUE(watcher.Get());
  }
  EXPECT_FALSE(watcher.Get());
}

TEST(RetainedTreeNode, FirstHasParent) {
  ObservedPtr<ObservableRetainedTreeNodeForTest> watcher;
  RetainPtr<ObservableRetainedTreeNodeForTest> parent =
      pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
  {
    RetainPtr<ObservableRetainedTreeNodeForTest> ptr =
        pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
    watcher = ObservedPtr<ObservableRetainedTreeNodeForTest>(ptr.Get());
    parent->AppendFirstChild(ptr);
    EXPECT_FALSE(parent->HasChild(parent.Get()));
    EXPECT_TRUE(parent->HasChild(ptr.Get()));
    EXPECT_TRUE(watcher.Get());
  }
  EXPECT_TRUE(watcher.Get());
  parent->RemoveChild(pdfium::WrapRetain(watcher.Get()));
  EXPECT_FALSE(watcher.Get());
  // Now add some clutter.
  {
    RetainPtr<ObservableRetainedTreeNodeForTest> ptr =
        pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
    watcher = ObservedPtr<ObservableRetainedTreeNodeForTest>(ptr.Get());
    parent->AppendFirstChild(ptr);
    AddClutterToFront(parent);
    AddClutterToBack(parent);
    EXPECT_TRUE(watcher.Get());
  }
  EXPECT_TRUE(watcher.Get());
  parent->RemoveChild(pdfium::WrapRetain(watcher.Get()));
  EXPECT_FALSE(watcher.Get());
}

TEST(RetainedTreeNode, LastHasParent) {
  ObservedPtr<ObservableRetainedTreeNodeForTest> watcher;
  RetainPtr<ObservableRetainedTreeNodeForTest> parent =
      pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
  {
    RetainPtr<ObservableRetainedTreeNodeForTest> ptr =
        pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
    watcher = ObservedPtr<ObservableRetainedTreeNodeForTest>(ptr.Get());
    parent->AppendLastChild(ptr);
    EXPECT_FALSE(parent->HasChild(parent.Get()));
    EXPECT_TRUE(parent->HasChild(ptr.Get()));
    EXPECT_TRUE(watcher.Get());
  }
  {
    // Now add some clutter.
    RetainPtr<ObservableRetainedTreeNodeForTest> ptr =
        pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
    watcher = ObservedPtr<ObservableRetainedTreeNodeForTest>(ptr.Get());
    parent->AppendLastChild(ptr);
    AddClutterToFront(parent);
    AddClutterToBack(parent);
    EXPECT_TRUE(watcher.Get());
  }
  EXPECT_TRUE(watcher.Get());
  parent->RemoveChild(pdfium::WrapRetain(watcher.Get()));
  EXPECT_FALSE(watcher.Get());
}

TEST(RetainedTreeNode, GrandChildCleanedUp) {
  ObservedPtr<ObservableRetainedTreeNodeForTest> watcher;
  RetainPtr<ObservableRetainedTreeNodeForTest> grandparent =
      pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
  {
    RetainPtr<ObservableRetainedTreeNodeForTest> parent =
        pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
    grandparent->AppendFirstChild(parent);
    {
      RetainPtr<ObservableRetainedTreeNodeForTest> ptr =
          pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
      watcher = ObservedPtr<ObservableRetainedTreeNodeForTest>(ptr.Get());
      parent->AppendFirstChild(ptr);
      EXPECT_TRUE(watcher.Get());
    }
    grandparent->RemoveChild(parent);
    EXPECT_TRUE(watcher.Get());
  }
  EXPECT_FALSE(watcher.Get());
}

TEST(RetainedTreeNode, RemoveSelf) {
  ObservedPtr<ObservableRetainedTreeNodeForTest> watcher;
  auto parent = pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
  {
    auto child = pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
    watcher = ObservedPtr<ObservableRetainedTreeNodeForTest>(child.Get());
    parent->AppendFirstChild(child);
  }
  EXPECT_TRUE(watcher.Get());
  watcher->RemoveSelfIfParented();
  EXPECT_FALSE(watcher.Get());
}

TEST(RetainedTreeNode, InsertBeforeAfter) {
  ObservedPtr<ObservableRetainedTreeNodeForTest> watcher;
  RetainPtr<ObservableRetainedTreeNodeForTest> parent =
      pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();

  AddClutterToFront(parent);
  {
    RetainPtr<ObservableRetainedTreeNodeForTest> ptr =
        pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();
    watcher = ObservedPtr<ObservableRetainedTreeNodeForTest>(ptr.Get());
    parent->AppendFirstChild(ptr);
    parent->InsertBefore(pdfium::WrapRetain(parent->GetFirstChild()),
                         parent->GetLastChild());
    parent->InsertAfter(pdfium::WrapRetain(parent->GetLastChild()),
                        parent->GetFirstChild());
    EXPECT_TRUE(watcher.Get());
  }
  parent->RemoveChild(pdfium::WrapRetain(watcher.Get()));
  EXPECT_FALSE(watcher.Get());
}

TEST(RetainedTreeNode, Traversal) {
  RetainPtr<ObservableRetainedTreeNodeForTest> parent =
      pdfium::MakeRetain<ObservableRetainedTreeNodeForTest>();

  AddClutterToFront(parent);
  int count = 0;
  for (ObservableRetainedTreeNodeForTest* pNode = parent->GetFirstChild();
       pNode; pNode = pNode->GetNextSibling()) {
    ++count;
  }
  EXPECT_EQ(4, count);
  count = 0;
  for (ObservableRetainedTreeNodeForTest* pNode = parent->GetLastChild(); pNode;
       pNode = pNode->GetPrevSibling()) {
    ++count;
  }
  EXPECT_EQ(4, count);
}

}  // namespace fxcrt
