// Copyright (c) 2012 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.

#ifndef CONTENT_BROWSER_APPCACHE_APPCACHE_DISK_CACHE_H_
#define CONTENT_BROWSER_APPCACHE_APPCACHE_DISK_CACHE_H_

#include <stdint.h>

#include <memory>
#include <set>
#include <vector>

#include "base/callback_forward.h"
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
#include "net/base/completion_once_callback.h"
#include "net/disk_cache/disk_cache.h"

namespace content {

class AppCacheDiskCache;

// Thin wrapper around disk_cache::Entry.
class CONTENT_EXPORT AppCacheDiskCacheEntry {
 public:
  // The newly created entry takes ownership of |disk_cache_entry| and closes it
  // on destruction. |cache| must outlive the newly created entry.
  AppCacheDiskCacheEntry(disk_cache::Entry* disk_cache_entry,
                         AppCacheDiskCache* cache);

  int Read(int index,
           int64_t offset,
           net::IOBuffer* buf,
           int buf_len,
           net::CompletionOnceCallback callback);

  int Write(int index,
            int64_t offset,
            net::IOBuffer* buf,
            int buf_len,
            net::CompletionOnceCallback callback);
  int64_t GetSize(int index);
  void Close();

  // Should only be called by AppCacheDiskCache.
  void Abandon();

 private:
  // Call Close() instead of calling this directly.
  ~AppCacheDiskCacheEntry();

  // The disk_cache::Entry is owned by this entry and closed on destruction.
  disk_cache::Entry* disk_cache_entry_;

  // The cache that this entry belongs to.
  AppCacheDiskCache* cache_;
};

// An implementation of AppCacheDiskCache that
// uses net::DiskCache as the backing store.
class CONTENT_EXPORT AppCacheDiskCache {
 public:
  AppCacheDiskCache();
  virtual ~AppCacheDiskCache();

  // Initializes the object to use disk backed storage.
  net::Error InitWithDiskBackend(const base::FilePath& disk_cache_directory,
                                 bool force,
                                 base::OnceClosure post_cleanup_callback,
                                 net::CompletionOnceCallback callback);

  // Initializes the object to use memory only storage.
  // This is used for Chrome's incognito browsing.
  net::Error InitWithMemBackend(int64_t disk_cache_size,
                                net::CompletionOnceCallback callback);

  void Disable();
  bool is_disabled() const { return is_disabled_; }

  net::Error CreateEntry(int64_t key,
                         AppCacheDiskCacheEntry** entry,
                         net::CompletionOnceCallback callback);
  net::Error OpenEntry(int64_t key,
                       AppCacheDiskCacheEntry** entry,
                       net::CompletionOnceCallback callback);
  net::Error DoomEntry(int64_t key, net::CompletionOnceCallback callback);

  base::WeakPtr<AppCacheDiskCache> GetWeakPtr();

  void set_is_waiting_to_initialize(bool is_waiting_to_initialize) {
    is_waiting_to_initialize_ = is_waiting_to_initialize;
  }

  const char* uma_name() { return uma_name_; }

 protected:
  // |uma_name| must remain valid for the life of the object.
  explicit AppCacheDiskCache(const char* uma_name, bool use_simple_cache);
  disk_cache::Backend* disk_cache() { return disk_cache_.get(); }

 private:
  class CreateBackendCallbackShim;
  friend class AppCacheDiskCacheEntry;

  // PendingCalls allow CreateEntry, OpenEntry, and DoomEntry to be called
  // immediately after construction, without waiting for the
  // underlying disk_cache::Backend to be fully constructed. Early
  // calls are queued up and serviced once the disk_cache::Backend is
  // really ready to go.
  enum PendingCallType {
    CREATE,
    OPEN,
    DOOM
  };
  struct PendingCall {
    PendingCall();
    PendingCall(PendingCallType call_type,
                int64_t key,
                AppCacheDiskCacheEntry** entry,
                net::CompletionOnceCallback callback);
    PendingCall(PendingCall&& other);

    ~PendingCall();

    PendingCallType call_type;
    int64_t key;
    AppCacheDiskCacheEntry** entry;
    net::CompletionOnceCallback callback;
  };
  using PendingCalls = std::vector<PendingCall>;

  class ActiveCall;
  using ActiveCalls = std::set<ActiveCall*>;
  using OpenEntries = std::set<AppCacheDiskCacheEntry*>;

  bool is_initializing_or_waiting_to_initialize() const {
    return create_backend_callback_.get() != NULL || is_waiting_to_initialize_;
  }

  net::Error Init(net::CacheType cache_type,
                  const base::FilePath& directory,
                  int64_t cache_size,
                  bool force,
                  base::OnceClosure post_cleanup_callback,
                  net::CompletionOnceCallback callback);
  void OnCreateBackendComplete(int return_value);

  // Called by AppCacheDiskCacheEntry constructor.
  void AddOpenEntry(AppCacheDiskCacheEntry* entry) {
    open_entries_.insert(entry);
  }
  // Called by AppCacheDiskCacheEntry destructor.
  void RemoveOpenEntry(AppCacheDiskCacheEntry* entry) {
    open_entries_.erase(entry);
  }

  bool use_simple_cache_;
  bool is_disabled_;
  bool is_waiting_to_initialize_;
  net::CompletionOnceCallback init_callback_;
  scoped_refptr<CreateBackendCallbackShim> create_backend_callback_;
  PendingCalls pending_calls_;
  OpenEntries open_entries_;
  std::unique_ptr<disk_cache::Backend> disk_cache_;
  const char* const uma_name_;

  base::WeakPtrFactory<AppCacheDiskCache> weak_factory_;
};

}  // namespace content

#endif  // CONTENT_BROWSER_APPCACHE_APPCACHE_DISK_CACHE_H_
