#include "config.h"
#include "NetworkResourceLoadScheduler.h"

#include "HostRecord.h"
#include "Logging.h"
#include "NetworkProcess.h"
#include "NetworkResourceLoadParameters.h"
#include "NetworkResourceLoader.h"
#include "SyncNetworkResourceLoader.h"
#include <wtf/MainThread.h>
#include <wtf/text/CString.h>

#if ENABLE(NETWORK_PROCESS)

using namespace WebCore;

namespace WebKit {

static const unsigned maxRequestsInFlightForNonHTTPProtocols = 20;
static unsigned maxRequestsInFlightPerHost;

NetworkResourceLoadScheduler::NetworkResourceLoadScheduler()
    : m_nonHTTPProtocolHost(HostRecord::create(String(), maxRequestsInFlightForNonHTTPProtocols))
    , m_requestTimer(this, &NetworkResourceLoadScheduler::requestTimerFired)

{
    maxRequestsInFlightPerHost = platformInitializeMaximumHTTPConnectionCountPerHost();
}

void NetworkResourceLoadScheduler::scheduleServePendingRequests()
{
    if (!m_requestTimer.isActive())
        m_requestTimer.startOneShot(0);
}

void NetworkResourceLoadScheduler::requestTimerFired(WebCore::Timer<NetworkResourceLoadScheduler>*)
{
    servePendingRequests();
}

void NetworkResourceLoadScheduler::scheduleLoader(PassRefPtr<SchedulableLoader> loader)
{
    ResourceLoadPriority priority = loader->priority();
    const ResourceRequest& resourceRequest = loader->request();
        
    LOG(NetworkScheduling, "(NetworkProcess) NetworkResourceLoadScheduler::scheduleLoader resource '%s'", resourceRequest.url().string().utf8().data());

    HostRecord* host = hostForURL(resourceRequest.url(), CreateIfNotFound);
    bool hadRequests = host->hasRequests();
    host->scheduleResourceLoader(loader);

    if (priority > ResourceLoadPriorityLow || !resourceRequest.url().protocolIsInHTTPFamily() || (priority == ResourceLoadPriorityLow && !hadRequests)) {
        // Try to request important resources immediately.
        host->servePendingRequests(priority);
        return;
    }
    
    // Handle asynchronously so early low priority requests don't get scheduled before later high priority ones.
    scheduleServePendingRequests();
}

HostRecord* NetworkResourceLoadScheduler::hostForURL(const WebCore::KURL& url, CreateHostPolicy createHostPolicy)
{
    if (!url.protocolIsInHTTPFamily())
        return m_nonHTTPProtocolHost.get();

    m_hosts.checkConsistency();
    String hostName = url.host();
    HostRecord* host = m_hosts.get(hostName);
    if (!host && createHostPolicy == CreateIfNotFound) {
        RefPtr<HostRecord> newHost = HostRecord::create(hostName, maxRequestsInFlightPerHost);
        host = newHost.get();
        m_hosts.add(hostName, newHost.release());
    }
    
    return host;
}

void NetworkResourceLoadScheduler::removeLoader(SchedulableLoader* loader)
{
    ASSERT(isMainThread());
    ASSERT(loader);

    LOG(NetworkScheduling, "(NetworkProcess) NetworkResourceLoadScheduler::removeLoadIdentifier removing loader %s", loader->request().url().string().utf8().data());

    HostRecord* host = loader->hostRecord();
    
    // Due to a race condition the WebProcess might have messaged the NetworkProcess to remove this identifier
    // after the NetworkProcess has already removed it internally.
    // In this situation we might not have a HostRecord to clean up.
    if (host)
        host->removeLoader(loader);

    scheduleServePendingRequests();
}

void NetworkResourceLoadScheduler::receivedRedirect(SchedulableLoader* loader, const WebCore::KURL& redirectURL)
{
    ASSERT(isMainThread());
    LOG(NetworkScheduling, "(NetworkProcess) NetworkResourceLoadScheduler::receivedRedirect loader originally for '%s' redirected to '%s'", loader->request().url().string().utf8().data(), redirectURL.string().utf8().data());

    HostRecord* oldHost = loader->hostRecord();

    // The load may have been cancelled while the message was in flight from network thread to main thread.
    if (!oldHost)
        return;

    HostRecord* newHost = hostForURL(redirectURL, CreateIfNotFound);
    
    if (oldHost->name() == newHost->name())
        return;

    oldHost->removeLoader(loader);
    newHost->addLoaderInProgress(loader);
}

void NetworkResourceLoadScheduler::servePendingRequests(ResourceLoadPriority minimumPriority)
{
    LOG(NetworkScheduling, "(NetworkProcess) NetworkResourceLoadScheduler::servePendingRequests Serving requests for up to %i hosts with minimum priority %i", m_hosts.size(), minimumPriority);

    m_requestTimer.stop();
    
    m_nonHTTPProtocolHost->servePendingRequests(minimumPriority);

    m_hosts.checkConsistency();
    Vector<RefPtr<HostRecord>> hostsToServe;
    copyValuesToVector(m_hosts, hostsToServe);

    size_t size = hostsToServe.size();
    for (size_t i = 0; i < size; ++i) {
        HostRecord* host = hostsToServe[i].get();
        if (host->hasRequests())
            host->servePendingRequests(minimumPriority);
        else
            m_hosts.remove(host->name());
    }
}

static bool removeScheduledLoadersCalled = false;

void NetworkResourceLoadScheduler::removeScheduledLoaders(void* context)
{
    ASSERT(isMainThread());
    ASSERT(removeScheduledLoadersCalled);

    NetworkResourceLoadScheduler* scheduler = static_cast<NetworkResourceLoadScheduler*>(context);
    scheduler->removeScheduledLoaders();
}

void NetworkResourceLoadScheduler::removeScheduledLoaders()
{
    Vector<RefPtr<SchedulableLoader>> loadersToRemove;
    {
        MutexLocker locker(m_loadersToRemoveMutex);
        loadersToRemove = m_loadersToRemove;
        m_loadersToRemove.clear();
        removeScheduledLoadersCalled = false;
    }
    
    for (size_t i = 0; i < loadersToRemove.size(); ++i)
        removeLoader(loadersToRemove[i].get());
}

void NetworkResourceLoadScheduler::scheduleRemoveLoader(SchedulableLoader* loader)
{
    MutexLocker locker(m_loadersToRemoveMutex);
    
    m_loadersToRemove.append(loader);
    
    if (!removeScheduledLoadersCalled) {
        removeScheduledLoadersCalled = true;
        callOnMainThread(NetworkResourceLoadScheduler::removeScheduledLoaders, this);
    }
}

uint64_t NetworkResourceLoadScheduler::hostsPendingCount() const
{
    uint64_t count = m_nonHTTPProtocolHost->pendingRequestCount() ? 1 : 0;

    HostMap::const_iterator end = m_hosts.end();
    for (HostMap::const_iterator i = m_hosts.begin(); i != end; ++i) {
        if (i->value->pendingRequestCount())
            ++count;
    }

    return count;
}

uint64_t NetworkResourceLoadScheduler::loadsPendingCount() const
{
    uint64_t count = m_nonHTTPProtocolHost->pendingRequestCount();

    HostMap::const_iterator end = m_hosts.end();
    for (HostMap::const_iterator i = m_hosts.begin(); i != end; ++i)
        count += i->value->pendingRequestCount();

    return count;
}

uint64_t NetworkResourceLoadScheduler::hostsActiveCount() const
{
    uint64_t count = 0;

    if (m_nonHTTPProtocolHost->activeLoadCount())
        count = 1;

    HostMap::const_iterator end = m_hosts.end();
    for (HostMap::const_iterator i = m_hosts.begin(); i != end; ++i) {
        if (i->value->activeLoadCount())
            ++count;
    }

    return count;
}

uint64_t NetworkResourceLoadScheduler::loadsActiveCount() const
{
    uint64_t count = m_nonHTTPProtocolHost->activeLoadCount();

    HostMap::const_iterator end = m_hosts.end();
    for (HostMap::const_iterator i = m_hosts.begin(); i != end; ++i)
        count += i->value->activeLoadCount();

    return count;
}

} // namespace WebKit

#endif // ENABLE(NETWORK_PROCESS)
