/*
 * Copyright (C) 2010 Julien Chaffraix <jchaffraix@webkit.org>
 * All right 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 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 "EventTarget.h"
#include "XMLHttpRequestProgressEvent.h"

namespace WebCore {

const double XMLHttpRequestProgressEventThrottle::minimumProgressEventDispatchingIntervalInSeconds = .05; // 50 ms per specification.

XMLHttpRequestProgressEventThrottle::XMLHttpRequestProgressEventThrottle(EventTarget* target)
    : m_target(target)
    , m_loaded(0)
    , m_total(0)
    , m_suspended(false)
{
    ASSERT(target);
}

XMLHttpRequestProgressEventThrottle::~XMLHttpRequestProgressEventThrottle()
{
}

void XMLHttpRequestProgressEventThrottle::dispatchProgressEvent(bool lengthComputable, unsigned loaded, unsigned total)
{
    ASSERT(!suspended());
    if (!isActive()) {
        // The timer is not active so the least frequent event for now is every byte.
        // Just go ahead and dispatch the event.

        // We should not have any pending loaded & total information from a previous run.
        ASSERT(!m_loaded);
        ASSERT(!m_total);

        dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, lengthComputable, loaded, total));
        startRepeating(minimumProgressEventDispatchingIntervalInSeconds);
        return;
    }

    // The timer is already active so minimumProgressEventDispatchingIntervalInSeconds is the least frequent event.
    m_lengthComputable = lengthComputable;
    m_loaded = loaded;
    m_total = total;
}

void XMLHttpRequestProgressEventThrottle::dispatchEvent(PassRefPtr<Event> event, ProgressEventAction progressEventAction)
{
    ASSERT(!suspended());
    // We should not have any pending events from a previous resume.
    ASSERT(!m_pausedEvent);

    if (progressEventAction == FlushProgressEvent)
        flushProgressEvent();

    m_target->dispatchEvent(event);
}

void XMLHttpRequestProgressEventThrottle::flushProgressEvent()
{
    if (!hasEventToDispatch())
        return;

    PassRefPtr<Event> event = XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total);
    m_loaded = 0;
    m_total = 0;

    // We stop the timer as this is called when no more events are supposed to occur.
    stop();

    m_target->dispatchEvent(event);
}

void XMLHttpRequestProgressEventThrottle::dispatchPausedEvent()
{
    ASSERT(!suspended());
    if (!m_pausedEvent)
        return;

    m_target->dispatchEvent(m_pausedEvent);
    m_pausedEvent = 0;
}

void XMLHttpRequestProgressEventThrottle::fired()
{
    ASSERT(isActive());
    ASSERT(!suspended());
    ASSERT(!m_pausedEvent);
    if (!hasEventToDispatch()) {
        // No progress event was queued since the previous dispatch, we can safely stop the timer.
        stop();
        return;
    }

    m_target->dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total));
    m_total = 0;
    m_loaded = 0;
}

bool XMLHttpRequestProgressEventThrottle::hasEventToDispatch() const
{
    return (m_total || m_loaded) && isActive();
}

void XMLHttpRequestProgressEventThrottle::suspend()
{
    ASSERT(!m_pausedEvent);

    m_suspended = true;
    // If we have a progress event waiting to be dispatched,
    // just queue it.
    if (hasEventToDispatch()) {
        m_pausedEvent = XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total);
        m_total = 0;
        m_loaded = 0;
    }
    stop();
}

void XMLHttpRequestProgressEventThrottle::resume()
{
    ASSERT(!m_loaded);
    ASSERT(!m_total);

    m_suspended = false;
    dispatchPausedEvent();
}

} // namespace WebCore
