/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
 * Copyright (C) 2011 Google Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "config.h"
#include "EventDispatcher.h"

#include "Event.h"
#include "EventContext.h"
#include "EventTarget.h"
#include "FrameView.h"
#include "InspectorInstrumentation.h"
#include "MouseEvent.h"
#include "Node.h"
#include "ScopedEventQueue.h"

#if ENABLE(SVG)
#include "SVGElementInstance.h"
#include "SVGNames.h"
#include "SVGUseElement.h"
#endif

#include "UIEvent.h"
#include "UIEventWithKeyState.h"
#include "WindowEventContext.h"

#include <wtf/RefPtr.h>

namespace WebCore {

static HashSet<Node*>* gNodesDispatchingSimulatedClicks = 0;

bool EventDispatcher::dispatchEvent(Node* node, const EventDispatchMediator& mediator)
{
    ASSERT(!eventDispatchForbidden());

    EventDispatcher dispatcher(node);
    return mediator.dispatchEvent(&dispatcher);
}

static EventTarget* findElementInstance(Node* referenceNode)
{
#if ENABLE(SVG)
    // Spec: The event handling for the non-exposed tree works as if the referenced element had been textually included
    // as a deeply cloned child of the 'use' element, except that events are dispatched to the SVGElementInstance objects
    for (Node* n = referenceNode; n; n = n->parentNode()) {
        if (!n->isSVGShadowRoot() || !n->isSVGElement())
            continue;

        Element* shadowTreeParentElement = n->svgShadowHost();
        ASSERT(shadowTreeParentElement->hasTagName(SVGNames::useTag));

        if (SVGElementInstance* instance = static_cast<SVGUseElement*>(shadowTreeParentElement)->instanceForShadowTreeElement(referenceNode))
            return instance;
    }
#else
    // SVG elements with SVG disabled should not be possible.
    ASSERT_NOT_REACHED();
#endif

    return referenceNode;
}

inline static EventTarget* eventTargetRespectingSVGTargetRules(Node* referenceNode)
{
    ASSERT(referenceNode);

    return referenceNode->isSVGElement() ? findElementInstance(referenceNode) : referenceNode;
}

void EventDispatcher::dispatchScopedEvent(Node* node, PassRefPtr<Event> event)
{
    // We need to set the target here because it can go away by the time we actually fire the event.
    event->setTarget(eventTargetRespectingSVGTargetRules(node));

    ScopedEventQueue::instance()->enqueueEvent(event);
}

void EventDispatcher::dispatchSimulatedClick(Node* node, PassRefPtr<Event> underlyingEvent, bool sendMouseEvents, bool showPressedLook)
{
    if (node->disabled())
        return;

    EventDispatcher dispatcher(node);

    if (!gNodesDispatchingSimulatedClicks)
        gNodesDispatchingSimulatedClicks = new HashSet<Node*>;
    else if (gNodesDispatchingSimulatedClicks->contains(node))
        return;

    gNodesDispatchingSimulatedClicks->add(node);

    // send mousedown and mouseup before the click, if requested
    if (sendMouseEvents)
        dispatcher.dispatchEvent(SimulatedMouseEvent::create(eventNames().mousedownEvent, node->document()->defaultView(), underlyingEvent));
    node->setActive(true, showPressedLook);
    if (sendMouseEvents)
        dispatcher.dispatchEvent(SimulatedMouseEvent::create(eventNames().mouseupEvent, node->document()->defaultView(), underlyingEvent));
    node->setActive(false);

    // always send click
    dispatcher.dispatchEvent(SimulatedMouseEvent::create(eventNames().clickEvent, node->document()->defaultView(), underlyingEvent));

    gNodesDispatchingSimulatedClicks->remove(node);
}

static inline bool isShadowRootOrSVGShadowRoot(const Node* node)
{
    return node->isShadowRoot() || node->isSVGShadowRoot();
}

PassRefPtr<EventTarget> EventDispatcher::adjustToShadowBoundaries(PassRefPtr<Node> relatedTarget, const Vector<Node*> relatedTargetAncestors)
{
    Vector<EventContext>::const_iterator lowestCommonBoundary = m_ancestors.end();
    // Assume divergent boundary is the relatedTarget itself (in other words, related target ancestor chain does not cross any shadow DOM boundaries).
    Vector<Node*>::const_iterator firstDivergentBoundary = relatedTargetAncestors.begin();

    Vector<EventContext>::const_iterator targetAncestor = m_ancestors.end();
    // Walk down from the top, looking for lowest common ancestor, also monitoring shadow DOM boundaries.
    bool diverged = false;
    for (Vector<Node*>::const_iterator i = relatedTargetAncestors.end() - 1; i >= relatedTargetAncestors.begin(); --i) {
        if (diverged) {
            if (isShadowRootOrSVGShadowRoot(*i)) {
                firstDivergentBoundary = i + 1;
                break;
            }
            continue;
        }

        if (targetAncestor == m_ancestors.begin()) {
            diverged = true;
            continue;
        }

        targetAncestor--;

        if (isShadowRootOrSVGShadowRoot(*i))
            lowestCommonBoundary = targetAncestor;

        if ((*i) != (*targetAncestor).node())
            diverged = true;
    }

    if (!diverged) {
        // The relatedTarget is an ancestor or shadowHost of the target.
        if (m_node->shadowHost() == relatedTarget.get())
            lowestCommonBoundary = m_ancestors.begin();
    } else if ((*firstDivergentBoundary) == m_node.get()) {
        // Since ancestors does not contain target itself, we must account
        // for the possibility that target is a shadowHost of relatedTarget
        // and thus serves as the lowestCommonBoundary.
        // Luckily, in this case the firstDivergentBoundary is target.
        lowestCommonBoundary = m_ancestors.begin();
    }

    // Trim ancestors to lowestCommonBoundary to keep events inside of the common shadow DOM subtree.
    if (lowestCommonBoundary != m_ancestors.end())
        m_ancestors.shrink(lowestCommonBoundary - m_ancestors.begin());
    // Set event's related target to the first encountered shadow DOM boundary in the divergent subtree.
    return firstDivergentBoundary != relatedTargetAncestors.begin() ? *firstDivergentBoundary : relatedTarget;
}

inline static bool ancestorsCrossShadowBoundaries(const Vector<EventContext>& ancestors)
{
    return ancestors.isEmpty() || ancestors.first().node() == ancestors.last().node();
}

// FIXME: Once https://bugs.webkit.org/show_bug.cgi?id=52963 lands, this should
// be greatly improved. See https://bugs.webkit.org/show_bug.cgi?id=54025.
PassRefPtr<EventTarget> EventDispatcher::adjustRelatedTarget(Event* event, PassRefPtr<EventTarget> prpRelatedTarget)
{
    if (!prpRelatedTarget)
        return 0;

    RefPtr<Node> relatedTarget = prpRelatedTarget->toNode();
    if (!relatedTarget)
        return 0;

    Node* target = m_node.get();
    if (!target)
        return prpRelatedTarget;

    ensureEventAncestors(event);

    // Calculate early if the common boundary is even possible by looking at
    // ancestors size and if the retargeting has occured (indicating the presence of shadow DOM boundaries).
    // If there are no boundaries detected, the target and related target can't have a common boundary.
    bool noCommonBoundary = ancestorsCrossShadowBoundaries(m_ancestors);

    Vector<Node*> relatedTargetAncestors;
    Node* outermostShadowBoundary = relatedTarget.get();
    for (Node* n = outermostShadowBoundary; n; n = n->parentOrHostNode()) {
        if (isShadowRootOrSVGShadowRoot(n))
            outermostShadowBoundary = n->parentOrHostNode();
        if (!noCommonBoundary)
            relatedTargetAncestors.append(n);
    }

    // Short-circuit the fast case when we know there is no need to calculate a common boundary.
    if (noCommonBoundary)
        return outermostShadowBoundary;

    return adjustToShadowBoundaries(relatedTarget.release(), relatedTargetAncestors);
}

EventDispatcher::EventDispatcher(Node* node)
    : m_node(node)
    , m_ancestorsInitialized(false)
{
    ASSERT(node);
    m_view = node->document()->view();
}

void EventDispatcher::ensureEventAncestors(Event* event)
{
    EventDispatchBehavior behavior = determineDispatchBehavior(event);

    if (!m_node->inDocument())
        return;

    if (m_ancestorsInitialized)
        return;

    m_ancestorsInitialized = true;

    Node* ancestor = m_node.get();
    EventTarget* target = eventTargetRespectingSVGTargetRules(ancestor);
    bool shouldSkipNextAncestor = false;
    while (true) {
        bool isSVGShadowRoot = ancestor->isSVGShadowRoot();
        if (isSVGShadowRoot || ancestor->isShadowRoot()) {
            if (behavior == StayInsideShadowDOM)
                return;
#if ENABLE(SVG)
            ancestor = isSVGShadowRoot ? ancestor->svgShadowHost() : ancestor->shadowHost();
#else
            ancestor = ancestor->shadowHost();
#endif
            if (!shouldSkipNextAncestor)
                target = ancestor;
        } else
            ancestor = ancestor->parentNodeGuaranteedHostFree();

        if (!ancestor)
            return;

#if ENABLE(SVG)
        // Skip SVGShadowTreeRootElement.
        shouldSkipNextAncestor = ancestor->isSVGShadowRoot();
        if (shouldSkipNextAncestor)
            continue;
#endif
        // FIXME: Unroll the extra loop inside eventTargetRespectingSVGTargetRules into this loop.
        m_ancestors.append(EventContext(ancestor, eventTargetRespectingSVGTargetRules(ancestor), target));
    }
}

bool EventDispatcher::dispatchEvent(PassRefPtr<Event> event)
{
    event->setTarget(eventTargetRespectingSVGTargetRules(m_node.get()));

    ASSERT(!eventDispatchForbidden());
    ASSERT(event->target());
    ASSERT(!event->type().isNull()); // JavaScript code can create an event with an empty name, but not null.

    RefPtr<EventTarget> originalTarget = event->target();
    ensureEventAncestors(event.get());

    WindowEventContext windowContext(event.get(), m_node.get(), topEventContext());

    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEvent(m_node->document(), *event, windowContext.window(), m_node.get(), m_ancestors);

    // Give the target node a chance to do some work before DOM event handlers get a crack.
    void* data = m_node->preDispatchEventHandler(event.get());
    if (event->propagationStopped())
        goto doneDispatching;

    // Trigger capturing event handlers, starting at the top and working our way down.
    event->setEventPhase(Event::CAPTURING_PHASE);

    if (windowContext.handleLocalEvents(event.get()) && event->propagationStopped())
        goto doneDispatching;

    for (size_t i = m_ancestors.size(); i; --i) {
        m_ancestors[i - 1].handleLocalEvents(event.get());
        if (event->propagationStopped())
            goto doneDispatching;
    }

    event->setEventPhase(Event::AT_TARGET);
    event->setTarget(originalTarget.get());
    event->setCurrentTarget(eventTargetRespectingSVGTargetRules(m_node.get()));
    m_node->handleLocalEvents(event.get());
    if (event->propagationStopped())
        goto doneDispatching;

    if (event->bubbles() && !event->cancelBubble()) {
        // Trigger bubbling event handlers, starting at the bottom and working our way up.
        event->setEventPhase(Event::BUBBLING_PHASE);

        size_t size = m_ancestors.size();
        for (size_t i = 0; i < size; ++i) {
            m_ancestors[i].handleLocalEvents(event.get());
            if (event->propagationStopped() || event->cancelBubble())
                goto doneDispatching;
        }
        windowContext.handleLocalEvents(event.get());
    }

doneDispatching:
    event->setTarget(originalTarget.get());
    event->setCurrentTarget(0);
    event->setEventPhase(0);

    // Pass the data from the preDispatchEventHandler to the postDispatchEventHandler.
    m_node->postDispatchEventHandler(event.get(), data);

    // Call default event handlers. While the DOM does have a concept of preventing
    // default handling, the detail of which handlers are called is an internal
    // implementation detail and not part of the DOM.
    if (!event->defaultPrevented() && !event->defaultHandled()) {
        // Non-bubbling events call only one default event handler, the one for the target.
        m_node->defaultEventHandler(event.get());
        ASSERT(!event->defaultPrevented());
        if (event->defaultHandled())
            goto doneWithDefault;
        // For bubbling events, call default event handlers on the same targets in the
        // same order as the bubbling phase.
        if (event->bubbles()) {
            size_t size = m_ancestors.size();
            for (size_t i = 0; i < size; ++i) {
                m_ancestors[i].node()->defaultEventHandler(event.get());
                ASSERT(!event->defaultPrevented());
                if (event->defaultHandled())
                    goto doneWithDefault;
            }
        }
    }

doneWithDefault:

    // Ensure that after event dispatch, the event's target object is the
    // outermost shadow DOM boundary.
    event->setTarget(windowContext.target());
    event->setCurrentTarget(0);
    InspectorInstrumentation::didDispatchEvent(cookie);

    return !event->defaultPrevented();
}

const EventContext* EventDispatcher::topEventContext()
{
    return m_ancestors.isEmpty() ? 0 : &m_ancestors.last();
}

EventDispatchBehavior EventDispatcher::determineDispatchBehavior(Event* event)
{
    // Per XBL 2.0 spec, mutation events should never cross shadow DOM boundary:
    // http://dev.w3.org/2006/xbl2/#event-flow-and-targeting-across-shadow-s
    if (event->isMutationEvent())
        return StayInsideShadowDOM;

    // WebKit never allowed selectstart event to cross the the shadow DOM boundary.
    // Changing this breaks existing sites.
    // See https://bugs.webkit.org/show_bug.cgi?id=52195 for details.
    if (event->type() == eventNames().selectstartEvent)
        return StayInsideShadowDOM;

    return RetargetEvent;
}

}

