// Copyright 2014 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef COBALT_DOM_TESTING_HTML_COLLECTION_TESTING_H_
#define COBALT_DOM_TESTING_HTML_COLLECTION_TESTING_H_

#include "cobalt/dom/document.h"
#include "cobalt/dom/element.h"
#include "cobalt/dom/html_collection.h"
#include "cobalt/dom/html_element.h"
#include "cobalt/dom/html_element_factory.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace cobalt {
namespace dom {
namespace testing {

// Given an empty node of a type T, test the functionality of
// T::GetElementsByClassName.
template <typename T>
void TestGetElementsByClassName(const scoped_refptr<T>& node);

// Given an empty node of a type T, test the functionality of
// T::GetElementsByTagName.
template <typename T>
void TestGetElementsByTagName(const scoped_refptr<T>& node);

/////////////////////////////////////////////////////////////////////////////
// Implementation
/////////////////////////////////////////////////////////////////////////////

template <typename T>
void TestGetElementsByClassName(const scoped_refptr<T>& node) {
  const scoped_refptr<Node> kNullNode;
  const scoped_refptr<HTMLCollection> kNullCollection;

  Document* document = node->node_document();

  if (!document) {
    document = node->AsDocument();
    DCHECK(document);
  }

  // Construct a tree:
  // node
  //   a1
  //     b1
  //       c1
  //   a2
  //     d1
  //     d2
  scoped_refptr<Node> a1 =
      node->AppendChild(new Element(document, base::Token("a1")));
  scoped_refptr<Node> a2 =
      node->AppendChild(new Element(document, base::Token("a2")));
  scoped_refptr<Node> b1 =
      a1->AppendChild(new Element(document, base::Token("b1")));
  scoped_refptr<Node> c1 =
      b1->AppendChild(new Element(document, base::Token("c1")));
  scoped_refptr<Node> d1 =
      a2->AppendChild(new Element(document, base::Token("d1")));
  scoped_refptr<Node> d2 =
      a2->AppendChild(new Element(document, base::Token("d2")));

  scoped_refptr<HTMLCollection> collection =
      node->GetElementsByClassName("class");

  // Start with an empty class.
  EXPECT_EQ(0, collection->length());

  // Set the matching class on all elements.
  a1->AsElement()->set_class_name("class");
  a2->AsElement()->set_class_name("class");
  b1->AsElement()->set_class_name("class");
  c1->AsElement()->set_class_name("class");
  d1->AsElement()->set_class_name("class");
  d2->AsElement()->set_class_name("class");

  EXPECT_EQ(6, collection->length());
  EXPECT_EQ(a1, collection->Item(0));
  EXPECT_EQ(b1, collection->Item(1));
  EXPECT_EQ(c1, collection->Item(2));
  EXPECT_EQ(a2, collection->Item(3));
  EXPECT_EQ(d1, collection->Item(4));
  EXPECT_EQ(d2, collection->Item(5));
  EXPECT_EQ(kNullNode, collection->Item(6));
  EXPECT_EQ(a1, collection->Item(0));

  // Modify the class name on some elements.
  a1->AsElement()->set_class_name("other_class");
  a2->AsElement()->set_class_name("other_class");
  b1->AsElement()->set_class_name("other_class");
  d1->AsElement()->set_class_name("other_class");

  EXPECT_EQ(2, collection->length());
  EXPECT_EQ(c1, collection->Item(0));
  EXPECT_EQ(d2, collection->Item(1));
  EXPECT_EQ(kNullNode, collection->Item(2));
  EXPECT_EQ(c1, collection->Item(0));

  // d1 is not matched by the collection so adding the id shouldn't change
  // anything.
  d1->AsElement()->set_id("id");
  EXPECT_EQ(kNullNode, collection->NamedItem("id"));

  // d2 is matched by the collection so adding the id should work.
  d2->AsElement()->set_id("id");
  EXPECT_EQ(d2, collection->NamedItem("id"));

  // Removing a2 should also remove its children from the collection, including
  // d2.
  node->RemoveChild(a2);
  EXPECT_EQ(1, collection->length());
  EXPECT_EQ(c1, collection->Item(0));
  EXPECT_EQ(kNullNode, collection->Item(1));
  EXPECT_EQ(kNullNode, collection->NamedItem("id"));

  c1->AsElement()->set_class_name("other_class");
  EXPECT_EQ(0, collection->length());
  EXPECT_EQ(kNullNode, collection->Item(0));

  // Test elements with multiple classes
  a1->AsElement()->set_class_name("class other_class");
  b1->AsElement()->set_class_name("class yet_another_class");
  c1->AsElement()->set_class_name("other_class yet_another_class");
  EXPECT_EQ(2, collection->length());
  EXPECT_EQ(a1, collection->Item(0));
  EXPECT_EQ(b1, collection->Item(1));
}

template <typename T>
void TestGetElementsByTagName(const scoped_refptr<T>& node) {
  const scoped_refptr<Node> kNullNode;
  const scoped_refptr<HTMLCollection> kNullCollection;
  Document* document = node->node_document();

  if (!document) {
    document = node->AsDocument();
    DCHECK(document);
  }

  // Construct a tree:
  // node
  //   a1
  //     b1
  //       c1
  //   a3
  //     d1
  HTMLElementFactory html_element_factory;
  html_element_factory.CreateHTMLElement(document, base::Token("a1"));

  scoped_refptr<Node> a1 = node->AppendChild(
      html_element_factory.CreateHTMLElement(document, base::Token("a1")));

  scoped_refptr<Node> a3 = node->AppendChild(
      html_element_factory.CreateHTMLElement(document, base::Token("a2")));
  scoped_refptr<Node> b1 = a1->AppendChild(
      html_element_factory.CreateHTMLElement(document, base::Token("b1")));
  scoped_refptr<Node> c1 = b1->AppendChild(
      html_element_factory.CreateHTMLElement(document, base::Token("element")));
  scoped_refptr<Node> d1 = a3->AppendChild(
      html_element_factory.CreateHTMLElement(document, base::Token("element")));

  // GetElementsByTagName should return all elements when provided with
  // parameter "*".
  scoped_refptr<HTMLCollection> collection = node->GetElementsByTagName("*");
  EXPECT_EQ(5, collection->length());
  EXPECT_EQ(a1, collection->Item(0));
  EXPECT_EQ(b1, collection->Item(1));
  EXPECT_EQ(c1, collection->Item(2));
  EXPECT_EQ(a3, collection->Item(3));
  EXPECT_EQ(d1, collection->Item(4));
  EXPECT_EQ(kNullNode, collection->Item(5));

  // GetElementsByTagName should only return elements with the specific local
  // name when that is provided.
  collection = node->GetElementsByTagName("element");
  EXPECT_EQ(2, collection->length());
  EXPECT_EQ(c1, collection->Item(0));
  EXPECT_EQ(d1, collection->Item(1));
  EXPECT_EQ(kNullNode, collection->Item(2));

  // a3 is not matched by the collection so adding the id shouldn't change
  // anything.
  a3->AsElement()->set_id("id");
  EXPECT_EQ(kNullNode, collection->NamedItem("id"));

  // d1 is matched by the collection so adding the id should work.
  d1->AsElement()->set_id("id");
  EXPECT_EQ(d1, collection->NamedItem("id"));

  // Add a new node with a matching tag.
  scoped_refptr<Node> a2 = node->InsertBefore(
      html_element_factory.CreateHTMLElement(document, base::Token("element")),
      a3);
  EXPECT_EQ(3, collection->length());
  EXPECT_EQ(c1, collection->Item(0));
  EXPECT_EQ(a2, collection->Item(1));
  EXPECT_EQ(d1, collection->Item(2));
  EXPECT_EQ(kNullNode, collection->Item(3));

  // Removing a3 should also remove its children from the collection.
  node->RemoveChild(a3);
  EXPECT_EQ(2, collection->length());
  EXPECT_EQ(c1, collection->Item(0));
  EXPECT_EQ(a2, collection->Item(1));
  EXPECT_EQ(kNullNode, collection->Item(2));
  EXPECT_EQ(kNullNode, collection->NamedItem("id"));
}

}  // namespace testing
}  // namespace dom
}  // namespace cobalt

#endif  // COBALT_DOM_TESTING_HTML_COLLECTION_TESTING_H_
