/*
 * Copyright (C) 2010 Google Inc. All Rights Reserved.
 * Copyright (C) 2013 Apple 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 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 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 "config.h"
#include "DocumentEventQueue.h"

#include "DOMWindow.h"
#include "Document.h"
#include "Event.h"
#include "EventNames.h"
#include "SuspendableTimer.h"
#include <wtf/Ref.h>

namespace WebCore {
    
class DocumentEventQueue::Timer final : public SuspendableTimer {
public:
    Timer(DocumentEventQueue& eventQueue)
        : SuspendableTimer(eventQueue.m_document)
        , m_eventQueue(eventQueue)
    {
    }

private:
    void fired() override
    {
        ASSERT(!isSuspended());
        m_eventQueue.pendingEventTimerFired();
    }

    const char* activeDOMObjectName() const override { return "DocumentEventQueueTimer"; }

    DocumentEventQueue& m_eventQueue;
};

DocumentEventQueue::DocumentEventQueue(Document& document)
    : m_document(document)
    , m_pendingEventTimer(std::make_unique<Timer>(*this))
    , m_isClosed(false)
{
    m_pendingEventTimer->suspendIfNeeded();
}

DocumentEventQueue::~DocumentEventQueue() = default;

bool DocumentEventQueue::enqueueEvent(Ref<Event>&& event)
{
    ASSERT(event->target());
    ASSERT(!m_queuedEvents.contains(event.ptr()));

    if (m_isClosed)
        return false;

    m_queuedEvents.add(event.ptr());
    if (!m_pendingEventTimer->isActive())
        m_pendingEventTimer->startOneShot(0_s);
    return true;
}

void DocumentEventQueue::enqueueOrDispatchScrollEvent(Node& target)
{
    ASSERT(&target.document() == &m_document);

    // Per the W3C CSSOM View Module, scroll events fired at the document should bubble, others should not.
    bool bubbles = target.isDocumentNode();
    bool cancelable = false;
    enqueueScrollEvent(target, bubbles, cancelable);
}

void DocumentEventQueue::enqueueScrollEvent(EventTarget& target, bool bubbles, bool cancelable)
{
    if (m_isClosed)
        return;

    if (!m_document.hasListenerType(Document::SCROLL_LISTENER))
        return;

    if (!m_targetsWithQueuedScrollEvents.add(&target).isNewEntry)
        return;

    Ref<Event> scrollEvent = Event::create(eventNames().scrollEvent, bubbles, cancelable);
    scrollEvent->setTarget(&target);
    enqueueEvent(WTFMove(scrollEvent));
}

void DocumentEventQueue::enqueueResizeEvent(EventTarget& target, bool bubbles, bool cancelable)
{
    if (m_isClosed)
        return;

    if (!m_document.hasListenerType(Document::RESIZE_LISTENER))
        return;

    if (!m_targetsWithQueuedResizeEvents.add(&target).isNewEntry)
        return;

    Ref<Event> resizeEvent = Event::create(eventNames().resizeEvent, bubbles, cancelable);
    resizeEvent->setTarget(&target);
    enqueueEvent(WTFMove(resizeEvent));
}

bool DocumentEventQueue::cancelEvent(Event& event)
{
    bool found = m_queuedEvents.remove(&event);
    if (m_queuedEvents.isEmpty())
        m_pendingEventTimer->cancel();
    return found;
}

void DocumentEventQueue::close()
{
    m_isClosed = true;
    m_pendingEventTimer->cancel();
    m_queuedEvents.clear();
}

void DocumentEventQueue::pendingEventTimerFired()
{
    ASSERT(!m_pendingEventTimer->isActive());
    ASSERT(!m_queuedEvents.isEmpty());

    m_targetsWithQueuedScrollEvents.clear();
    m_targetsWithQueuedResizeEvents.clear();

    // Insert a marker for where we should stop.
    ASSERT(!m_queuedEvents.contains(nullptr));
    m_queuedEvents.add(nullptr);

    Ref<Document> protect(m_document);

    while (!m_queuedEvents.isEmpty()) {
        RefPtr<Event> event = m_queuedEvents.takeFirst();
        if (!event)
            break;
        dispatchEvent(*event);
    }
}

void DocumentEventQueue::dispatchEvent(Event& event)
{
    // FIXME: Why do we have this special case here instead of a virtual function?
    // If it's not safe to call EventTarget::dispatchEvent on a DOMWindow, then we
    // likely have problems elsewhere.
    auto& eventTarget = *event.target();
    if (is<DOMWindow>(eventTarget))
        downcast<DOMWindow>(eventTarget).dispatchEvent(event, nullptr);
    else
        eventTarget.dispatchEvent(event);
}

}
