// 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.

#include "chrome/browser/icon_loader.h"

#include <map>
#include <string>
#include <utility>

#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/lazy_instance.h"
#include "base/memory/ref_counted_memory.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_util.h"
#include "chrome/browser/icon_loader.h"
#include "grit/theme_resources.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/layout.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_operations.h"

namespace {

// Used with GenerateImageWithSize() to indicate that the image shouldn't be
// resized.
const int kDoNotResize = -1;

struct IdrBySize {
  int idr_small;
  int idr_normal;
  int idr_large;
};

// Performs mapping of <file extension, icon size> to icon resource IDs.
class IconMapper {
 public:
  IconMapper();

  // Lookup icon resource ID for a given filename |extension| and
  // |icon_size|. Defaults to generic icons if there are no icons for the given
  // extension.
  int Lookup(const std::string& extension, IconLoader::IconSize icon_size);

 private:
  typedef std::map<std::string, IdrBySize> ExtensionIconMap;

  ExtensionIconMap extension_icon_map_;
};

const IdrBySize kAudioIdrs = {
  IDR_FILETYPE_AUDIO,
  IDR_FILETYPE_LARGE_AUDIO,
  IDR_FILETYPE_LARGE_AUDIO
};
const IdrBySize kGenericIdrs = {
  IDR_FILETYPE_GENERIC,
  IDR_FILETYPE_LARGE_GENERIC,
  IDR_FILETYPE_LARGE_GENERIC
};
const IdrBySize kImageIdrs = {
  IDR_FILETYPE_IMAGE,
  IDR_FILETYPE_IMAGE,
  IDR_FILETYPE_IMAGE
};
#if defined(USE_PROPRIETARY_CODECS)
const IdrBySize kPdfIdrs = {
  IDR_FILETYPE_PDF,
  IDR_FILETYPE_PDF,
  IDR_FILETYPE_PDF
};
#endif
const IdrBySize kVideoIdrs = {
  IDR_FILETYPE_VIDEO,
  IDR_FILETYPE_LARGE_VIDEO,
  IDR_FILETYPE_LARGE_VIDEO
};

IconMapper::IconMapper() {
  // The code below should match translation in
  // ui/file_manager/file_manager/js/file_manager.js
  // ui/file_manager/file_manager/css/file_manager.css
  // 'audio': /\.(mp3|m4a|oga|ogg|wav)$/i,
  // 'html': /\.(html?)$/i,
  // 'image': /\.(bmp|gif|jpe?g|ico|png|webp)$/i,
  // 'pdf' : /\.(pdf)$/i,
  // 'text': /\.(pod|rst|txt|log)$/i,
  // 'video': /\.(mov|mp4|m4v|mpe?g4?|ogm|ogv|ogx|webm)$/i

  const ExtensionIconMap::value_type kExtensionIdrBySizeData[] = {
#if defined(USE_PROPRIETARY_CODECS)
    std::make_pair(".m4a", kAudioIdrs),
    std::make_pair(".mp3", kAudioIdrs),
    std::make_pair(".pdf", kPdfIdrs),
    std::make_pair(".3gp", kVideoIdrs),
    std::make_pair(".avi", kVideoIdrs),
    std::make_pair(".m4v", kVideoIdrs),
    std::make_pair(".mov", kVideoIdrs),
    std::make_pair(".mp4", kVideoIdrs),
    std::make_pair(".mpeg", kVideoIdrs),
    std::make_pair(".mpg", kVideoIdrs),
    std::make_pair(".mpeg4", kVideoIdrs),
    std::make_pair(".mpg4", kVideoIdrs),
#endif
    std::make_pair(".flac", kAudioIdrs),
    std::make_pair(".oga", kAudioIdrs),
    std::make_pair(".ogg", kAudioIdrs),
    std::make_pair(".wav", kAudioIdrs),
    std::make_pair(".bmp", kImageIdrs),
    std::make_pair(".gif", kImageIdrs),
    std::make_pair(".ico", kImageIdrs),
    std::make_pair(".jpeg", kImageIdrs),
    std::make_pair(".jpg", kImageIdrs),
    std::make_pair(".png", kImageIdrs),
    std::make_pair(".webp", kImageIdrs),
    std::make_pair(".ogm", kVideoIdrs),
    std::make_pair(".ogv", kVideoIdrs),
    std::make_pair(".ogx", kVideoIdrs),
    std::make_pair(".webm", kVideoIdrs),
  };

  const size_t kESize = arraysize(kExtensionIdrBySizeData);
  ExtensionIconMap source(&kExtensionIdrBySizeData[0],
                          &kExtensionIdrBySizeData[kESize]);
  extension_icon_map_.swap(source);
}

int IconMapper::Lookup(const std::string& extension,
                       IconLoader::IconSize icon_size) {
  DCHECK(icon_size == IconLoader::SMALL ||
         icon_size == IconLoader::NORMAL ||
         icon_size == IconLoader::LARGE);
  ExtensionIconMap::const_iterator it = extension_icon_map_.find(extension);
  const IdrBySize& idrbysize =
      ((it == extension_icon_map_.end()) ? kGenericIdrs : it->second);
  int idr = -1;
  switch (icon_size) {
    case IconLoader::SMALL:  idr = idrbysize.idr_small;  break;
    case IconLoader::NORMAL: idr = idrbysize.idr_normal; break;
    case IconLoader::LARGE:  idr = idrbysize.idr_large;  break;
    case IconLoader::ALL:
    default:
      NOTREACHED();
  }
  return idr;
}

// Returns a copy of |source| that is |dip_size| in width and height. If
// |dip_size| is |kDoNotResize|, returns an unmodified copy of |source|.
// |source| must be a square image (width == height).
gfx::ImageSkia ResizeImage(const gfx::ImageSkia& source, int dip_size) {
  DCHECK(!source.isNull());
  DCHECK(source.width() == source.height());

  if (dip_size == kDoNotResize || source.width() == dip_size)
    return source;

  return gfx::ImageSkiaOperations::CreateResizedImage(source,
      skia::ImageOperations::RESIZE_BEST, gfx::Size(dip_size, dip_size));
}

int IconSizeToDIPSize(IconLoader::IconSize size) {
  switch (size) {
    case IconLoader::SMALL:  return 16;
    case IconLoader::NORMAL: return 32;
    case IconLoader::LARGE:  // fallthrough
      // On ChromeOS, we consider LARGE to mean "the largest image we have."
      // Since we have already chosen the largest applicable image resource, we
      // return the image as-is.
    case IconLoader::ALL:    // fallthrough
    default:
      return kDoNotResize;
  }
}

}  // namespace

// static
IconGroupID IconLoader::ReadGroupIDFromFilepath(
    const base::FilePath& filepath) {
  return base::StringToLowerASCII(filepath.Extension());
}

// static
bool IconLoader::IsIconMutableFromFilepath(const base::FilePath&) {
  return false;
}

// static
content::BrowserThread::ID IconLoader::ReadIconThreadID() {
  return content::BrowserThread::FILE;
}

void IconLoader::ReadIcon() {
  static base::LazyInstance<IconMapper>::Leaky icon_mapper =
      LAZY_INSTANCE_INITIALIZER;
  int idr = icon_mapper.Get().Lookup(group_, icon_size_);
  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  gfx::ImageSkia image_skia(ResizeImage(*(rb.GetImageNamed(idr)).ToImageSkia(),
                                        IconSizeToDIPSize(icon_size_)));
  image_skia.MakeThreadSafe();
  image_.reset(new gfx::Image(image_skia));
  target_message_loop_->PostTask(
      FROM_HERE, base::Bind(&IconLoader::NotifyDelegate, this));
}
