// Copyright (c) 2009 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/appcache/appcache_storage.h"

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/stl_util.h"
#include "content/browser/appcache/appcache_response.h"
#include "content/browser/appcache/appcache_service_impl.h"
#include "webkit/browser/quota/quota_client.h"
#include "webkit/browser/quota/quota_manager_proxy.h"

namespace content {

// static
const int64 AppCacheStorage::kUnitializedId = -1;

AppCacheStorage::AppCacheStorage(AppCacheServiceImpl* service)
    : last_cache_id_(kUnitializedId), last_group_id_(kUnitializedId),
      last_response_id_(kUnitializedId), service_(service)  {
}

AppCacheStorage::~AppCacheStorage() {
  STLDeleteValues(&pending_info_loads_);
  DCHECK(delegate_references_.empty());
}

AppCacheStorage::DelegateReference::DelegateReference(
    Delegate* delegate, AppCacheStorage* storage)
    : delegate(delegate), storage(storage) {
  storage->delegate_references_.insert(
      DelegateReferenceMap::value_type(delegate, this));
}

AppCacheStorage::DelegateReference::~DelegateReference() {
  if (delegate)
    storage->delegate_references_.erase(delegate);
}

AppCacheStorage::ResponseInfoLoadTask::ResponseInfoLoadTask(
    const GURL& manifest_url,
    int64 group_id,
    int64 response_id,
    AppCacheStorage* storage)
    : storage_(storage),
      manifest_url_(manifest_url),
      group_id_(group_id),
      response_id_(response_id),
      info_buffer_(new HttpResponseInfoIOBuffer) {
  storage_->pending_info_loads_.insert(
      PendingResponseInfoLoads::value_type(response_id, this));
}

AppCacheStorage::ResponseInfoLoadTask::~ResponseInfoLoadTask() {
}

void AppCacheStorage::ResponseInfoLoadTask::StartIfNeeded() {
  if (reader_)
    return;
  reader_.reset(
      storage_->CreateResponseReader(manifest_url_, group_id_, response_id_));
  reader_->ReadInfo(info_buffer_.get(),
                    base::Bind(&ResponseInfoLoadTask::OnReadComplete,
                               base::Unretained(this)));
}

void AppCacheStorage::ResponseInfoLoadTask::OnReadComplete(int result) {
  storage_->pending_info_loads_.erase(response_id_);
  scoped_refptr<AppCacheResponseInfo> info;
  if (result >= 0) {
    info = new AppCacheResponseInfo(storage_, manifest_url_,
                                    response_id_,
                                    info_buffer_->http_info.release(),
                                    info_buffer_->response_data_size);
  }
  FOR_EACH_DELEGATE(delegates_, OnResponseInfoLoaded(info.get(), response_id_));
  delete this;
}

void AppCacheStorage::LoadResponseInfo(
    const GURL& manifest_url, int64 group_id, int64 id, Delegate* delegate) {
  AppCacheResponseInfo* info = working_set_.GetResponseInfo(id);
  if (info) {
    delegate->OnResponseInfoLoaded(info, id);
    return;
  }
  ResponseInfoLoadTask* info_load =
      GetOrCreateResponseInfoLoadTask(manifest_url, group_id, id);
  DCHECK(manifest_url == info_load->manifest_url());
  DCHECK(group_id == info_load->group_id());
  DCHECK(id == info_load->response_id());
  info_load->AddDelegate(GetOrCreateDelegateReference(delegate));
  info_load->StartIfNeeded();
}

void AppCacheStorage::UpdateUsageMapAndNotify(
    const GURL& origin, int64 new_usage) {
  DCHECK_GE(new_usage, 0);
  int64 old_usage = usage_map_[origin];
  if (new_usage > 0)
    usage_map_[origin] = new_usage;
  else
    usage_map_.erase(origin);
  if (new_usage != old_usage && service()->quota_manager_proxy()) {
    service()->quota_manager_proxy()->NotifyStorageModified(
        quota::QuotaClient::kAppcache,
        origin, quota::kStorageTypeTemporary,
        new_usage - old_usage);
  }
}

void AppCacheStorage::ClearUsageMapAndNotify() {
  if (service()->quota_manager_proxy()) {
    for (UsageMap::const_iterator iter = usage_map_.begin();
         iter != usage_map_.end(); ++iter) {
      service()->quota_manager_proxy()->NotifyStorageModified(
          quota::QuotaClient::kAppcache,
          iter->first, quota::kStorageTypeTemporary,
          -(iter->second));
    }
  }
  usage_map_.clear();
}

void AppCacheStorage::NotifyStorageAccessed(const GURL& origin) {
  if (service()->quota_manager_proxy() &&
      usage_map_.find(origin) != usage_map_.end())
    service()->quota_manager_proxy()->NotifyStorageAccessed(
        quota::QuotaClient::kAppcache,
        origin, quota::kStorageTypeTemporary);
}

}  // namespace content

