/*
 * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
 * Copyright (C) 2006, 2009 Apple Inc.
 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "third_party/blink/renderer/core/xml/xpath_path.h"

#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/node_traversal.h"
#include "third_party/blink/renderer/core/xml/xpath_predicate.h"
#include "third_party/blink/renderer/core/xml/xpath_step.h"
#include "third_party/blink/renderer/core/xml/xpath_value.h"

namespace blink {
namespace xpath {

Filter::Filter(Expression* expr, HeapVector<Member<Predicate>>& predicates)
    : expr_(expr) {
  predicates_.swap(predicates);
  SetIsContextNodeSensitive(expr_->IsContextNodeSensitive());
  SetIsContextPositionSensitive(expr_->IsContextPositionSensitive());
  SetIsContextSizeSensitive(expr_->IsContextSizeSensitive());
}

Filter::~Filter() = default;

void Filter::Trace(blink::Visitor* visitor) {
  visitor->Trace(expr_);
  visitor->Trace(predicates_);
  Expression::Trace(visitor);
}

Value Filter::Evaluate(EvaluationContext& evaluation_context) const {
  Value v = expr_->Evaluate(evaluation_context);

  NodeSet& nodes = v.ModifiableNodeSet(evaluation_context);
  nodes.Sort();

  for (const auto& predicate : predicates_) {
    NodeSet* new_nodes = NodeSet::Create();
    evaluation_context.size = nodes.size();
    evaluation_context.position = 0;

    for (const auto& node : nodes) {
      evaluation_context.node = node;
      ++evaluation_context.position;

      if (predicate->Evaluate(evaluation_context))
        new_nodes->Append(node);
    }
    nodes.Swap(*new_nodes);
  }

  return v;
}

LocationPath::LocationPath() : absolute_(false) {
  SetIsContextNodeSensitive(true);
}

LocationPath::~LocationPath() = default;

void LocationPath::Trace(blink::Visitor* visitor) {
  visitor->Trace(steps_);
  Expression::Trace(visitor);
}

Value LocationPath::Evaluate(EvaluationContext& evaluation_context) const {
  EvaluationContext cloned_context = evaluation_context;
  // http://www.w3.org/TR/xpath/
  // Section 2, Location Paths:
  // "/ selects the document root (which is always the parent of the document
  // element)"
  // "A / by itself selects the root node of the document containing the context
  // node."
  // In the case of a tree that is detached from the document, we violate
  // the spec and treat / as the root node of the detached tree.
  // This is for compatibility with Firefox, and also seems like a more
  // logical treatment of where you would expect the "root" to be.
  Node* context = evaluation_context.node.Get();
  if (absolute_ && context->getNodeType() != Node::kDocumentNode) {
    if (context->isConnected())
      context = context->ownerDocument();
    else
      context = &NodeTraversal::HighestAncestorOrSelf(*context);
  }

  NodeSet* nodes = NodeSet::Create();
  nodes->Append(context);
  Evaluate(cloned_context, *nodes);

  return Value(nodes, Value::kAdopt);
}

void LocationPath::Evaluate(EvaluationContext& context, NodeSet& nodes) const {
  bool result_is_sorted = nodes.IsSorted();

  for (const auto& step : steps_) {
    NodeSet* new_nodes = NodeSet::Create();
    HeapHashSet<Member<Node>> new_nodes_set;

    bool need_to_check_for_duplicate_nodes =
        !nodes.SubtreesAreDisjoint() ||
        (step->GetAxis() != Step::kChildAxis &&
         step->GetAxis() != Step::kSelfAxis &&
         step->GetAxis() != Step::kDescendantAxis &&
         step->GetAxis() != Step::kDescendantOrSelfAxis &&
         step->GetAxis() != Step::kAttributeAxis);

    if (need_to_check_for_duplicate_nodes)
      result_is_sorted = false;

    // This is a simplified check that can be improved to handle more cases.
    if (nodes.SubtreesAreDisjoint() && (step->GetAxis() == Step::kChildAxis ||
                                        step->GetAxis() == Step::kSelfAxis))
      new_nodes->MarkSubtreesDisjoint(true);

    for (const auto& input_node : nodes) {
      NodeSet* matches = NodeSet::Create();
      step->Evaluate(context, input_node, *matches);

      if (!matches->IsSorted())
        result_is_sorted = false;

      for (const auto& node : *matches) {
        if (!need_to_check_for_duplicate_nodes ||
            new_nodes_set.insert(node).is_new_entry)
          new_nodes->Append(node);
      }
    }

    nodes.Swap(*new_nodes);
  }

  nodes.MarkSorted(result_is_sorted);
}

void LocationPath::AppendStep(Step* step) {
  unsigned step_count = steps_.size();
  if (step_count && OptimizeStepPair(steps_[step_count - 1], step))
    return;
  step->Optimize();
  steps_.push_back(step);
}

void LocationPath::InsertFirstStep(Step* step) {
  if (steps_.size() && OptimizeStepPair(step, steps_[0])) {
    steps_[0] = step;
    return;
  }
  step->Optimize();
  steps_.insert(0, step);
}

Path::Path(Expression* filter, LocationPath* path)
    : filter_(filter), path_(path) {
  SetIsContextNodeSensitive(filter->IsContextNodeSensitive());
  SetIsContextPositionSensitive(filter->IsContextPositionSensitive());
  SetIsContextSizeSensitive(filter->IsContextSizeSensitive());
}

Path::~Path() = default;

void Path::Trace(blink::Visitor* visitor) {
  visitor->Trace(filter_);
  visitor->Trace(path_);
  Expression::Trace(visitor);
}

Value Path::Evaluate(EvaluationContext& context) const {
  Value v = filter_->Evaluate(context);

  NodeSet& nodes = v.ModifiableNodeSet(context);
  path_->Evaluate(context, nodes);

  return v;
}

}  // namespace xpath

}  // namespace blink
