/*
 * Copyright (C) 2010 Julien Chaffraix <jchaffraix@webkit.org>  All right reserved.
 * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
 *
 * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "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 COPYRIGHT
 * OWNER 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 "XMLHttpRequestProgressEventThrottle.h"

#include "EventNames.h"
#include "EventTarget.h"
#include "XMLHttpRequestProgressEvent.h"

namespace WebCore {

const Seconds XMLHttpRequestProgressEventThrottle::minimumProgressEventDispatchingInterval { 50_ms }; // 50 ms per specification.

XMLHttpRequestProgressEventThrottle::XMLHttpRequestProgressEventThrottle(EventTarget& target)
    : m_target(target)
    , m_dispatchThrottledProgressEventTimer(target.scriptExecutionContext(), *this, &XMLHttpRequestProgressEventThrottle::dispatchThrottledProgressEventTimerFired)
    , m_dispatchDeferredEventsAfterResumingTimer(target.scriptExecutionContext(), *this, &XMLHttpRequestProgressEventThrottle::dispatchDeferredEventsAfterResuming)
{
    m_dispatchThrottledProgressEventTimer.suspendIfNeeded();
    m_dispatchDeferredEventsAfterResumingTimer.suspendIfNeeded();
}

XMLHttpRequestProgressEventThrottle::~XMLHttpRequestProgressEventThrottle() = default;

void XMLHttpRequestProgressEventThrottle::dispatchThrottledProgressEvent(bool lengthComputable, unsigned long long loaded, unsigned long long total)
{
    m_lengthComputable = lengthComputable;
    m_loaded = loaded;
    m_total = total;

    if (!m_target.hasEventListeners(eventNames().progressEvent))
        return;

    if (!m_shouldDeferEventsDueToSuspension && !m_dispatchThrottledProgressEventTimer.isActive()) {
        // The timer is not active so the least frequent event for now is every byte. Just dispatch the event.

        // We should not have any throttled progress event.
        ASSERT(!m_hasPendingThrottledProgressEvent);

        dispatchEventWhenPossible(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, lengthComputable, loaded, total));
        m_dispatchThrottledProgressEventTimer.startRepeating(minimumProgressEventDispatchingInterval);
        m_hasPendingThrottledProgressEvent = false;
        return;
    }

    // The timer is already active so minimumProgressEventDispatchingInterval is the least frequent event.
    m_hasPendingThrottledProgressEvent = true;
}

void XMLHttpRequestProgressEventThrottle::dispatchReadyStateChangeEvent(Event& event, ProgressEventAction progressEventAction)
{
    if (progressEventAction == FlushProgressEvent)
        flushProgressEvent();

    dispatchEventWhenPossible(event);
}

void XMLHttpRequestProgressEventThrottle::dispatchEventWhenPossible(Event& event)
{
    if (m_shouldDeferEventsDueToSuspension) {
        if (m_eventsDeferredDueToSuspension.size() > 1 && event.type() == eventNames().readystatechangeEvent && event.type() == m_eventsDeferredDueToSuspension.last()->type()) {
            // Readystatechange events are state-less so avoid repeating two identical events in a row on resume.
            return;
        }
        m_eventsDeferredDueToSuspension.append(event);
    } else
        m_target.dispatchEvent(event);
}

void XMLHttpRequestProgressEventThrottle::dispatchProgressEvent(const AtomString& type)
{
    ASSERT(type == eventNames().loadstartEvent || type == eventNames().progressEvent || type == eventNames().loadEvent || type == eventNames().loadendEvent || type == eventNames().abortEvent || type == eventNames().errorEvent || type == eventNames().timeoutEvent);

    if (type == eventNames().loadstartEvent) {
        m_lengthComputable = false;
        m_loaded = 0;
        m_total = 0;
    }

    if (m_target.hasEventListeners(type))
        dispatchEventWhenPossible(XMLHttpRequestProgressEvent::create(type, m_lengthComputable, m_loaded, m_total));
}

void XMLHttpRequestProgressEventThrottle::flushProgressEvent()
{
    if (!m_hasPendingThrottledProgressEvent)
        return;

    m_hasPendingThrottledProgressEvent = false;
    // We stop the timer as this is called when no more events are supposed to occur.
    m_dispatchThrottledProgressEventTimer.cancel();

    dispatchEventWhenPossible(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total));
}

void XMLHttpRequestProgressEventThrottle::dispatchDeferredEventsAfterResuming()
{
    ASSERT(m_shouldDeferEventsDueToSuspension);
    m_shouldDeferEventsDueToSuspension = false;

    // Take over the deferred events before dispatching them which can potentially add more.
    auto eventsDeferredDueToSuspension = WTFMove(m_eventsDeferredDueToSuspension);

    flushProgressEvent();

    for (auto& deferredEvent : eventsDeferredDueToSuspension)
        dispatchEventWhenPossible(deferredEvent);
}

void XMLHttpRequestProgressEventThrottle::dispatchThrottledProgressEventTimerFired()
{
    ASSERT(m_dispatchThrottledProgressEventTimer.isActive());
    if (!m_hasPendingThrottledProgressEvent) {
        // No progress event was queued since the previous dispatch, we can safely stop the timer.
        m_dispatchThrottledProgressEventTimer.cancel();
        return;
    }

    dispatchEventWhenPossible(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total));
    m_hasPendingThrottledProgressEvent = false;
}

void XMLHttpRequestProgressEventThrottle::suspend()
{
    m_shouldDeferEventsDueToSuspension = true;
}

void XMLHttpRequestProgressEventThrottle::resume()
{
    if (m_eventsDeferredDueToSuspension.isEmpty() && !m_hasPendingThrottledProgressEvent) {
        m_shouldDeferEventsDueToSuspension = false;
        return;
    }

    m_dispatchDeferredEventsAfterResumingTimer.startOneShot(0_s);
}

} // namespace WebCore
