/*
 * Copyright (C) 2014 Google Inc. All Rights Reserved.
 *
 * 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. OR
 * CONTRIBUTORS 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/dom/events/tree_scope_event_context.h"

#include "third_party/blink/renderer/core/dom/events/event_path.h"
#include "third_party/blink/renderer/core/dom/events/window_event_context.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/dom/static_node_list.h"
#include "third_party/blink/renderer/core/events/touch_event_context.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"

namespace blink {

bool TreeScopeEventContext::IsUnclosedTreeOf(
    const TreeScopeEventContext& other) {
  // Exclude closed nodes if necessary.
  // If a node is in a closed shadow root, or in a tree whose ancestor has a
  // closed shadow root, it should not be visible to nodes above the closed
  // shadow root.

  // (1) If |this| is an ancestor of |other| in tree-of-trees, include it.
  if (IsInclusiveAncestorOf(other))
    return true;

  // (2) If no closed shadow root in ancestors of this, include it.
  if (!ContainingClosedShadowTree())
    return true;

  // (3) If |this| is descendent of |other|, exclude if any closed shadow root
  // in between.
  if (IsDescendantOf(other))
    return !ContainingClosedShadowTree()->IsDescendantOf(other);

// (4) |this| and |other| must be in exclusive branches.
#if DCHECK_IS_ON()
  DCHECK(other.IsExclusivePartOf(*this));
#endif
  return false;
}

HeapVector<Member<EventTarget>>& TreeScopeEventContext::EnsureEventPath(
    EventPath& path) {
  if (event_path_)
    return *event_path_;

  event_path_ = new HeapVector<Member<EventTarget>>();
  LocalDOMWindow* window = path.GetWindowEventContext().Window();
  event_path_->ReserveCapacity(path.size() + (window ? 1 : 0));

  for (auto& context : path.NodeEventContexts()) {
    if (context.GetTreeScopeEventContext().IsUnclosedTreeOf(*this))
      event_path_->push_back(context.GetNode());
  }
  if (window)
    event_path_->push_back(window);
  return *event_path_;
}

TouchEventContext* TreeScopeEventContext::EnsureTouchEventContext() {
  if (!touch_event_context_)
    touch_event_context_ = TouchEventContext::Create();
  return touch_event_context_.Get();
}

TreeScopeEventContext* TreeScopeEventContext::Create(TreeScope& tree_scope) {
  return new TreeScopeEventContext(tree_scope);
}

TreeScopeEventContext::TreeScopeEventContext(TreeScope& tree_scope)
    : tree_scope_(tree_scope),
      containing_closed_shadow_tree_(nullptr),
      pre_order_(-1),
      post_order_(-1) {}

void TreeScopeEventContext::Trace(blink::Visitor* visitor) {
  visitor->Trace(tree_scope_);
  visitor->Trace(target_);
  visitor->Trace(related_target_);
  visitor->Trace(event_path_);
  visitor->Trace(touch_event_context_);
  visitor->Trace(containing_closed_shadow_tree_);
  visitor->Trace(children_);
}

int TreeScopeEventContext::CalculateTreeOrderAndSetNearestAncestorClosedTree(
    int order_number,
    TreeScopeEventContext* nearest_ancestor_closed_tree_scope_event_context) {
  pre_order_ = order_number;
  containing_closed_shadow_tree_ =
      (RootNode().IsShadowRoot() && !ToShadowRoot(RootNode()).IsOpenOrV0())
          ? this
          : nearest_ancestor_closed_tree_scope_event_context;
  for (const auto& context : children_) {
    order_number = context->CalculateTreeOrderAndSetNearestAncestorClosedTree(
        order_number + 1, ContainingClosedShadowTree());
  }
  post_order_ = order_number + 1;

  return order_number + 1;
}

}  // namespace blink
