// 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 "chrome/browser/icon_manager.h"

#include <memory>
#include <tuple>

#include "base/bind.h"
#include "base/stl_util.h"
#include "base/task_runner.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"

namespace {

void RunCallbackIfNotCanceled(
    const base::CancelableTaskTracker::IsCanceledCallback& is_canceled,
    const IconManager::IconRequestCallback& callback,
    gfx::Image* image) {
  if (is_canceled.Run())
    return;
  callback.Run(image);
}

}  // namespace

struct IconManager::ClientRequest {
  IconRequestCallback callback;
  base::FilePath file_path;
  IconLoader::IconSize size;
};

IconManager::IconManager() {
}

IconManager::~IconManager() {
  base::STLDeleteValues(&icon_cache_);
}

gfx::Image* IconManager::LookupIconFromFilepath(const base::FilePath& file_name,
                                                IconLoader::IconSize size) {
  GroupMap::iterator it = group_cache_.find(file_name);
  if (it != group_cache_.end())
    return LookupIconFromGroup(it->second, size);

  return NULL;
}

gfx::Image* IconManager::LookupIconFromGroup(const IconGroupID& group,
                                             IconLoader::IconSize size) {
  IconMap::iterator it = icon_cache_.find(CacheKey(group, size));
  if (it != icon_cache_.end())
    return it->second;

  return NULL;
}

base::CancelableTaskTracker::TaskId IconManager::LoadIcon(
    const base::FilePath& file_name,
    IconLoader::IconSize size,
    const IconRequestCallback& callback,
    base::CancelableTaskTracker* tracker) {
  IconLoader* loader = new IconLoader(file_name, size, this);
  loader->AddRef();
  loader->Start();

  base::CancelableTaskTracker::IsCanceledCallback is_canceled;
  base::CancelableTaskTracker::TaskId id =
      tracker->NewTrackedTaskId(&is_canceled);
  IconRequestCallback callback_runner = base::Bind(
      &RunCallbackIfNotCanceled, is_canceled, callback);

  ClientRequest client_request = { callback_runner, file_name, size };
  requests_[loader] = client_request;
  return id;
}

// IconLoader::Delegate implementation -----------------------------------------

bool IconManager::OnGroupLoaded(IconLoader* loader,
                                const IconGroupID& group) {
  ClientRequests::iterator rit = requests_.find(loader);
  if (rit == requests_.end()) {
    NOTREACHED();
    return false;
  }

  gfx::Image* result = LookupIconFromGroup(group, rit->second.size);
  if (!result) {
    return false;
  }

  return OnImageLoaded(loader, result, group);
}

bool IconManager::OnImageLoaded(
    IconLoader* loader, gfx::Image* result, const IconGroupID& group) {
  ClientRequests::iterator rit = requests_.find(loader);

  // Balances the AddRef() in LoadIcon().
  loader->Release();

  // Look up our client state.
  if (rit == requests_.end()) {
    NOTREACHED();
    return false;  // Return false to indicate result should be deleted.
  }

  const ClientRequest& client_request = rit->second;

  // Cache the bitmap. Watch out: |result| may be NULL to indicate a current
  // failure. We assume that if we have an entry in |icon_cache_|
  // it must not be NULL.
  CacheKey key(group, client_request.size);
  IconMap::iterator it = icon_cache_.find(key);
  if (it != icon_cache_.end()) {
    if (!result) {
      delete it->second;
      icon_cache_.erase(it);
    } else if (result != it->second) {
      it->second->SwapRepresentations(result);
      delete result;
      result = it->second;
    }
  } else if (result) {
    icon_cache_[key] = result;
  }

  group_cache_[client_request.file_path] = group;

  // Inform our client that the request has completed.
  client_request.callback.Run(result);
  requests_.erase(rit);

  return true;  // Indicates we took ownership of result.
}

IconManager::CacheKey::CacheKey(const IconGroupID& group,
                                IconLoader::IconSize size)
    : group(group),
      size(size) {
}

bool IconManager::CacheKey::operator<(const CacheKey &other) const {
  return std::tie(group, size) < std::tie(other.group, other.size);
}
