// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/renderer_host/resource_queue.h"

#include "base/stl_util-inl.h"
#include "chrome/browser/browser_thread.h"
#include "content/browser/renderer_host/global_request_id.h"
#include "content/browser/renderer_host/resource_dispatcher_host_request_info.h"

ResourceQueueDelegate::~ResourceQueueDelegate() {
}

ResourceQueue::ResourceQueue() : shutdown_(false) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}

ResourceQueue::~ResourceQueue() {
  DCHECK(shutdown_);
}

void ResourceQueue::Initialize(const DelegateSet& delegates) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(delegates_.empty());
  delegates_ = delegates;
}

void ResourceQueue::Shutdown() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  shutdown_ = true;
  for (DelegateSet::iterator i = delegates_.begin();
       i != delegates_.end(); ++i) {
    (*i)->WillShutdownResourceQueue();
  }
}

void ResourceQueue::AddRequest(
    net::URLRequest* request,
    const ResourceDispatcherHostRequestInfo& request_info) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  DCHECK(!shutdown_);

  GlobalRequestID request_id(request_info.child_id(),
                             request_info.request_id());

  DCHECK(!ContainsKey(requests_, request_id))
      << "child_id:" << request_info.child_id()
      << ", request_id:" << request_info.request_id();
  requests_[request_id] = request;

  DelegateSet interested_delegates;

  for (DelegateSet::iterator i = delegates_.begin();
       i != delegates_.end(); ++i) {
    if ((*i)->ShouldDelayRequest(request, request_info, request_id))
      interested_delegates.insert(*i);
  }

  if (interested_delegates.empty()) {
    request->Start();
    return;
  }

  DCHECK(!ContainsKey(interested_delegates_, request_id));
  interested_delegates_[request_id] = interested_delegates;
}

void ResourceQueue::RemoveRequest(const GlobalRequestID& request_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  requests_.erase(request_id);
}

void ResourceQueue::StartDelayedRequest(ResourceQueueDelegate* delegate,
                                        const GlobalRequestID& request_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  DCHECK(!shutdown_);

  DCHECK(ContainsKey(interested_delegates_, request_id));
  DCHECK(ContainsKey(interested_delegates_[request_id], delegate));
  interested_delegates_[request_id].erase(delegate);
  if (interested_delegates_[request_id].empty()) {
    interested_delegates_.erase(request_id);

    if (ContainsKey(requests_, request_id)) {
      net::URLRequest* request = requests_[request_id];
      // The request shouldn't have started (SUCCESS is the initial state).
      DCHECK_EQ(net::URLRequestStatus::SUCCESS, request->status().status());
      request->Start();
    }
  }
}
