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

#include "cobalt/dom/rule_matching.h"

#include <algorithm>
#include <memory>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/callback.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
#include "base/trace_event/trace_event.h"
#include "cobalt/base/unused.h"
#include "cobalt/cssom/after_pseudo_element.h"
#include "cobalt/cssom/attribute_selector.h"
#include "cobalt/cssom/before_pseudo_element.h"
#include "cobalt/cssom/cascade_precedence.h"
#include "cobalt/cssom/child_combinator.h"
#include "cobalt/cssom/class_selector.h"
#include "cobalt/cssom/combinator.h"
#include "cobalt/cssom/combinator_visitor.h"
#include "cobalt/cssom/complex_selector.h"
#include "cobalt/cssom/compound_selector.h"
#include "cobalt/cssom/css_style_rule.h"
#include "cobalt/cssom/css_style_sheet.h"
#include "cobalt/cssom/descendant_combinator.h"
#include "cobalt/cssom/empty_pseudo_class.h"
#include "cobalt/cssom/following_sibling_combinator.h"
#include "cobalt/cssom/id_selector.h"
#include "cobalt/cssom/next_sibling_combinator.h"
#include "cobalt/cssom/not_pseudo_class.h"
#include "cobalt/cssom/property_value.h"
#include "cobalt/cssom/pseudo_element.h"
#include "cobalt/cssom/selector_tree.h"
#include "cobalt/cssom/selector_visitor.h"
#include "cobalt/cssom/simple_selector.h"
#include "cobalt/cssom/type_selector.h"
#include "cobalt/cssom/universal_selector.h"
#include "cobalt/dom/attr.h"
#include "cobalt/dom/document.h"
#include "cobalt/dom/dom_token_list.h"
#include "cobalt/dom/element.h"
#include "cobalt/dom/html_element.h"
#include "cobalt/dom/html_html_element.h"
#include "cobalt/dom/named_node_map.h"
#include "cobalt/dom/node_descendants_iterator.h"
#include "cobalt/dom/node_list.h"
#include "cobalt/dom/pseudo_element.h"
#include "cobalt/math/safe_integer_conversions.h"

namespace cobalt {
namespace dom {
namespace {

using cssom::SelectorTree;

struct NodeCombinatorType {
  NodeCombinatorType(const SelectorTree::Node* node,
                     cssom::CombinatorType combinator_type)
      : node(node), combinator_type(combinator_type) {}

  const SelectorTree::Node* node;
  cssom::CombinatorType combinator_type;
};

//////////////////////////////////////////////////////////////////////////
// Helper functions
//////////////////////////////////////////////////////////////////////////

// Matches an element against a selector. If the element doesn't match, returns
// NULL, otherwise returns the result of advancing the pointer to the element
// according to the combinators.
Element* MatchSelectorAndElement(cssom::Selector* selector, Element* element,
                                 bool matching_combinators);

//////////////////////////////////////////////////////////////////////////
// Combinator matcher
//////////////////////////////////////////////////////////////////////////

class CombinatorMatcher : public cssom::CombinatorVisitor {
 public:
  explicit CombinatorMatcher(Element* element) : element_(element) {
    DCHECK(element);
  }

  // Child combinator describes a childhood relationship between two elements.
  //   https://www.w3.org/TR/selectors4/#child-combinators
  void VisitChildCombinator(cssom::ChildCombinator* child_combinator) override {
    element_ = MatchSelectorAndElement(child_combinator->left_selector(),
                                       element_->parent_element(), true);
  }

  // Next-sibling combinator describes that the elements represented by the two
  // compound selectors share the same parent in the document tree and the
  // element represented by the first compound selector immediately precedes the
  // element represented by the second one.
  //   https://www.w3.org/TR/selectors4/#adjacent-sibling-combinators
  void VisitNextSiblingCombinator(
      cssom::NextSiblingCombinator* next_sibling_combinator) override {
    element_ =
        MatchSelectorAndElement(next_sibling_combinator->left_selector(),
                                element_->previous_element_sibling(), true);
  }

  // Descendant combinator describes an element that is the descendant of
  // another element in the document tree.
  //   https://www.w3.org/TR/selectors4/#descendant-combinators
  void VisitDescendantCombinator(
      cssom::DescendantCombinator* descendant_combinator) override {
    do {
      element_ = element_->parent_element();
      Element* element = MatchSelectorAndElement(
          descendant_combinator->left_selector(), element_, true);
      if (element) {
        element_ = element;
        return;
      }
    } while (element_);
  }

  // Following-sibling combinator describes that the elements represented by the
  // two compound selectors share the same parent in the document tree and the
  // element represented by the first compound selector precedes (not
  // necessarily immediately) the element represented by the second one.
  //   https://www.w3.org/TR/selectors4/#general-sibling-combinators
  void VisitFollowingSiblingCombinator(
      cssom::FollowingSiblingCombinator* following_sibling_combinator)
      override {
    do {
      element_ = element_->previous_element_sibling();
      Element* element = MatchSelectorAndElement(
          following_sibling_combinator->left_selector(), element_, true);
      if (element) {
        element_ = element;
        return;
      }
    } while (element_);
  }

  Element* element() { return element_; }

 private:
  Element* element_;
  DISALLOW_COPY_AND_ASSIGN(CombinatorMatcher);
};

//////////////////////////////////////////////////////////////////////////
// Selector matcher
//////////////////////////////////////////////////////////////////////////

class SelectorMatcher : public cssom::SelectorVisitor {
 public:
  explicit SelectorMatcher(Element* element)
      : element_(element), matching_combinators_(false) {
    DCHECK(element);
  }
  SelectorMatcher(Element* element, bool matching_combinators)
      : element_(element), matching_combinators_(matching_combinators) {
    DCHECK(element);
  }

  // The universal selector represents the qualified name of any element type.
  //   https://www.w3.org/TR/selectors4/#universal-selector
  void VisitUniversalSelector(
      cssom::UniversalSelector* universal_selector) override {}

  // A type selector represents an instance of the element type in the document
  // tree.
  //   https://www.w3.org/TR/selectors4/#type-selector
  void VisitTypeSelector(cssom::TypeSelector* type_selector) override {
    if (type_selector->element_name() != element_->local_name()) {
      element_ = NULL;
    }
  }

  // An attribute selector represents an element that has an attribute that
  // matches the attribute represented by the attribute selector.
  //   https://www.w3.org/TR/selectors4/#attribute-selector
  void VisitAttributeSelector(
      cssom::AttributeSelector* attribute_selector) override {
    if (!element_->HasAttribute(attribute_selector->attribute_name().c_str())) {
      element_ = NULL;
      return;
    }

    switch (attribute_selector->value_match_type()) {
      case cssom::AttributeSelector::kNoMatch:
        return;
      case cssom::AttributeSelector::kEquals:
        if (element_->GetAttribute(attribute_selector->attribute_name().c_str())
                .value() != attribute_selector->attribute_value()) {
          element_ = NULL;
        }
        return;
      case cssom::AttributeSelector::kIncludes:
      case cssom::AttributeSelector::kDashMatch:
      case cssom::AttributeSelector::kBeginsWith:
      case cssom::AttributeSelector::kEndsWith:
      case cssom::AttributeSelector::kContains:
        NOTIMPLEMENTED();
        element_ = NULL;
        return;
    }
  }

  // The class selector represents an element belonging to the class identified
  // by the identifier.
  //   https://www.w3.org/TR/selectors4/#class-selector
  void VisitClassSelector(cssom::ClassSelector* class_selector) override {
    if (!element_->class_list()->ContainsValid(class_selector->class_name())) {
      element_ = NULL;
    }
  }

  // An ID selector represents an element instance that has an identifier that
  // matches the identifier in the ID selector.
  //   https://www.w3.org/TR/selectors4/#id-selector
  void VisitIdSelector(cssom::IdSelector* id_selector) override {
    if (id_selector->id() != element_->id()) {
      element_ = NULL;
    }
  }

  // The :active pseudo-class applies while an element is being activated by the
  // user. For example, between the times the user presses the mouse button and
  // releases it. On systems with more than one mouse button, :active applies
  // only to the primary or primary activation button (typically the "left"
  // mouse button), and any aliases thereof.
  //   https://www.w3.org/TR/selectors4/#active-pseudo
  void VisitActivePseudoClass(cssom::ActivePseudoClass*) override {
    NOTIMPLEMENTED();
    element_ = NULL;
  }

  // The :empty pseudo-class represents an element that has no content children.
  //   https://www.w3.org/TR/selectors4/#empty-pseudo
  void VisitEmptyPseudoClass(cssom::EmptyPseudoClass*) override {
    if (!element_->IsEmpty()) {
      element_ = NULL;
    }
  }

  // The :focus pseudo-class applies while an element has the focus (accepts
  // keyboard or mouse events, or other forms of input).
  //   https://www.w3.org/TR/selectors4/#focus-pseudo
  void VisitFocusPseudoClass(cssom::FocusPseudoClass*) override {
    if (!element_->HasFocus()) {
      element_ = NULL;
    }
  }

  // The :hover pseudo-class applies while the user designates an element with a
  // pointing device, but does not necessarily activate it. For example, a
  // visual user agent could apply this pseudo-class when the cursor (mouse
  // pointer) hovers over a box generated by the element. Interactive user
  // agents that cannot detect hovering due to hardware limitations (e.g., a pen
  // device that does not detect hovering) are still conforming.
  //   https://www.w3.org/TR/selectors4/#hover-pseudo
  void VisitHoverPseudoClass(cssom::HoverPseudoClass*) override {
    if (!element_->AsHTMLElement() ||
        !element_->AsHTMLElement()->IsDesignated()) {
      element_ = NULL;
    }
  }

  // The negation pseudo-class, :not(), is a functional pseudo-class taking a
  // selector list as an argument. It represents an element that is not
  // represented by its argument.
  //   https://www.w3.org/TR/selectors4/#negation-pseudo
  void VisitNotPseudoClass(cssom::NotPseudoClass* not_pseudo_class) override {
    if (MatchSelectorAndElement(not_pseudo_class->selector(), element_, true)) {
      element_ = NULL;
    }
  }

  // Pseudo elements doesn't affect whether the selector matches or not.

  // The :after pseudo-element represents a generated element.
  //   https://www.w3.org/TR/CSS21/generate.html#before-after-content
  void VisitAfterPseudoElement(cssom::AfterPseudoElement*) override {}

  // The :before pseudo-element represents a generated element.
  //   https://www.w3.org/TR/CSS21/generate.html#before-after-content
  void VisitBeforePseudoElement(cssom::BeforePseudoElement*) override {}

  // A compound selector is a chain of simple selectors that are not separated
  // by a combinator.
  //   https://www.w3.org/TR/selectors4/#compound
  void VisitCompoundSelector(
      cssom::CompoundSelector* compound_selector) override {
    DCHECK_GT(compound_selector->simple_selectors().size(), 0U);

    // Iterate through all the simple selectors. If any of the simple selectors
    // doesn't match, the compound selector doesn't match.
    for (cssom::CompoundSelector::SimpleSelectors::const_iterator
             selector_iterator = compound_selector->simple_selectors().begin();
         selector_iterator != compound_selector->simple_selectors().end();
         ++selector_iterator) {
      element_ =
          MatchSelectorAndElement(selector_iterator->get(), element_, false);
      if (!element_) {
        return;
      }
    }

    // Check combinator.
    if (matching_combinators_ && compound_selector->left_combinator()) {
      CombinatorMatcher combinator_matcher(element_);
      compound_selector->left_combinator()->Accept(&combinator_matcher);
      element_ = combinator_matcher.element();
    }
  }

  // A complex selector is a chain of one or more compound selectors separated
  // by combinators.
  //   https://www.w3.org/TR/selectors4/#complex
  void VisitComplexSelector(cssom::ComplexSelector* complex_selector) override {
    element_ = MatchSelectorAndElement(complex_selector->last_selector(),
                                       element_, true);
  }

  Element* element() const { return element_; }

 private:
  Element* element_;
  bool matching_combinators_;
  DISALLOW_COPY_AND_ASSIGN(SelectorMatcher);
};

//////////////////////////////////////////////////////////////////////////
// Helper functions
//////////////////////////////////////////////////////////////////////////

Element* MatchSelectorAndElement(cssom::Selector* selector, Element* element,
                                 bool matching_combinators) {
  DCHECK(selector);
  if (!element) {
    return NULL;
  }

  SelectorMatcher selector_matcher(element, matching_combinators);
  selector->Accept(&selector_matcher);
  return selector_matcher.element();
}

void GatherCandidateNodesFromSelectorNodesMap(
    cssom::SimpleSelectorType simple_selector_type,
    cssom::CombinatorType combinator_type,
    const SelectorTree::Node* parent_node,
    const SelectorTree::SelectorTextToNodesMap* map, base::Token key,
    SelectorTree::NodePairs* candidate_nodes) {
  SelectorTree::SelectorTextToNodesMap::const_iterator it = map->find(key);
  if (it != map->end()) {
    const SelectorTree::SimpleSelectorNodes& nodes = it->second;
    for (const auto& nodes_iterator : nodes) {
      if (nodes_iterator.simple_selector_type == simple_selector_type &&
          nodes_iterator.combinator_type == combinator_type) {
        candidate_nodes->emplace_back(parent_node, nodes_iterator.node);
      }
    }
  }
}

void GatherCandidateNodesFromPseudoClassNodes(
    cssom::PseudoClassType pseudo_class_type,
    cssom::CombinatorType combinator_type,
    const SelectorTree::Node* parent_node,
    const SelectorTree::PseudoClassNodes& pseudo_class_nodes,
    SelectorTree::NodePairs* candidate_nodes) {
  for (const auto& nodes_iterator : pseudo_class_nodes) {
    if (nodes_iterator.pseudo_class_type == pseudo_class_type &&
        nodes_iterator.combinator_type == combinator_type) {
      candidate_nodes->emplace_back(parent_node, nodes_iterator.node);
    }
  }
}

bool GatherNodeModificationsAndUpdateTargetNodes(
    const SelectorTree::Nodes& source_nodes, SelectorTree::Nodes* target_nodes,
    SelectorTree::Nodes* added_nodes, SelectorTree::Nodes* removed_nodes) {
  if (source_nodes == *target_nodes) {
    return false;
  }

  added_nodes->clear();
  removed_nodes->clear();

  if (target_nodes->empty()) {
    // If the previous state of the nodes (|target_nodes|) is empty, then all
    // nodes in the new state (|source_nodes|) are being added.
    *added_nodes = source_nodes;
  } else if (source_nodes.empty()) {
    // If the new state (|source_nodes|) is empty, then all nodes in the
    // previous state (|target_nodes|) are being removed.
    *removed_nodes = *target_nodes;
  } else {
    // If neither the previous state nor the new state or empty, then the lists
    // must be manually searched to determine what is being added and removed.
    // Remove all nodes in |source_nodes| from |target_nodes|. Any of the nodes
    // that are not found in |target_nodes| are newly added nodes.
    size_t start_index = 0;
    for (const auto& check_node : source_nodes) {
      bool node_found = false;
      for (size_t index = start_index; index < target_nodes->size(); ++index) {
        if ((*target_nodes)[index] == check_node) {
          if (index == start_index) {
            ++start_index;
          }
          node_found = true;
          (*target_nodes)[index] = NULL;
          break;
        }
      }
      if (!node_found) {
        added_nodes->push_back(check_node);
      }
    }
    // Find nodes that remain in |target_nodes|. These did not exist in
    // |source_nodes| and are newly removed nodes.
    for (const auto& check_node : *target_nodes) {
      if (check_node != NULL) {
        removed_nodes->push_back(check_node);
      }
    }
  }

  *target_nodes = source_nodes;

  // Return whether or not any modifications were found.
  return !added_nodes->empty() || !removed_nodes->empty();
}

// Returns true if a matching node was added.
bool GatherMatchingNodes(const SelectorTree::Nodes& nodes,
                         cssom::CombinatorType combinator_type,
                         HTMLElement* element,
                         SelectorTree::NodePairs* scratchpad_node_pairs) {
  bool matching_node_added = false;

  // Gathering Phase: Generate candidate nodes from the nodes.
  SelectorTree::NodePairs* candidate_node_pairs = scratchpad_node_pairs;
  candidate_node_pairs->clear();

  const std::vector<base::Token>& element_class_list =
      element->class_list()->GetTokens();

  // Don't retrieve the element's attributes until they are needed. Retrieving
  // them typically requires the creation of a NamedNodeMap.
  scoped_refptr<NamedNodeMap> element_attributes;

  // Iterate through all nodes.
  for (const auto& node : nodes) {
    if (!node->HasCombinator(combinator_type)) {
      continue;
    }

    // Gather candidate nodes in node's children under the given combinator.
    const SelectorTree::SelectorTextToNodesMap* selector_nodes_map =
        node->selector_nodes_map();
    if (selector_nodes_map) {
      // Universal selector.
      if (node->HasSimpleSelector(cssom::kUniversalSelector, combinator_type)) {
        GatherCandidateNodesFromSelectorNodesMap(
            cssom::kUniversalSelector, combinator_type, node,
            selector_nodes_map, base::Token(), candidate_node_pairs);
      }

      // Type selector.
      if (node->HasSimpleSelector(cssom::kTypeSelector, combinator_type)) {
        GatherCandidateNodesFromSelectorNodesMap(
            cssom::kTypeSelector, combinator_type, node, selector_nodes_map,
            element->local_name(), candidate_node_pairs);
      }

      // Attribute selector.
      if (node->HasSimpleSelector(cssom::kAttributeSelector, combinator_type)) {
        // If the element's attributes have not been retrieved yet, then
        // retrieve them now.
        if (!element_attributes) {
          element_attributes = element->attributes();
        }

        for (unsigned int index = 0; index < element_attributes->length();
             ++index) {
          GatherCandidateNodesFromSelectorNodesMap(
              cssom::kAttributeSelector, combinator_type, node,
              selector_nodes_map,
              base::Token(element_attributes->Item(index)->name()),
              candidate_node_pairs);
        }
      }

      // Class selector.
      if (node->HasSimpleSelector(cssom::kClassSelector, combinator_type)) {
        for (const auto& element_class : element_class_list) {
          GatherCandidateNodesFromSelectorNodesMap(
              cssom::kClassSelector, combinator_type, node, selector_nodes_map,
              element_class, candidate_node_pairs);
        }
      }

      // Id selector.
      if (node->HasSimpleSelector(cssom::kIdSelector, combinator_type)) {
        GatherCandidateNodesFromSelectorNodesMap(
            cssom::kIdSelector, combinator_type, node, selector_nodes_map,
            element->id(), candidate_node_pairs);
      }
    }

    // Only check for specific pseudo classes when the node has as least one.
    if (node->HasAnyPseudoClass()) {
      // Empty pseudo class.
      if (node->HasPseudoClass(cssom::kEmptyPseudoClass, combinator_type) &&
          element->IsEmpty()) {
        GatherCandidateNodesFromPseudoClassNodes(
            cssom::kEmptyPseudoClass, combinator_type, node,
            node->pseudo_class_nodes(), candidate_node_pairs);
      }

      // Focus pseudo class.
      if (node->HasPseudoClass(cssom::kFocusPseudoClass, combinator_type) &&
          element->HasFocus()) {
        GatherCandidateNodesFromPseudoClassNodes(
            cssom::kFocusPseudoClass, combinator_type, node,
            node->pseudo_class_nodes(), candidate_node_pairs);
      }

      // Hover pseudo class.
      if (node->HasPseudoClass(cssom::kHoverPseudoClass, combinator_type) &&
          element->IsDesignated()) {
        GatherCandidateNodesFromPseudoClassNodes(
            cssom::kHoverPseudoClass, combinator_type, node,
            node->pseudo_class_nodes(), candidate_node_pairs);
      }

      // Not pseudo class.
      if (node->HasPseudoClass(cssom::kNotPseudoClass, combinator_type)) {
        GatherCandidateNodesFromPseudoClassNodes(
            cssom::kNotPseudoClass, combinator_type, node,
            node->pseudo_class_nodes(), candidate_node_pairs);
      }
    }
  }

  // Verifying Phase: Check all candidate nodes and run callback for matching
  // nodes.
  for (const auto& candidate_node_pair : *candidate_node_pairs) {
    const SelectorTree::Node* candidate_node = candidate_node_pair.second;

    // Verify that this node is a match:
    // 1. If the candidate node's compound selector doesn't require a visit to
    //    verify the match, then the act of gathering the node as a candidate
    //    proved the match.
    // 2. Otherwise, the node requires additional verification checks, so call
    //    MatchSelectorAndElement().
    if (!candidate_node->compound_selector()
             ->requires_rule_matching_verification_visit() ||
        MatchSelectorAndElement(candidate_node->compound_selector(), element,
                                false)) {
      matching_node_added = true;
      element->rule_matching_state()->matching_nodes_parent_nodes.push_back(
          candidate_node_pair.first);
      element->rule_matching_state()->matching_nodes.push_back(candidate_node);
    }
  }

  return matching_node_added;
}

// Returns true if a matching node was removed.
bool RemoveNodesFromMatchingNodes(
    const SelectorTree::Nodes& parent_nodes_to_remove,
    SelectorTree::Nodes* parent_nodes, SelectorTree::Nodes* matching_nodes) {
  DCHECK_EQ(parent_nodes->size(), matching_nodes->size());
  bool node_removed = false;

  // Find any |parent_nodes| that are being removed. Remove these from both
  // |parent_nodes| and |matching_nodes|, as these two containers are kept in
  // sync.
  for (const auto& parent_node_to_remove : parent_nodes_to_remove) {
    for (size_t index = 0; index < parent_nodes->size();) {
      if (parent_node_to_remove == (*parent_nodes)[index]) {
        node_removed = true;
        parent_nodes->erase(parent_nodes->begin() + index);
        matching_nodes->erase(matching_nodes->begin() + index);
      } else {
        ++index;
      }
    }
  }

  return node_removed;
}

// Returns true if the matching nodes were modified.
bool UpdateMatchingNodesFromNodeModifications(
    const SelectorTree::Nodes& added_nodes,
    const SelectorTree::Nodes& removed_nodes,
    cssom::CombinatorType combinator_type, HTMLElement* element,
    SelectorTree::NodePairs* scratchpad_node_pairs) {
  // First gather the matching nodes found in |added_nodes|.
  bool matching_nodes_modified = GatherMatchingNodes(
      added_nodes, combinator_type, element, scratchpad_node_pairs);

  // Now remove any matching nodes found in |removed_nodes|.
  HTMLElement::RuleMatchingState* element_matching_state =
      element->rule_matching_state();
  matching_nodes_modified |= RemoveNodesFromMatchingNodes(
      removed_nodes, &element_matching_state->matching_nodes_parent_nodes,
      &element_matching_state->matching_nodes);

  return matching_nodes_modified;
}

void UpdateRuleMatchingStateCombinatorNodes(
    HTMLElement::RuleMatchingState* matching_state,
    cssom::CombinatorType combinator_type) {
  // Only descendant and following sibling combinators are supported.
  DCHECK(combinator_type == cssom::kDescendantCombinator ||
         combinator_type == cssom::kFollowingSiblingCombinator);
  if (!matching_state) {
    return;
  }

  DCHECK(matching_state->is_set);
  bool& is_dirty = combinator_type == cssom::kDescendantCombinator
                       ? matching_state->are_descendant_nodes_dirty
                       : matching_state->are_following_sibling_nodes_dirty;
  if (!is_dirty) {
    return;
  }

  const SelectorTree::Nodes& base_combinator_nodes =
      combinator_type == cssom::kDescendantCombinator
          ? matching_state->parent_descendant_nodes
          : matching_state->previous_sibling_following_sibling_nodes;
  SelectorTree::Nodes& combinator_nodes =
      combinator_type == cssom::kDescendantCombinator
          ? matching_state->descendant_nodes
          : matching_state->following_sibling_nodes;

  // First copy the base combinator nodes and then add any matching nodes that
  // have the required combinator and are not already included within the list.
  combinator_nodes = base_combinator_nodes;
  for (const auto& node : matching_state->matching_nodes) {
    if (node->HasCombinator(combinator_type) &&
        std::find(base_combinator_nodes.begin(), base_combinator_nodes.end(),
                  node) == base_combinator_nodes.end()) {
      combinator_nodes.push_back(node);
    }
  }

  is_dirty = false;
}

// Returns true if the matching state was modified.
bool UpdateElementRuleMatchingState(HTMLElement* element) {
  SelectorTree* selector_tree = element->node_document()->selector_tree();
  bool sibling_matching_active = selector_tree->has_sibling_combinators();

  // Retrieve the parent and previous sibling of the current element.
  HTMLElement* parent = element->parent_element()
                            ? element->parent_element()->AsHTMLElement()
                            : NULL;
  HTMLElement* previous_sibling =
      sibling_matching_active && element->previous_element_sibling()
          ? element->previous_element_sibling()->AsHTMLElement()
          : NULL;

  // Retrieve the rule matching state of this element, its parent, and its
  // previous sibling.
  HTMLElement::RuleMatchingState* element_matching_state =
      element->rule_matching_state();
  HTMLElement::RuleMatchingState* parent_matching_state =
      parent ? parent->rule_matching_state() : NULL;
  HTMLElement::RuleMatchingState* previous_sibling_matching_state =
      previous_sibling ? previous_sibling->rule_matching_state() : NULL;

  // A parent must always have valid matching rules when its child is being
  // updated.
  DCHECK(!parent || parent->matching_rules_valid());

  // Ensure that the previous sibling has updated matching rules. This is
  // necessary because Document::UpdateComputedStyleOnElementAndAncestor() does
  // not update previous siblings so it is possible for an element to have its
  // computed style updated while previous siblings have invalid matching rules.
  if (previous_sibling) {
    UpdateElementMatchingRules(previous_sibling);
    DCHECK(previous_sibling->matching_rules_valid());
  }

  // Ensure that the required combinator nodes of the parent and previous
  // sibling are up to date. These are lazily updated, so they won't be updated
  // until the first child/next sibling needs them.
  UpdateRuleMatchingStateCombinatorNodes(parent_matching_state,
                                         cssom::kDescendantCombinator);
  UpdateRuleMatchingStateCombinatorNodes(previous_sibling_matching_state,
                                         cssom::kFollowingSiblingCombinator);

  bool matching_nodes_modified = !element_matching_state->is_set;

  // Gather modifications between the element's previous state and current state
  // for each combinator type, and use them to update the element's matching
  // nodes.
  SelectorTree::Nodes* added_nodes = selector_tree->scratchpad_nodes_1();
  SelectorTree::Nodes* removed_nodes = selector_tree->scratchpad_nodes_2();

  // Child combinator
  if (parent_matching_state &&
      GatherNodeModificationsAndUpdateTargetNodes(
          parent_matching_state->matching_nodes,
          &element_matching_state->parent_matching_nodes, added_nodes,
          removed_nodes)) {
    matching_nodes_modified |= UpdateMatchingNodesFromNodeModifications(
        *added_nodes, *removed_nodes, cssom::kChildCombinator, element,
        selector_tree->scratchpad_node_pairs());
  }

  // Descendant combinator
  const SelectorTree::Nodes& parent_descendant_nodes =
      parent_matching_state ? parent_matching_state->descendant_nodes
                            : selector_tree->root_nodes();
  if (GatherNodeModificationsAndUpdateTargetNodes(
          parent_descendant_nodes,
          &element_matching_state->parent_descendant_nodes, added_nodes,
          removed_nodes)) {
    element_matching_state->are_descendant_nodes_dirty = true;
    matching_nodes_modified |= UpdateMatchingNodesFromNodeModifications(
        *added_nodes, *removed_nodes, cssom::kDescendantCombinator, element,
        selector_tree->scratchpad_node_pairs());
  }

  // Siblings only need to be checked if they're active.
  if (sibling_matching_active) {
    const SelectorTree::Nodes empty_nodes{};

    // Next sibling combinator
    const SelectorTree::Nodes& previous_sibling_matching_nodes =
        previous_sibling_matching_state
            ? previous_sibling_matching_state->matching_nodes
            : empty_nodes;
    if (GatherNodeModificationsAndUpdateTargetNodes(
            previous_sibling_matching_nodes,
            &element_matching_state->previous_sibling_matching_nodes,
            added_nodes, removed_nodes)) {
      matching_nodes_modified |= UpdateMatchingNodesFromNodeModifications(
          *added_nodes, *removed_nodes, cssom::kNextSiblingCombinator, element,
          selector_tree->scratchpad_node_pairs());
    }

    // Following sibling combinator
    const SelectorTree::Nodes& previous_sibling_following_sibling_nodes =
        previous_sibling_matching_state
            ? previous_sibling_matching_state->following_sibling_nodes
            : empty_nodes;
    if (GatherNodeModificationsAndUpdateTargetNodes(
            previous_sibling_following_sibling_nodes,
            &element_matching_state->previous_sibling_following_sibling_nodes,
            added_nodes, removed_nodes)) {
      element_matching_state->are_following_sibling_nodes_dirty = true;
      matching_nodes_modified |= UpdateMatchingNodesFromNodeModifications(
          *added_nodes, *removed_nodes, cssom::kFollowingSiblingCombinator,
          element, selector_tree->scratchpad_node_pairs());
    }
  }

  element_matching_state->is_set = true;

  // Matching node modifications may impact combinator nodes, so they must be
  // dirtied. However, they are lazily updated the first time that they are
  // needed by a child/following sibling, rather than immediately updated. This
  // prevents unnecessary updates of leaf elements and last sibling elements.
  if (matching_nodes_modified) {
    element_matching_state->are_descendant_nodes_dirty = true;
    element_matching_state->are_following_sibling_nodes_dirty = true;
  }

  return matching_nodes_modified;
}

void UpdateElementMatchingRulesFromRuleMatchingState(HTMLElement* element) {
  Document* element_document = element->node_document();

  // Store the element's and its pseudo element's old matching rules so that
  // they can be compared to the new matching rules after they are generated.
  cssom::RulesWithCascadePrecedence* element_old_matching_rules =
      element_document->scratchpad_html_element_matching_rules();
  *element_old_matching_rules = std::move(*element->matching_rules());
  element->matching_rules()->clear();

  for (int type = 0; type < kMaxPseudoElementType; ++type) {
    PseudoElement* pseudo_element =
        element->pseudo_element(PseudoElementType(type));
    if (pseudo_element) {
      cssom::RulesWithCascadePrecedence* old_pseudo_element_matching_rules =
          element_document->scratchpad_pseudo_element_matching_rules(
              PseudoElementType(type));
      *old_pseudo_element_matching_rules =
          std::move(*pseudo_element->matching_rules());
      pseudo_element->matching_rules()->clear();
    }
  }

  // Walk all matching nodes, generating matching rules for the element and
  // its pseudo elements from them.
  for (const auto& node : element->rule_matching_state()->matching_nodes) {
    // Determine the matching rules that this specific node targets. If the
    // node does not have a pseudo element, then this will be the element's
    // matching rules; otherwise, it'll be the matching rules associated with
    // the pseudo element's type.
    cssom::RulesWithCascadePrecedence* target_matching_rules;

    cssom::PseudoElement* pseudo_element =
        node->compound_selector()->pseudo_element();
    if (!pseudo_element) {
      target_matching_rules = element->matching_rules();
    } else {
      PseudoElementType pseudo_element_type = kNotPseudoElementType;

      if (pseudo_element->AsAfterPseudoElement()) {
        pseudo_element_type = kAfterPseudoElementType;
      } else if (pseudo_element->AsBeforePseudoElement()) {
        pseudo_element_type = kBeforePseudoElementType;
      } else {
        NOTREACHED();
      }

      // Make sure the pseudo element exists under element. If not, create it
      // and clear out the old matching rules since the pseudo element had no
      // pre-existing matching rules.
      if (!element->pseudo_element(pseudo_element_type)) {
        element->SetPseudoElement(
            pseudo_element_type,
            base::WrapUnique(new dom::PseudoElement(element)));

        cssom::RulesWithCascadePrecedence* old_pseudo_element_matching_rules =
            element_document->scratchpad_pseudo_element_matching_rules(
                PseudoElementType(pseudo_element_type));
        old_pseudo_element_matching_rules->clear();
      }

      target_matching_rules =
          element->pseudo_element(pseudo_element_type)->matching_rules();
    }

    // Add all of the node's rules to the target matching rules.
    for (const auto& weak_rule : node->rules()) {
      const auto rule = weak_rule.get();
      if (!rule) {
        continue;
      }
      DCHECK(rule->parent_style_sheet());
      cssom::CascadePrecedence precedence(
          pseudo_element ? cssom::kNormalOverride
                         : rule->parent_style_sheet()->origin(),
          node->cumulative_specificity(),
          cssom::Appearance(rule->parent_style_sheet()->index(),
                            rule->index()));
      target_matching_rules->push_back(std::make_pair(rule, precedence));
    }
  }

  // Check for if the newly generated matching rules are different for the
  // element or its pseudo elements.
  if (*element_old_matching_rules != *element->matching_rules()) {
    element->OnMatchingRulesModified();
  }

  for (int type = 0; type < kMaxPseudoElementType; ++type) {
    PseudoElement* pseudo_element =
        element->pseudo_element(PseudoElementType(type));
    if (pseudo_element) {
      cssom::RulesWithCascadePrecedence* old_pseudo_element_matching_rules =
          element_document->scratchpad_pseudo_element_matching_rules(
              PseudoElementType(type));
      if (*old_pseudo_element_matching_rules !=
          *pseudo_element->matching_rules()) {
        pseudo_element->set_computed_style_invalid();
        element->OnPseudoElementMatchingRulesModified();
      }
    }
  }
}

}  // namespace

//////////////////////////////////////////////////////////////////////////
// Public APIs
//////////////////////////////////////////////////////////////////////////

void UpdateElementMatchingRules(HTMLElement* element) {
  DCHECK(element);
  DCHECK(element->node_document());
  if (element->matching_rules_valid()) {
    return;
  }

  // Only update the matching rules if the rule matching state is modified.
  if (UpdateElementRuleMatchingState(element)) {
    UpdateElementMatchingRulesFromRuleMatchingState(element);
  }

  element->set_matching_rules_valid();
}

scoped_refptr<Element> QuerySelector(Node* node, const std::string& selectors,
                                     cssom::CSSParser* css_parser) {
  DCHECK(css_parser);

  // Generate a rule with the given selectors and no style.
  scoped_refptr<cssom::CSSRule> css_rule =
      css_parser->ParseRule(selectors + " {}", node->GetInlineSourceLocation());
  if (!css_rule) {
    return NULL;
  }
  scoped_refptr<cssom::CSSStyleRule> css_style_rule =
      css_rule->AsCSSStyleRule();
  if (!css_style_rule) {
    return NULL;
  }

  // Iterate through the descendants of the node and find the first matching
  // element if any.
  NodeDescendantsIterator iterator(node);
  Node* child = iterator.First();
  while (child) {
    if (child->IsElement()) {
      scoped_refptr<Element> element = child->AsElement();
      if (MatchRuleAndElement(css_style_rule, element)) {
        return element;
      }
    }
    child = iterator.Next();
  }
  return NULL;
}

bool MatchRuleAndElement(cssom::CSSStyleRule* rule, Element* element) {
  for (cssom::Selectors::const_iterator selector_iterator =
           rule->selectors().begin();
       selector_iterator != rule->selectors().end(); ++selector_iterator) {
    DCHECK(*selector_iterator);
    if (MatchSelectorAndElement(selector_iterator->get(), element, true)) {
      return true;
    }
  }
  return false;
}

scoped_refptr<NodeList> QuerySelectorAll(Node* node,
                                         const std::string& selectors,
                                         cssom::CSSParser* css_parser) {
  DCHECK(css_parser);

  scoped_refptr<NodeList> node_list = new NodeList();

  // Generate a rule with the given selectors and no style.
  scoped_refptr<cssom::CSSRule> css_rule =
      css_parser->ParseRule(selectors + " {}", node->GetInlineSourceLocation());
  if (!css_rule) {
    return node_list;
  }
  scoped_refptr<cssom::CSSStyleRule> css_style_rule =
      css_rule->AsCSSStyleRule();
  if (!css_style_rule) {
    return node_list;
  }

  // Iterate through the descendants of the node and find the matching elements.
  NodeDescendantsIterator iterator(node);
  Node* child = iterator.First();
  while (child) {
    if (child->IsElement()) {
      scoped_refptr<Element> element = child->AsElement();
      if (MatchRuleAndElement(css_style_rule, element)) {
        node_list->AppendNode(element);
      }
    }
    child = iterator.Next();
  }
  return node_list;
}

}  // namespace dom
}  // namespace cobalt
