// 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/cssom/selector_tree.h"

#include <set>

#if defined(COBALT_ENABLE_VERSION_COMPATIBILITY_VALIDATIONS)
#include "cobalt/base/version_compatibility.h"
#endif  // defined(COBALT_ENABLE_VERSION_COMPATIBILITY_VALIDATIONS)
#include "cobalt/cssom/complex_selector.h"
#include "cobalt/cssom/compound_selector.h"
#include "cobalt/cssom/css_style_rule.h"

namespace cobalt {
namespace cssom {

bool SelectorTree::CompoundNodeLessThan::operator()(
    const CompoundSelector* lhs, const CompoundSelector* rhs) const {
  return *lhs < *rhs;
}

SelectorTree::Node::Node()
    : combinator_mask_(0),
      compound_selector_(NULL),
      selector_mask_(0),
      pseudo_class_mask_(0) {}

SelectorTree::Node::Node(CompoundSelector* compound_selector,
                         Specificity parent_specificity)
    : combinator_mask_(0),
      compound_selector_(compound_selector),
      cumulative_specificity_(parent_specificity),
      selector_mask_(0),
      pseudo_class_mask_(0) {
  cumulative_specificity_.AddFrom(compound_selector_->GetSpecificity());
}

void SelectorTree::AppendRule(CSSStyleRule* rule) {
  for (Selectors::const_iterator it = rule->selectors().begin();
       it != rule->selectors().end(); ++it) {
    DCHECK((*it)->AsComplexSelector());
    Node* node = GetOrCreateNodeForComplexSelector((*it)->AsComplexSelector());
    node->rules().push_back(base::AsWeakPtr(rule));
  }
}

void SelectorTree::RemoveRule(CSSStyleRule* rule) {
  for (Selectors::const_iterator it = rule->selectors().begin();
       it != rule->selectors().end(); ++it) {
    DCHECK((*it)->AsComplexSelector());
    Node* node = GetOrCreateNodeForComplexSelector((*it)->AsComplexSelector());
    for (Rules::iterator remove_it = node->rules().begin();
         remove_it != node->rules().end(); ++remove_it) {
      if (*remove_it == rule) {
        node->rules().erase(remove_it);
        break;
      }
    }
  }
}

const SelectorTree::OwnedNodes& SelectorTree::children(
    const Node* node, CombinatorType combinator) {
  return owned_nodes_map_[std::make_pair(node, combinator)];
}

#if defined(COBALT_ENABLE_VERSION_COMPATIBILITY_VALIDATIONS)
namespace {

// This uses the old CompoundSelector compare logic that had a bug where 'not'
// pseudo classes with the same prefix would be treated as matching, regardless
// of their arguments.
struct PreVersion16CompoundSelectorLessThan {
  bool operator()(const CompoundSelector* lhs,
                  const CompoundSelector* rhs) const {
    const CompoundSelector::SimpleSelectors& lhs_simple_selectors =
        lhs->simple_selectors();
    const CompoundSelector::SimpleSelectors& rhs_simple_selectors =
        rhs->simple_selectors();
    if (lhs_simple_selectors.size() < rhs_simple_selectors.size()) {
      return true;
    }
    if (lhs_simple_selectors.size() > rhs_simple_selectors.size()) {
      return false;
    }

    for (size_t i = 0; i < lhs_simple_selectors.size(); ++i) {
      if (lhs_simple_selectors[i]->type() < rhs_simple_selectors[i]->type()) {
        return true;
      }
      if (lhs_simple_selectors[i]->type() > rhs_simple_selectors[i]->type()) {
        return false;
      }
      if (lhs_simple_selectors[i]->prefix() <
          rhs_simple_selectors[i]->prefix()) {
        return true;
      }
      if (lhs_simple_selectors[i]->prefix() >
          rhs_simple_selectors[i]->prefix()) {
        return false;
      }
      if (lhs_simple_selectors[i]->text() < rhs_simple_selectors[i]->text()) {
        return true;
      }
      if (lhs_simple_selectors[i]->text() > rhs_simple_selectors[i]->text()) {
        return false;
      }
    }

    return false;
  }
};

bool HasNotPseudoClassCompatibilityViolations(
    const SelectorTree::OwnedNodesMap& owned_nodes_map) {
  constexpr int kNotPseudoClassCobaltVersionFix = 16;
  if (base::VersionCompatibility::GetInstance()->GetMinimumVersion() >=
      kNotPseudoClassCobaltVersionFix) {
    return false;
  }

  typedef std::set<CompoundSelector*, PreVersion16CompoundSelectorLessThan>
      PreVersion16CompoundSelectorLessThanSet;

  // Walk all of the owned nodes looking for multiple compound selectors within
  // them that are treated as duplicates using the pre-version 16 compound
  // selector less than logic.
  PreVersion16CompoundSelectorLessThanSet unsupported_usage_set;
  for (const auto& owned_nodes_iterator : owned_nodes_map) {
    PreVersion16CompoundSelectorLessThanSet encountered_set;
    for (const auto& node_info : owned_nodes_iterator.second) {
      if (!encountered_set.insert(node_info.first).second) {
        unsupported_usage_set.insert(node_info.first);
      }
    }
  }

  // Log the cases of unsupported usage.
  for (const auto& unsupported_usage_iterator : unsupported_usage_set) {
    const std::string kUnsupportedNotUsageString =
        "Unsupported :not() pseudo class usage found. Multiple negation pseudo "
        "classes with the same prefix but different arguments are not "
        "supported in versions of Cobalt <= 15. Offending selectors: '";

    std::string selectors_string;
    const CompoundSelector::SimpleSelectors& simple_selectors =
        unsupported_usage_iterator->simple_selectors();
    for (const auto& simple_selector : simple_selectors) {
      selectors_string += simple_selector->prefix().c_str();
      if (simple_selector->type() == kPseudoClass &&
          simple_selector->GetContainedCompoundSelector() != NULL) {
        selectors_string += "not(...)";
      } else {
        selectors_string += simple_selector->text().c_str();
      }
    }

    base::VersionCompatibility::GetInstance()->ReportViolation(
        kUnsupportedNotUsageString + selectors_string);
  }
  return !unsupported_usage_set.empty();
}

}  // namespace

bool SelectorTree::ValidateVersionCompatibility() const {
  return !HasNotPseudoClassCompatibilityViolations(owned_nodes_map_);
}
#endif  // defined(COBALT_ENABLE_VERSION_COMPATIBILITY_VALIDATIONS)

SelectorTree::Node* SelectorTree::GetOrCreateNodeForComplexSelector(
    ComplexSelector* complex_selector) {
  CompoundSelector* selector = complex_selector->first_selector();
  Node* node = GetOrCreateNodeForCompoundSelector(selector, &root_node_,
                                                  kDescendantCombinator);

  while (selector->right_combinator()) {
    Combinator* combinator = selector->right_combinator();
    selector = combinator->right_selector();
    node = GetOrCreateNodeForCompoundSelector(selector, node,
                                              combinator->GetCombinatorType());
  }

  return node;
}

SelectorTree::Node* SelectorTree::GetOrCreateNodeForCompoundSelector(
    CompoundSelector* compound_selector, Node* parent_node,
    CombinatorType combinator) {
  if (combinator == kNextSiblingCombinator ||
      combinator == kFollowingSiblingCombinator) {
    has_sibling_combinators_ = true;
  }

  OwnedNodes& owned_nodes =
      owned_nodes_map_[std::make_pair(parent_node, combinator)];
  OwnedNodes::iterator child_node_it = owned_nodes.find(compound_selector);
  if (child_node_it != owned_nodes.end()) {
    return child_node_it->second;
  }
  Node* child_node =
      new Node(compound_selector, parent_node->cumulative_specificity());
  parent_node->combinator_mask_ |= (1 << combinator);
  owned_nodes[compound_selector] = child_node;

  (*compound_selector->simple_selectors().begin())
      ->IndexSelectorTreeNode(parent_node, child_node, combinator);
  return child_node;
}

}  // namespace cssom
}  // namespace cobalt
