/*
 * Copyright 2015 Google Inc. 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.
 */

#include "cobalt/css_parser/parser.h"
#include "cobalt/cssom/css_style_rule.h"
#include "cobalt/cssom/selector_tree.h"
#include "cobalt/cssom/specificity.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace cobalt {
namespace cssom {

TEST(SelectorTreeTest, RootShouldHaveNoChildrenAfterInitialization) {
  SelectorTree selector_tree;
  EXPECT_TRUE(
      selector_tree.children(selector_tree.root(), kChildCombinator).empty());
  EXPECT_TRUE(
      selector_tree.children(selector_tree.root(), kDescendantCombinator)
          .empty());
  EXPECT_TRUE(
      selector_tree.children(selector_tree.root(), kNextSiblingCombinator)
          .empty());
  EXPECT_TRUE(
      selector_tree.children(selector_tree.root(), kFollowingSiblingCombinator)
          .empty());
}

TEST(SelectorTreeTest, AppendRuleShouldTakeOneRule) {
  SelectorTree selector_tree;

  // Selector Tree:
  // root
  //   kDescendantCombinator -> node_1("div")
  scoped_ptr<css_parser::Parser> css_parser = css_parser::Parser::Create();
  scoped_refptr<CSSStyleRule> css_style_rule_1 =
      css_parser->ParseRule("div {}", base::SourceLocation(
                                          "[object SelectorTreeTest]", 1, 1))
          ->AsCSSStyleRule();
  selector_tree.AppendRule(css_style_rule_1);
  ASSERT_EQ(
      0, selector_tree.children(selector_tree.root(), kChildCombinator).size());
  ASSERT_EQ(1,
            selector_tree.children(selector_tree.root(), kDescendantCombinator)
                .size());
  ASSERT_EQ(0,
            selector_tree.children(selector_tree.root(), kNextSiblingCombinator)
                .size());
  ASSERT_EQ(0, selector_tree.children(selector_tree.root(),
                                      kFollowingSiblingCombinator)
                   .size());

  const SelectorTree::Node* node_1 =
      selector_tree.children(selector_tree.root(), kDescendantCombinator)
          .begin()
          ->second;
  ASSERT_EQ(1, node_1->rules().size());
  EXPECT_EQ(css_style_rule_1, node_1->rules()[0]);
  EXPECT_EQ(Specificity(0, 0, 1), node_1->cumulative_specificity());
}

TEST(SelectorTreeTest, AppendRuleShouldNormalizeCompoundSelector) {
  SelectorTree selector_tree;

  // Selector Tree:
  // root
  //   kDescendantCombinator -> node_1(".class#id")
  scoped_ptr<css_parser::Parser> css_parser = css_parser::Parser::Create();
  scoped_refptr<CSSStyleRule> css_style_rule_1 =
      css_parser->ParseRule(
                    ".class#id {}",
                    base::SourceLocation("[object SelectorTreeTest]", 1, 1))
          ->AsCSSStyleRule();
  scoped_refptr<CSSStyleRule> css_style_rule_2 =
      css_parser->ParseRule(
                    "#id.class {}",
                    base::SourceLocation("[object SelectorTreeTest]", 1, 1))
          ->AsCSSStyleRule();
  selector_tree.AppendRule(css_style_rule_1);
  selector_tree.AppendRule(css_style_rule_2);
  ASSERT_EQ(
      0, selector_tree.children(selector_tree.root(), kChildCombinator).size());
  ASSERT_EQ(1,
            selector_tree.children(selector_tree.root(), kDescendantCombinator)
                .size());
  ASSERT_EQ(0,
            selector_tree.children(selector_tree.root(), kNextSiblingCombinator)
                .size());
  ASSERT_EQ(0, selector_tree.children(selector_tree.root(),
                                      kFollowingSiblingCombinator)
                   .size());
}

TEST(SelectorTreeTest, AppendRuleSimpleShouldTakeTwoIdenticalRules) {
  SelectorTree selector_tree;

  // Selector Tree:
  // root
  //   kDescendantCombinator -> node_1("div")
  scoped_ptr<css_parser::Parser> css_parser = css_parser::Parser::Create();
  scoped_refptr<CSSStyleRule> css_style_rule_1 =
      css_parser->ParseRule("div {}", base::SourceLocation(
                                          "[object SelectorTreeTest]", 1, 1))
          ->AsCSSStyleRule();
  scoped_refptr<CSSStyleRule> css_style_rule_2 =
      css_parser->ParseRule("div {}", base::SourceLocation(
                                          "[object SelectorTreeTest]", 1, 1))
          ->AsCSSStyleRule();
  selector_tree.AppendRule(css_style_rule_1);
  selector_tree.AppendRule(css_style_rule_2);

  ASSERT_EQ(
      0, selector_tree.children(selector_tree.root(), kChildCombinator).size());
  ASSERT_EQ(1,
            selector_tree.children(selector_tree.root(), kDescendantCombinator)
                .size());
  ASSERT_EQ(0,
            selector_tree.children(selector_tree.root(), kNextSiblingCombinator)
                .size());
  ASSERT_EQ(0, selector_tree.children(selector_tree.root(),
                                      kFollowingSiblingCombinator)
                   .size());
  const SelectorTree::Node* node_1 =
      selector_tree.children(selector_tree.root(), kDescendantCombinator)
          .begin()
          ->second;
  ASSERT_EQ(2, node_1->rules().size());
  EXPECT_EQ(css_style_rule_1, node_1->rules()[0]);
  EXPECT_EQ(css_style_rule_2, node_1->rules()[1]);
  EXPECT_EQ(Specificity(0, 0, 1), node_1->cumulative_specificity());
}

TEST(SelectorTreeTest, AppendRuleSimpleShouldTakeTwoDesendantSelectors) {
  SelectorTree selector_tree;

  // Selector Tree:
  // root
  //   kNone -> node_1("div")
  //     kChildCombinator -> node_2("span")
  scoped_ptr<css_parser::Parser> css_parser = css_parser::Parser::Create();
  scoped_refptr<CSSStyleRule> css_style_rule_1 =
      css_parser->ParseRule("div {}", base::SourceLocation(
                                          "[object SelectorTreeTest]", 1, 1))
          ->AsCSSStyleRule();
  scoped_refptr<CSSStyleRule> css_style_rule_2 =
      css_parser->ParseRule(
                    "div span {}",
                    base::SourceLocation("[object SelectorTreeTest]", 1, 1))
          ->AsCSSStyleRule();
  selector_tree.AppendRule(css_style_rule_1);
  selector_tree.AppendRule(css_style_rule_2);

  ASSERT_EQ(
      0, selector_tree.children(selector_tree.root(), kChildCombinator).size());
  ASSERT_EQ(1,
            selector_tree.children(selector_tree.root(), kDescendantCombinator)
                .size());
  ASSERT_EQ(0,
            selector_tree.children(selector_tree.root(), kNextSiblingCombinator)
                .size());
  ASSERT_EQ(0, selector_tree.children(selector_tree.root(),
                                      kFollowingSiblingCombinator)
                   .size());
  const SelectorTree::Node* node_1 =
      selector_tree.children(selector_tree.root(), kDescendantCombinator)
          .begin()
          ->second;
  ASSERT_EQ(1, node_1->rules().size());
  EXPECT_EQ(css_style_rule_1, node_1->rules()[0]);
  EXPECT_EQ(Specificity(0, 0, 1), node_1->cumulative_specificity());

  ASSERT_EQ(0, selector_tree.children(node_1, kChildCombinator).size());
  ASSERT_EQ(1, selector_tree.children(node_1, kDescendantCombinator).size());
  ASSERT_EQ(0, selector_tree.children(node_1, kNextSiblingCombinator).size());
  ASSERT_EQ(0,
            selector_tree.children(node_1, kFollowingSiblingCombinator).size());
  const SelectorTree::Node* node_2 =
      selector_tree.children(node_1, kDescendantCombinator).begin()->second;
  ASSERT_EQ(1, node_2->rules().size());
  EXPECT_EQ(css_style_rule_2, node_2->rules()[0]);
  EXPECT_EQ(Specificity(0, 0, 2), node_2->cumulative_specificity());
}

}  // namespace cssom
}  // namespace cobalt
