// 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/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
