// Copyright (c) 2013 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 "ash/desktop_background/wallpaper_resizer.h"

#include "ash/desktop_background/wallpaper_resizer_observer.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/worker_pool.h"
#include "content/public/browser/browser_thread.h"
#include "third_party/skia/include/core/SkImage.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image_skia_rep.h"
#include "ui/gfx/skia_util.h"

using content::BrowserThread;

namespace ash {
namespace {

// For our scaling ratios we need to round positive numbers.
int RoundPositive(double x) {
  return static_cast<int>(floor(x + 0.5));
}

// Resizes |orig_bitmap| to |target_size| using |layout| and stores the
// resulting bitmap at |resized_bitmap_out|.
void Resize(SkBitmap orig_bitmap,
            const gfx::Size& target_size,
            WallpaperLayout layout,
            SkBitmap* resized_bitmap_out) {
  DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
  SkBitmap new_bitmap = orig_bitmap;

  const int orig_width = orig_bitmap.width();
  const int orig_height = orig_bitmap.height();
  const int new_width = target_size.width();
  const int new_height = target_size.height();

  if (orig_width > new_width || orig_height > new_height) {
    gfx::Rect wallpaper_rect(0, 0, orig_width, orig_height);
    gfx::Size cropped_size = gfx::Size(std::min(new_width, orig_width),
                                       std::min(new_height, orig_height));
    switch (layout) {
      case WALLPAPER_LAYOUT_CENTER:
        wallpaper_rect.ClampToCenteredSize(cropped_size);
        orig_bitmap.extractSubset(&new_bitmap,
                                  gfx::RectToSkIRect(wallpaper_rect));
        break;
      case WALLPAPER_LAYOUT_TILE:
        wallpaper_rect.set_size(cropped_size);
        orig_bitmap.extractSubset(&new_bitmap,
                                  gfx::RectToSkIRect(wallpaper_rect));
        break;
      case WALLPAPER_LAYOUT_STRETCH:
        new_bitmap = skia::ImageOperations::Resize(
            orig_bitmap, skia::ImageOperations::RESIZE_LANCZOS3,
            new_width, new_height);
        break;
      case WALLPAPER_LAYOUT_CENTER_CROPPED:
        if (orig_width > new_width && orig_height > new_height) {
          // The dimension with the smallest ratio must be cropped, the other
          // one is preserved. Both are set in gfx::Size cropped_size.
          double horizontal_ratio = static_cast<double>(new_width) /
              static_cast<double>(orig_width);
          double vertical_ratio = static_cast<double>(new_height) /
              static_cast<double>(orig_height);

          if (vertical_ratio > horizontal_ratio) {
            cropped_size = gfx::Size(
                RoundPositive(static_cast<double>(new_width) / vertical_ratio),
                orig_height);
          } else {
            cropped_size = gfx::Size(orig_width, RoundPositive(
                static_cast<double>(new_height) / horizontal_ratio));
          }
          wallpaper_rect.ClampToCenteredSize(cropped_size);
          SkBitmap sub_image;
          orig_bitmap.extractSubset(&sub_image,
                                    gfx::RectToSkIRect(wallpaper_rect));
          new_bitmap = skia::ImageOperations::Resize(
              sub_image, skia::ImageOperations::RESIZE_LANCZOS3,
              new_width, new_height);
        }
    }
  }

  *resized_bitmap_out = new_bitmap;
  resized_bitmap_out->setImmutable();
}

}  // namespace

// static
uint32_t WallpaperResizer::GetImageId(const gfx::ImageSkia& image) {
  const gfx::ImageSkiaRep& image_rep = image.GetRepresentation(1.0f);
  return image_rep.is_null() ? 0 : image_rep.sk_bitmap().getGenerationID();
}

WallpaperResizer::WallpaperResizer(int image_resource_id,
                                   const gfx::Size& target_size,
                                   WallpaperLayout layout)
    : image_(*(ui::ResourceBundle::GetSharedInstance().
          GetImageNamed(image_resource_id).ToImageSkia())),
      original_image_id_(GetImageId(image_)),
      target_size_(target_size),
      layout_(layout),
      weak_ptr_factory_(this) {
  image_.MakeThreadSafe();
}

WallpaperResizer::WallpaperResizer(const gfx::ImageSkia& image,
                                   const gfx::Size& target_size,
                                   WallpaperLayout layout)
    : image_(image),
      original_image_id_(GetImageId(image_)),
      target_size_(target_size),
      layout_(layout),
      weak_ptr_factory_(this) {
  image_.MakeThreadSafe();
}

WallpaperResizer::~WallpaperResizer() {
}

void WallpaperResizer::StartResize() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  SkBitmap* resized_bitmap = new SkBitmap;
  if (!content::BrowserThread::PostBlockingPoolTaskAndReply(
          FROM_HERE,
          base::Bind(&Resize, *image_.bitmap(), target_size_,
                     layout_, resized_bitmap),
          base::Bind(&WallpaperResizer::OnResizeFinished,
                     weak_ptr_factory_.GetWeakPtr(),
                     base::Owned(resized_bitmap)))) {
    LOG(WARNING) << "PostSequencedWorkerTask failed. "
                 << "Wallpaper may not be resized.";
  }
}

void WallpaperResizer::AddObserver(WallpaperResizerObserver* observer) {
  observers_.AddObserver(observer);
}

void WallpaperResizer::RemoveObserver(WallpaperResizerObserver* observer) {
  observers_.RemoveObserver(observer);
}

void WallpaperResizer::OnResizeFinished(SkBitmap* resized_bitmap) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  image_ = gfx::ImageSkia::CreateFrom1xBitmap(*resized_bitmap);
  FOR_EACH_OBSERVER(WallpaperResizerObserver, observers_,
                    OnWallpaperResized());
}

} // namespace ash
