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

#import "chrome/browser/ui/cocoa/tabpose_window.h"

#import <QuartzCore/QuartzCore.h>

#include <algorithm>

#include "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/memory/weak_ptr.h"
#include "base/prefs/pref_service.h"
#include "base/strings/sys_string_conversions.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/devtools/devtools_window.h"
#include "chrome/browser/extensions/tab_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/thumbnails/render_widget_snapshot_taker.h"
#include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h"
#import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h"
#import "chrome/browser/ui/cocoa/browser_window_controller.h"
#import "chrome/browser/ui/cocoa/infobars/infobar_container_controller.h"
#import "chrome/browser/ui/cocoa/tab_contents/favicon_util_mac.h"
#import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h"
#import "chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
#include "grit/theme_resources.h"
#include "grit/ui_resources.h"
#include "skia/ext/skia_utils_mac.h"
#include "third_party/skia/include/utils/mac/SkCGUtils.h"
#include "ui/base/cocoa/animation_utils.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/scoped_cg_context_save_gstate_mac.h"

using content::BrowserThread;
using content::RenderWidgetHost;

// Height of the bottom gradient, in pixels.
const CGFloat kBottomGradientHeight = 50;

// The shade of gray at the top of the window. There's a  gradient from
// this to |kCentralGray| at the top of the window.
const CGFloat kTopGray = 0.77;

// The shade of gray at the center of the window. Most of the window background
// has this color.
const CGFloat kCentralGray = 0.6;

// The shade of gray at the bottom of the window. There's a gradient from
// |kCentralGray| to this at the bottom of the window, |kBottomGradientHeight|
// high.
const CGFloat kBottomGray = 0.5;

NSString* const kAnimationIdKey = @"AnimationId";
NSString* const kAnimationIdFadeIn = @"FadeIn";
NSString* const kAnimationIdFadeOut = @"FadeOut";

const CGFloat kDefaultAnimationDuration = 0.25;  // In seconds.
const CGFloat kSlomoFactor = 4;
const CGFloat kObserverChangeAnimationDuration = 0.25;  // In seconds.
const CGFloat kSelectionInset = 5;

// CAGradientLayer is 10.6-only -- roll our own.
@interface GrayGradientLayer : CALayer {
 @private
  CGFloat startGray_;
  CGFloat endGray_;
}
- (id)initWithStartGray:(CGFloat)startGray endGray:(CGFloat)endGray;
- (void)drawInContext:(CGContextRef)context;
@end

@implementation GrayGradientLayer
- (id)initWithStartGray:(CGFloat)startGray endGray:(CGFloat)endGray {
  if ((self = [super init])) {
    startGray_ = startGray;
    endGray_ = endGray;
  }
  return self;
}

- (void)drawInContext:(CGContextRef)context {
  base::ScopedCFTypeRef<CGColorSpaceRef> grayColorSpace(
      CGColorSpaceCreateWithName(kCGColorSpaceGenericGray));
  CGFloat grays[] = { startGray_, 1.0, endGray_, 1.0 };
  CGFloat locations[] = { 0, 1 };
  base::ScopedCFTypeRef<CGGradientRef> gradient(
      CGGradientCreateWithColorComponents(
          grayColorSpace.get(), grays, locations, arraysize(locations)));
  CGPoint topLeft = CGPointMake(0.0, self.bounds.size.height);
  CGContextDrawLinearGradient(context, gradient.get(), topLeft, CGPointZero, 0);
}
@end

namespace tabpose {
class ThumbnailLoader;
}

// A CALayer that draws a thumbnail for a WebContents object. The layer
// tries to draw the WebContents's backing store directly if possible, and
// requests a thumbnail bitmap from the WebContents's renderer process if not.
@interface ThumbnailLayer : CALayer {
  // The WebContents the thumbnail is for.
  content::WebContents* contents_;  // weak

  // The size the thumbnail is drawn at when zoomed in.
  NSSize fullSize_;

  // Used to load a thumbnail, if required.
  scoped_refptr<tabpose::ThumbnailLoader> loader_;

  // If the backing store couldn't be used and a thumbnail was returned from a
  // renderer process, it's stored in |thumbnail_|.
  base::ScopedCFTypeRef<CGImageRef> thumbnail_;

  // True if the layer already sent a thumbnail request to a renderer.
  BOOL didSendLoad_;
}
- (id)initWithWebContents:(content::WebContents*)contents
                 fullSize:(NSSize)fullSize;
- (void)drawInContext:(CGContextRef)context;
- (void)setThumbnail:(const SkBitmap&)bitmap;
@end

namespace tabpose {

// ThumbnailLoader talks to the renderer process to load a thumbnail of a given
// RenderWidgetHost, and sends the thumbnail back to a ThumbnailLayer once it
// comes back from the renderer.
class ThumbnailLoader : public base::RefCountedThreadSafe<ThumbnailLoader> {
 public:
  ThumbnailLoader(gfx::Size size, RenderWidgetHost* rwh, ThumbnailLayer* layer)
      : size_(size), rwh_(rwh), layer_(layer), weak_factory_(this) {}

  // Starts the fetch.
  void LoadThumbnail();

 private:
  friend class base::RefCountedThreadSafe<ThumbnailLoader>;
  ~ThumbnailLoader() {
  }

  void DidReceiveBitmap(const SkBitmap& bitmap) {
    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    [layer_ setThumbnail:bitmap];
  }

  gfx::Size size_;
  RenderWidgetHost* rwh_;  // weak
  ThumbnailLayer* layer_;  // weak, owns us
  base::WeakPtrFactory<ThumbnailLoader> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(ThumbnailLoader);
};

void ThumbnailLoader::LoadThumbnail() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  // As mentioned in ThumbnailLayer's -drawInContext:, it's sufficient to have
  // thumbnails at the zoomed-out pixel size for all but the thumbnail the user
  // clicks on in the end. But we don't don't which thumbnail that will be, so
  // keep it simple and request full thumbnails for everything.
  // TODO(thakis): Request smaller thumbnails for users with many tabs.
  gfx::Size page_size(size_);  // Logical size the renderer renders at.
  gfx::Size pixel_size(size_);  // Physical pixel size the image is rendered at.

  // Will send an IPC to the renderer on the IO thread.
  g_browser_process->GetRenderWidgetSnapshotTaker()->AskForSnapshot(
      rwh_,
      base::Bind(&ThumbnailLoader::DidReceiveBitmap,
                 weak_factory_.GetWeakPtr()),
      page_size,
      pixel_size);
}

}  // namespace tabpose

@implementation ThumbnailLayer

- (id)initWithWebContents:(content::WebContents*)contents
                 fullSize:(NSSize)fullSize {
  CHECK(contents);
  if ((self = [super init])) {
    contents_ = contents;
    fullSize_ = fullSize;
  }
  return self;
}

- (void)setWebContents:(content::WebContents*)contents {
  contents_ = contents;
}

- (void)setThumbnail:(const SkBitmap&)bitmap {
  // SkCreateCGImageRef() holds on to |bitmaps|'s memory, so this doesn't
  // create a copy. The renderer always draws data in the system colorspace.
  thumbnail_.reset(SkCreateCGImageRefWithColorspace(
      bitmap, base::mac::GetSystemColorSpace()));
  loader_ = NULL;
  [self setNeedsDisplay];
}

- (int)topOffset {
  int topOffset = 0;

  // Medium term, we want to show thumbs of the actual info bar views, which
  // means I need to create InfoBarControllers here.
  NSWindow* window = [contents_->GetView()->GetNativeView() window];
  NSWindowController* windowController = [window windowController];
  if ([windowController isKindOfClass:[BrowserWindowController class]]) {
    BrowserWindowController* bwc =
        static_cast<BrowserWindowController*>(windowController);
    InfoBarContainerController* infoBarContainer =
        [bwc infoBarContainerController];
    // TODO(thakis|rsesek): This is not correct for background tabs with
    // infobars as the aspect ratio will be wrong. Fix that.
    topOffset += NSHeight([[infoBarContainer view] frame]) -
        [infoBarContainer overlappingTipHeight];
  }

  BookmarkTabHelper* bookmark_tab_helper =
      BookmarkTabHelper::FromWebContents(contents_);
  Profile* profile =
      Profile::FromBrowserContext(contents_->GetBrowserContext());
  bool always_show_bookmark_bar =
      profile->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar);
  bool has_detached_bookmark_bar =
      bookmark_tab_helper->ShouldShowBookmarkBar() &&
      !always_show_bookmark_bar;
  if (has_detached_bookmark_bar)
    topOffset += chrome::kNTPBookmarkBarHeight;

  return topOffset;
}

- (int)bottomOffset {
  int bottomOffset = 0;
  DevToolsWindow* devToolsWindow =
      DevToolsWindow::GetDockedInstanceForInspectedTab(contents_);
  content::WebContents* devToolsContents =
      devToolsWindow ? devToolsWindow->web_contents() : NULL;
  if (devToolsContents && devToolsContents->GetRenderViewHost() &&
      devToolsContents->GetRenderViewHost()->GetView()) {
    // The devtool's size might not be up-to-date, but since its height doesn't
    // change on window resize, and since most users don't use devtools, this is
    // good enough.
    bottomOffset += devToolsContents->GetRenderViewHost()->GetView()->
        GetViewBounds().height();
    bottomOffset += 1;  // :-( Divider line between web contents and devtools.
  }
  return bottomOffset;
}

- (void)drawInContext:(CGContextRef)context {
  RenderWidgetHost* rwh = contents_->GetRenderViewHost();
  // NULL if renderer crashed.
  content::RenderWidgetHostView* rwhv = rwh ? rwh->GetView() : NULL;
  if (!rwhv) {
    // TODO(thakis): Maybe draw a sad tab layer?
    [super drawInContext:context];
    return;
  }

  // The size of the WebContents's RenderWidgetHost might not fit to the
  // current browser window at all, for example if the window was resized while
  // this WebContents object was not an active tab.
  // Compute the required size ourselves. Leave room for eventual infobars and
  // a detached bookmarks bar on the top, and for the devtools on the bottom.
  // Download shelf is not included in the |fullSize| rect, so no need to
  // correct for it here.
  // TODO(thakis): This is not resolution-independent.
  int topOffset = [self topOffset];
  int bottomOffset = [self bottomOffset];
  gfx::Size desiredThumbSize(fullSize_.width,
                             fullSize_.height - topOffset - bottomOffset);

  // We need to ask the renderer for a thumbnail if
  // a) there's no backing store or
  // b) the backing store's size doesn't match our required size and
  // c) we didn't already send a thumbnail request to the renderer.
  bool draw_backing_store = rwh->GetBackingStoreSize() == desiredThumbSize;

  // Next weirdness: The destination rect. If the layer is |fullSize_| big, the
  // destination rect is (0, bottomOffset), (fullSize_.width, topOffset). But we
  // might be amidst an animation, so interpolate that rect.
  CGRect destRect = [self bounds];
  CGFloat scale = destRect.size.width / fullSize_.width;
  destRect.origin.y += bottomOffset * scale;
  destRect.size.height -= (bottomOffset + topOffset) * scale;

  // TODO(thakis): Draw infobars, detached bookmark bar as well.

  // If we haven't already, sent a thumbnail request to the renderer.
  if (!draw_backing_store && !didSendLoad_) {
    // Either the tab was never visible, or its backing store got evicted, or
    // the size of the backing store is wrong.

    // We only need a thumbnail the size of the zoomed-out layer for all
    // layers except the one the user clicks on. But since we can't know which
    // layer that is, request full-resolution layers for all tabs. This is
    // simple and seems to work in practice.
    loader_ = new tabpose::ThumbnailLoader(desiredThumbSize, rwh, self);
    loader_->LoadThumbnail();
    didSendLoad_ = YES;

    // Fill with bg color.
    [super drawInContext:context];
  }

  if (draw_backing_store) {
    // Backing store 'cache' hit!
    // TODO(thakis): Add a sublayer for each accelerated surface in the rwhv.
    // Until then, accelerated layers (CoreAnimation NPAPI plugins, compositor)
    // won't show up in tabpose.
    rwh->CopyFromBackingStoreToCGContext(destRect, context);
  } else if (thumbnail_) {
    // No cache hit, but the renderer returned a thumbnail to us.
    gfx::ScopedCGContextSaveGState save_gstate(context);
    CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
    CGContextDrawImage(context, destRect, thumbnail_.get());
  }
}

@end

// Given the number |n| of tiles with a desired aspect ratio of |a| and a
// desired distance |dx|, |dy| between tiles, returns how many tiles fit
// vertically into a rectangle with the dimensions |w_c|, |h_c|. This returns
// an exact solution, which is usually a fractional number.
static float FitNRectsWithAspectIntoBoundingSizeWithConstantPadding(
    int n, double a, int w_c, int h_c, int dx, int dy) {
  // We want to have the small rects have the same aspect ratio a as a full
  // tab. Let w, h be the size of a small rect, and w_c, h_c the size of the
  // container. dx, dy are the distances between small rects in x, y direction.

  // Geometry yields:
  // w_c = nx * (w + dx) - dx <=> w = (w_c + d_x) / nx - d_x
  // h_c = ny * (h + dy) - dy <=> h = (h_c + d_y) / ny - d_t
  // Plugging this into
  // a := tab_width / tab_height = w / h
  // yields
  // a = ((w_c - (nx - 1)*d_x)*ny) / (nx*(h_c - (ny - 1)*d_y))
  // Plugging in nx = n/ny and pen and paper (or wolfram alpha:
  // http://www.wolframalpha.com/input/?i=(-sqrt((d+n-a+f+n)^2-4+(a+f%2Ba+h)+(-d+n-n+w))%2Ba+f+n-d+n)/(2+a+(f%2Bh)) , (solution for nx)
  // http://www.wolframalpha.com/input/?i=+(-sqrt((a+f+n-d+n)^2-4+(d%2Bw)+(-a+f+n-a+h+n))-a+f+n%2Bd+n)/(2+(d%2Bw)) , (solution for ny)
  // ) gives us nx and ny (but the wrong root -- s/-sqrt(FOO)/sqrt(FOO)/.

  // This function returns ny.
  return (sqrt(pow(n * (a * dy - dx), 2) +
               4 * n * a * (dx + w_c) * (dy + h_c)) -
          n * (a * dy - dx))
      /
         (2 * (dx + w_c));
}

namespace tabpose {

CGFloat ScaleWithOrigin(CGFloat x, CGFloat origin, CGFloat scale) {
  return (x - origin) * scale + origin;
}

NSRect ScaleRectWithOrigin(NSRect r, NSPoint p, CGFloat scale) {
  return NSMakeRect(ScaleWithOrigin(NSMinX(r), p.x, scale),
                    ScaleWithOrigin(NSMinY(r), p.y, scale),
                    NSWidth(r) * scale,
                    NSHeight(r) * scale);
}

// A tile is what is shown for a single tab in tabpose mode. It consists of a
// title, favicon, thumbnail image, and pre- and postanimation rects.
class Tile {
 public:
  Tile() {}

  // Returns the rectangle this thumbnail is at at the beginning of the zoom-in
  // animation. |tile| is the rectangle that's covering the whole tab area when
  // the animation starts.
  NSRect GetStartRectRelativeTo(const Tile& tile) const;
  NSRect thumb_rect() const { return thumb_rect_; }

  NSRect GetFaviconStartRectRelativeTo(const Tile& tile) const;
  NSRect favicon_rect() const { return NSIntegralRect(favicon_rect_); }
  NSImage* favicon() const;

  // This changes |title_rect| and |favicon_rect| such that the favicon is on
  // the font's baseline and that the minimum distance between thumb rect and
  // favicon and title rects doesn't change.
  // The view code
  // 1. queries desired font size by calling |title_font_size()|
  // 2. loads that font
  // 3. calls |set_font_metrics()| which updates the title rect
  // 4. receives the title rect and puts the title on it with the font from 2.
  void set_font_metrics(CGFloat ascender, CGFloat descender);
  CGFloat title_font_size() const { return title_font_size_; }

  NSRect GetTitleStartRectRelativeTo(const Tile& tile) const;
  NSRect title_rect() const { return NSIntegralRect(title_rect_); }

  // Returns an unelided title. The view logic is responsible for eliding.
  const string16& title() const {
    return contents_->GetTitle();
  }

  content::WebContents* web_contents() const { return contents_; }
  void set_tab_contents(content::WebContents* new_contents) {
    contents_ = new_contents;
  }

 private:
  friend class TileSet;

  // The thumb rect includes infobars, detached thumbnail bar, web contents,
  // and devtools.
  NSRect thumb_rect_;
  NSRect start_thumb_rect_;

  NSRect favicon_rect_;

  CGFloat title_font_size_;
  NSRect title_rect_;

  content::WebContents* contents_;  // weak

  DISALLOW_COPY_AND_ASSIGN(Tile);
};

NSRect Tile::GetStartRectRelativeTo(const Tile& tile) const {
  NSRect rect = start_thumb_rect_;
  rect.origin.x -= tile.start_thumb_rect_.origin.x;
  rect.origin.y -= tile.start_thumb_rect_.origin.y;
  return rect;
}

NSRect Tile::GetFaviconStartRectRelativeTo(const Tile& tile) const {
  NSRect thumb_start = GetStartRectRelativeTo(tile);
  CGFloat scale_to_start = NSWidth(thumb_start) / NSWidth(thumb_rect_);
  NSRect rect =
      ScaleRectWithOrigin(favicon_rect_, thumb_rect_.origin, scale_to_start);
  rect.origin.x += NSMinX(thumb_start) - NSMinX(thumb_rect_);
  rect.origin.y += NSMinY(thumb_start) - NSMinY(thumb_rect_);
  return rect;
}

NSImage* Tile::favicon() const {
  extensions::TabHelper* extensions_tab_helper =
      extensions::TabHelper::FromWebContents(contents_);
  if (extensions_tab_helper->is_app()) {
    SkBitmap* bitmap = extensions_tab_helper->GetExtensionAppIcon();
    if (bitmap)
      return gfx::SkBitmapToNSImage(*bitmap);
  }
  return mac::FaviconForWebContents(contents_);
}

NSRect Tile::GetTitleStartRectRelativeTo(const Tile& tile) const {
  NSRect thumb_start = GetStartRectRelativeTo(tile);
  CGFloat scale_to_start = NSWidth(thumb_start) / NSWidth(thumb_rect_);
  NSRect rect =
      ScaleRectWithOrigin(title_rect_, thumb_rect_.origin, scale_to_start);
  rect.origin.x += NSMinX(thumb_start) - NSMinX(thumb_rect_);
  rect.origin.y += NSMinY(thumb_start) - NSMinY(thumb_rect_);
  return rect;
}

// Changes |title_rect| and |favicon_rect| such that the favicon's and the
// title's vertical center is aligned and that the minimum distance between
// the thumb rect and favicon and title rects doesn't change.
void Tile::set_font_metrics(CGFloat ascender, CGFloat descender) {
  // Make the title height big enough to fit the font, and adopt the title
  // position to keep its distance from the thumb rect.
  title_rect_.origin.y -= ascender + descender - NSHeight(title_rect_);
  title_rect_.size.height = ascender + descender;

  // Align vertical center. Both rects are currently aligned on their top edge.
  CGFloat delta_y = NSMidY(title_rect_) - NSMidY(favicon_rect_);
  if (delta_y > 0) {
    // Title is higher: Move favicon down to align the centers.
    favicon_rect_.origin.y += delta_y;
  } else {
    // Favicon is higher: Move title down to align the centers.
    title_rect_.origin.y -= delta_y;
  }
}

// A tileset is responsible for owning and laying out all |Tile|s shown in a
// tabpose window.
class TileSet {
 public:
  TileSet() {}

  // Fills in |tiles_|.
  void Build(TabStripModel* source_model);

  // Computes coordinates for |tiles_|.
  void Layout(NSRect containing_rect);

  int selected_index() const { return selected_index_; }
  void set_selected_index(int index);

  const Tile& selected_tile() const { return *tiles_[selected_index()]; }
  Tile& tile_at(int index) { return *tiles_[index]; }
  const Tile& tile_at(int index) const { return *tiles_[index]; }

  // These return which index needs to be selected when the user presses
  // up, down, left, or right respectively.
  int up_index() const;
  int down_index() const;
  int left_index() const;
  int right_index() const;

  // These return which index needs to be selected on tab / shift-tab.
  int next_index() const;
  int previous_index() const;

  // Inserts a new Tile object containing |contents| at |index|. Does no
  // relayout.
  void InsertTileAt(int index, content::WebContents* contents);

  // Removes the Tile object at |index|. Does no relayout.
  void RemoveTileAt(int index);

  // Moves the Tile object at |from_index| to |to_index|. Since this doesn't
  // change the number of tiles, relayout can be done just by swapping the
  // tile rectangles in the index interval [from_index, to_index], so this does
  // layout.
  void MoveTileFromTo(int from_index, int to_index);

 private:
  int count_x() const {
    return ceilf(tiles_.size() / static_cast<float>(count_y_));
  }
  int count_y() const {
    return count_y_;
  }
  int last_row_count_x() const {
    return tiles_.size() - count_x() * (count_y() - 1);
  }
  int tiles_in_row(int row) const {
    return row != count_y() - 1 ? count_x() : last_row_count_x();
  }
  void index_to_tile_xy(int index, int* tile_x, int* tile_y) const {
    *tile_x = index % count_x();
    *tile_y = index / count_x();
  }
  int tile_xy_to_index(int tile_x, int tile_y) const {
    return tile_y * count_x() + tile_x;
  }

  ScopedVector<Tile> tiles_;
  int selected_index_;
  int count_y_;

  DISALLOW_COPY_AND_ASSIGN(TileSet);
};

void TileSet::Build(TabStripModel* source_model) {
  selected_index_ =  source_model->active_index();
  tiles_.resize(source_model->count());
  for (size_t i = 0; i < tiles_.size(); ++i) {
    tiles_[i] = new Tile;
    tiles_[i]->contents_ = source_model->GetWebContentsAt(i);
  }
}

void TileSet::Layout(NSRect containing_rect) {
  int tile_count = tiles_.size();
  if (tile_count == 0)  // Happens e.g. during test shutdown.
    return;

  // Room around the tiles insde of |containing_rect|.
  const int kSmallPaddingTop = 30;
  const int kSmallPaddingLeft = 30;
  const int kSmallPaddingRight = 30;
  const int kSmallPaddingBottom = 30;

  // Favicon / title area.
  const int kThumbTitlePaddingY = 6;
  const int kFaviconSize = 16;
  const int kTitleHeight = 14;  // Font size.
  const int kTitleExtraHeight = kThumbTitlePaddingY + kTitleHeight;
  const int kFaviconExtraHeight = kThumbTitlePaddingY + kFaviconSize;
  const int kFaviconTitleDistanceX = 6;
  const int kFooterExtraHeight =
      std::max(kFaviconExtraHeight, kTitleExtraHeight);

  // Room between the tiles.
  const int kSmallPaddingX = 15;
  const int kSmallPaddingY = kFooterExtraHeight;

  // Aspect ratio of the containing rect.
  CGFloat aspect = NSWidth(containing_rect) / NSHeight(containing_rect);

  // Room left in container after the outer padding is removed.
  double container_width =
      NSWidth(containing_rect) - kSmallPaddingLeft - kSmallPaddingRight;
  double container_height =
      NSHeight(containing_rect) - kSmallPaddingTop - kSmallPaddingBottom;

  // The tricky part is figuring out the size of a tab thumbnail, or since the
  // size of the containing rect is known, the number of tiles in x and y
  // direction.
  // Given are the size of the containing rect, and the number of thumbnails
  // that need to fit into that rect. The aspect ratio of the thumbnails needs
  // to be the same as that of |containing_rect|, else they will look distorted.
  // The thumbnails need to be distributed such that
  // |count_x * count_y >= tile_count|, and such that wasted space is minimized.
  //  See the comments in
  // |FitNRectsWithAspectIntoBoundingSizeWithConstantPadding()| for a more
  // detailed discussion.
  // TODO(thakis): It might be good enough to choose |count_x| and |count_y|
  //   such that count_x / count_y is roughly equal to |aspect|?
  double fny = FitNRectsWithAspectIntoBoundingSizeWithConstantPadding(
      tile_count, aspect,
      container_width, container_height - kFooterExtraHeight,
      kSmallPaddingX, kSmallPaddingY + kFooterExtraHeight);
  count_y_ = roundf(fny);

  // Now that |count_x()| and |count_y_| are known, it's straightforward to
  // compute thumbnail width/height. See comment in
  // |FitNRectsWithAspectIntoBoundingSizeWithConstantPadding| for the derivation
  // of these two formulas.
  int small_width =
      floor((container_width + kSmallPaddingX) / static_cast<float>(count_x()) -
            kSmallPaddingX);
  int small_height =
      floor((container_height + kSmallPaddingY) / static_cast<float>(count_y_) -
            (kSmallPaddingY + kFooterExtraHeight));

  // |small_width / small_height| has only roughly an aspect ratio of |aspect|.
  // Shrink the thumbnail rect to make the aspect ratio fit exactly, and add
  // the extra space won by shrinking to the outer padding.
  int smallExtraPaddingLeft = 0;
  int smallExtraPaddingTop = 0;
  if (aspect > small_width/static_cast<float>(small_height)) {
    small_height = small_width / aspect;
    CGFloat all_tiles_height =
        (small_height + kSmallPaddingY + kFooterExtraHeight) * count_y() -
        (kSmallPaddingY + kFooterExtraHeight);
    smallExtraPaddingTop = (container_height - all_tiles_height)/2;
  } else {
    small_width = small_height * aspect;
    CGFloat all_tiles_width =
        (small_width + kSmallPaddingX) * count_x() - kSmallPaddingX;
    smallExtraPaddingLeft = (container_width - all_tiles_width)/2;
  }

  // Compute inter-tile padding in the zoomed-out view.
  CGFloat scale_small_to_big =
      NSWidth(containing_rect) / static_cast<float>(small_width);
  CGFloat big_padding_x = kSmallPaddingX * scale_small_to_big;
  CGFloat big_padding_y =
      (kSmallPaddingY + kFooterExtraHeight) * scale_small_to_big;

  // Now all dimensions are known. Lay out all tiles on a regular grid:
  // X X X X
  // X X X X
  // X X
  for (int row = 0, i = 0; i < tile_count; ++row) {
    for (int col = 0; col < count_x() && i < tile_count; ++col, ++i) {
      // Compute the smalled, zoomed-out thumbnail rect.
      tiles_[i]->thumb_rect_.size = NSMakeSize(small_width, small_height);

      int small_x = col * (small_width + kSmallPaddingX) +
                    kSmallPaddingLeft + smallExtraPaddingLeft;
      int small_y = row * (small_height + kSmallPaddingY + kFooterExtraHeight) +
                    kSmallPaddingTop + smallExtraPaddingTop;

      tiles_[i]->thumb_rect_.origin = NSMakePoint(
          small_x, NSHeight(containing_rect) - small_y - small_height);

      tiles_[i]->favicon_rect_.size = NSMakeSize(kFaviconSize, kFaviconSize);
      tiles_[i]->favicon_rect_.origin = NSMakePoint(
          small_x,
          NSHeight(containing_rect) -
              (small_y + small_height + kFaviconExtraHeight));

      // Align lower left corner of title rect with lower left corner of favicon
      // for now. The final position is computed later by
      // |Tile::set_font_metrics()|.
      tiles_[i]->title_font_size_ = kTitleHeight;
      tiles_[i]->title_rect_.origin = NSMakePoint(
          NSMaxX(tiles_[i]->favicon_rect()) + kFaviconTitleDistanceX,
          NSMinY(tiles_[i]->favicon_rect()));
      tiles_[i]->title_rect_.size = NSMakeSize(
          small_width -
              NSWidth(tiles_[i]->favicon_rect()) - kFaviconTitleDistanceX,
          kTitleHeight);

      // Compute the big, pre-zoom thumbnail rect.
      tiles_[i]->start_thumb_rect_.size = containing_rect.size;

      int big_x = col * (NSWidth(containing_rect) + big_padding_x);
      int big_y = row * (NSHeight(containing_rect) + big_padding_y);
      tiles_[i]->start_thumb_rect_.origin = NSMakePoint(big_x, -big_y);
    }
  }
}

void TileSet::set_selected_index(int index) {
  CHECK_GE(index, 0);
  CHECK_LT(index, static_cast<int>(tiles_.size()));
  selected_index_ = index;
}

// Given a |value| in [0, from_scale), map it into [0, to_scale) such that:
// * [0, from_scale) ends up in the middle of [0, to_scale) if the latter is
//   a bigger range
// * The middle of [0, from_scale) is mapped to [0, to_scale), and the parts
//   of the former that don't fit are mapped to 0 and to_scale - respectively
//   if the former is a bigger range.
static int rescale(int value, int from_scale, int to_scale) {
  int left = (to_scale - from_scale) / 2;
  int result = value + left;
  if (result < 0)
    return 0;
  if (result >= to_scale)
    return to_scale - 1;
  return result;
}

int TileSet::up_index() const {
  int tile_x, tile_y;
  index_to_tile_xy(selected_index(), &tile_x, &tile_y);
  tile_y -= 1;
  if (tile_y == count_y() - 2) {
    // Transition from last row to second-to-last row.
    tile_x = rescale(tile_x, last_row_count_x(), count_x());
  } else if (tile_y < 0) {
    // Transition from first row to last row.
    tile_x = rescale(tile_x, count_x(), last_row_count_x());
    tile_y = count_y() - 1;
  }
  return tile_xy_to_index(tile_x, tile_y);
}

int TileSet::down_index() const {
  int tile_x, tile_y;
  index_to_tile_xy(selected_index(), &tile_x, &tile_y);
  tile_y += 1;
  if (tile_y == count_y() - 1) {
    // Transition from second-to-last row to last row.
    tile_x = rescale(tile_x, count_x(), last_row_count_x());
  } else if (tile_y >= count_y()) {
    // Transition from last row to first row.
    tile_x = rescale(tile_x, last_row_count_x(), count_x());
    tile_y = 0;
  }
  return tile_xy_to_index(tile_x, tile_y);
}

int TileSet::left_index() const {
  int tile_x, tile_y;
  index_to_tile_xy(selected_index(), &tile_x, &tile_y);
  tile_x -= 1;
  if (tile_x < 0)
    tile_x = tiles_in_row(tile_y) - 1;
  return tile_xy_to_index(tile_x, tile_y);
}

int TileSet::right_index() const {
  int tile_x, tile_y;
  index_to_tile_xy(selected_index(), &tile_x, &tile_y);
  tile_x += 1;
  if (tile_x >= tiles_in_row(tile_y))
    tile_x = 0;
  return tile_xy_to_index(tile_x, tile_y);
}

int TileSet::next_index() const {
  int new_index = selected_index() + 1;
  if (new_index >= static_cast<int>(tiles_.size()))
    new_index = 0;
  return new_index;
}

int TileSet::previous_index() const {
  int new_index = selected_index() - 1;
  if (new_index < 0)
    new_index = tiles_.size() - 1;
  return new_index;
}

void TileSet::InsertTileAt(int index, content::WebContents* contents) {
  tiles_.insert(tiles_.begin() + index, new Tile);
  tiles_[index]->contents_ = contents;
}

void TileSet::RemoveTileAt(int index) {
  tiles_.erase(tiles_.begin() + index);
}

// Moves the Tile object at |from_index| to |to_index|. Also updates rectangles
// so that the tiles stay in a left-to-right, top-to-bottom layout when walked
// in sequential order.
void TileSet::MoveTileFromTo(int from_index, int to_index) {
  NSRect thumb = tiles_[from_index]->thumb_rect_;
  NSRect start_thumb = tiles_[from_index]->start_thumb_rect_;
  NSRect favicon = tiles_[from_index]->favicon_rect_;
  NSRect title = tiles_[from_index]->title_rect_;

  scoped_ptr<Tile> tile(tiles_[from_index]);
  tiles_.weak_erase(tiles_.begin() + from_index);
  tiles_.insert(tiles_.begin() + to_index, tile.release());

  int step = from_index < to_index ? -1 : 1;
  for (int i = to_index; (i - from_index) * step < 0; i += step) {
    tiles_[i]->thumb_rect_ = tiles_[i + step]->thumb_rect_;
    tiles_[i]->start_thumb_rect_ = tiles_[i + step]->start_thumb_rect_;
    tiles_[i]->favicon_rect_ = tiles_[i + step]->favicon_rect_;
    tiles_[i]->title_rect_ = tiles_[i + step]->title_rect_;
  }
  tiles_[from_index]->thumb_rect_ = thumb;
  tiles_[from_index]->start_thumb_rect_ = start_thumb;
  tiles_[from_index]->favicon_rect_ = favicon;
  tiles_[from_index]->title_rect_ = title;
}

}  // namespace tabpose

void AnimateScaledCALayerFrameFromTo(
    CALayer* layer,
    const NSRect& from, CGFloat from_scale,
    const NSRect& to, CGFloat to_scale,
    NSTimeInterval duration, id boundsAnimationDelegate) {
  // http://developer.apple.com/mac/library/qa/qa2008/qa1620.html
  CABasicAnimation* animation;

  animation = [CABasicAnimation animationWithKeyPath:@"bounds"];
  animation.fromValue = [NSValue valueWithRect:from];
  animation.toValue = [NSValue valueWithRect:to];
  animation.duration = duration;
  animation.timingFunction =
      [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
  animation.delegate = boundsAnimationDelegate;

  // Update the layer's bounds so the layer doesn't snap back when the animation
  // completes.
  layer.bounds = NSRectToCGRect(to);

  // Add the animation, overriding the implicit animation.
  [layer addAnimation:animation forKey:@"bounds"];

  // Prepare the animation from the current position to the new position.
  NSPoint opoint = from.origin;
  NSPoint point = to.origin;

  // Adapt to anchorPoint.
  opoint.x += NSWidth(from) * from_scale * layer.anchorPoint.x;
  opoint.y += NSHeight(from) * from_scale * layer.anchorPoint.y;
  point.x += NSWidth(to) * to_scale * layer.anchorPoint.x;
  point.y += NSHeight(to) * to_scale * layer.anchorPoint.y;

  animation = [CABasicAnimation animationWithKeyPath:@"position"];
  animation.fromValue = [NSValue valueWithPoint:opoint];
  animation.toValue = [NSValue valueWithPoint:point];
  animation.duration = duration;
  animation.timingFunction =
      [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];

  // Update the layer's position so that the layer doesn't snap back when the
  // animation completes.
  layer.position = NSPointToCGPoint(point);

  // Add the animation, overriding the implicit animation.
  [layer addAnimation:animation forKey:@"position"];
}

void AnimateCALayerFrameFromTo(
    CALayer* layer, const NSRect& from, const NSRect& to,
    NSTimeInterval duration, id boundsAnimationDelegate) {
  AnimateScaledCALayerFrameFromTo(
      layer, from, 1.0, to, 1.0, duration, boundsAnimationDelegate);
}

void AnimateCALayerOpacityFromTo(
    CALayer* layer, double from, double to, NSTimeInterval duration) {
  CABasicAnimation* animation;
  animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
  animation.fromValue = [NSNumber numberWithFloat:from];
  animation.toValue = [NSNumber numberWithFloat:to];
  animation.duration = duration;

  layer.opacity = to;
  // Add the animation, overriding the implicit animation.
  [layer addAnimation:animation forKey:@"opacity"];
}

@interface TabposeWindow (Private)
- (id)initForWindow:(NSWindow*)parent
               rect:(NSRect)rect
              slomo:(BOOL)slomo
      tabStripModel:(TabStripModel*)tabStripModel;

// Creates and initializes the CALayer in the background and all the CALayers
// for the thumbnails, favicons, and titles.
- (void)setUpLayersInSlomo:(BOOL)slomo;

// Tells the browser to make the tab corresponding to currently selected
// thumbnail the current tab and starts the tabpose exit animmation.
- (void)fadeAwayInSlomo:(BOOL)slomo;

// Returns the CALayer for the close button belonging to the thumbnail at
// index |index|.
- (CALayer*)closebuttonLayerAtIndex:(NSUInteger)index;

// Updates the visibility of all closebutton layers.
- (void)updateClosebuttonLayersVisibility;
@end

@implementation TabposeWindow

+ (id)openTabposeFor:(NSWindow*)parent
                rect:(NSRect)rect
               slomo:(BOOL)slomo
       tabStripModel:(TabStripModel*)tabStripModel {
  // Releases itself when closed.
  return [[TabposeWindow alloc]
      initForWindow:parent rect:rect slomo:slomo tabStripModel:tabStripModel];
}

- (id)initForWindow:(NSWindow*)parent
               rect:(NSRect)rect
              slomo:(BOOL)slomo
      tabStripModel:(TabStripModel*)tabStripModel {
  NSRect frame = [parent frame];
  if ((self = [super initWithContentRect:frame
                               styleMask:NSBorderlessWindowMask
                                 backing:NSBackingStoreBuffered
                                   defer:NO])) {
    containingRect_ = rect;
    tabStripModel_ = tabStripModel;
    state_ = tabpose::kFadingIn;
    tileSet_.reset(new tabpose::TileSet);
    tabStripModelObserverBridge_.reset(
        new TabStripModelObserverBridge(tabStripModel_, self));
    NSImage* nsCloseIcon =
        ResourceBundle::GetSharedInstance().GetNativeImageNamed(
            IDR_TABPOSE_CLOSE).ToNSImage();
    closeIcon_.reset(base::mac::CopyNSImageToCGImage(nsCloseIcon));
    [self setReleasedWhenClosed:YES];
    [self setOpaque:NO];
    [self setBackgroundColor:[NSColor clearColor]];
    [self setUpLayersInSlomo:slomo];
    [self setAcceptsMouseMovedEvents:YES];
    [parent addChildWindow:self ordered:NSWindowAbove];
    [self makeKeyAndOrderFront:self];
  }
  return self;
}

- (CALayer*)selectedLayer {
  return [allThumbnailLayers_ objectAtIndex:tileSet_->selected_index()];
}

- (void)selectTileAtIndexWithoutAnimation:(int)newIndex {
  ScopedCAActionDisabler disabler;
  const tabpose::Tile& tile = tileSet_->tile_at(newIndex);
  selectionHighlight_.frame =
      NSRectToCGRect(NSInsetRect(tile.thumb_rect(),
                     -kSelectionInset, -kSelectionInset));
  tileSet_->set_selected_index(newIndex);

  [self updateClosebuttonLayersVisibility];
}

- (void)addLayersForTile:(tabpose::Tile&)tile
                showZoom:(BOOL)showZoom
                   slomo:(BOOL)slomo
       animationDelegate:(id)animationDelegate {
  base::scoped_nsobject<CALayer> layer(
      [[ThumbnailLayer alloc] initWithWebContents:tile.web_contents()
                                         fullSize:tile.GetStartRectRelativeTo(
                                             tileSet_->selected_tile()).size]);
  [layer setNeedsDisplay];

  NSTimeInterval interval =
      kDefaultAnimationDuration * (slomo ? kSlomoFactor : 1);

  // Background color as placeholder for now.
  layer.get().backgroundColor = CGColorGetConstantColor(kCGColorWhite);
  if (showZoom) {
    AnimateCALayerFrameFromTo(
        layer,
        tile.GetStartRectRelativeTo(tileSet_->selected_tile()),
        tile.thumb_rect(),
        interval,
        animationDelegate);
  } else {
    layer.get().frame = NSRectToCGRect(tile.thumb_rect());
  }

  layer.get().shadowRadius = 10;
  layer.get().shadowOffset = CGSizeMake(0, -10);
  if (state_ == tabpose::kFadedIn)
    layer.get().shadowOpacity = 0.5;

  // Add a close button to the thumb layer.
  CALayer* closeLayer = [CALayer layer];
  closeLayer.contents = reinterpret_cast<id>(closeIcon_.get());
  CGRect closeBounds = {};
  closeBounds.size.width = CGImageGetWidth(closeIcon_);
  closeBounds.size.height = CGImageGetHeight(closeIcon_);
  closeLayer.bounds = closeBounds;
  closeLayer.hidden = YES;

  [closeLayer addConstraint:
      [CAConstraint constraintWithAttribute:kCAConstraintMidX
                                 relativeTo:@"superlayer"
                                  attribute:kCAConstraintMinX]];
  [closeLayer addConstraint:
      [CAConstraint constraintWithAttribute:kCAConstraintMidY
                                 relativeTo:@"superlayer"
                                  attribute:kCAConstraintMaxY]];

  layer.get().layoutManager = [CAConstraintLayoutManager layoutManager];
  [layer.get() addSublayer:closeLayer];

  [bgLayer_ addSublayer:layer];
  [allThumbnailLayers_ addObject:layer];

  // Favicon and title.
  NSFont* font = [NSFont systemFontOfSize:tile.title_font_size()];
  tile.set_font_metrics([font ascender], -[font descender]);

  base::ScopedCFTypeRef<CGImageRef> favicon(
      base::mac::CopyNSImageToCGImage(tile.favicon()));

  CALayer* faviconLayer = [CALayer layer];
  if (showZoom) {
    AnimateCALayerFrameFromTo(
        faviconLayer,
        tile.GetFaviconStartRectRelativeTo(tileSet_->selected_tile()),
        tile.favicon_rect(),
        interval,
        nil);
    AnimateCALayerOpacityFromTo(faviconLayer, 0.0, 1.0, interval);
  } else {
    faviconLayer.frame = NSRectToCGRect(tile.favicon_rect());
  }
  faviconLayer.contents = (id)favicon.get();
  faviconLayer.zPosition = 1;  // On top of the thumb shadow.
  [bgLayer_ addSublayer:faviconLayer];
  [allFaviconLayers_ addObject:faviconLayer];

  // CATextLayers can't animate their fontSize property, at least on 10.5.
  // Animate transform.scale instead.

  // The scaling should have its origin in the layer's upper left corner.
  // This needs to be set before |AnimateCALayerFrameFromTo()| is called.
  CATextLayer* titleLayer = [CATextLayer layer];
  titleLayer.anchorPoint = CGPointMake(0, 1);
  if (showZoom) {
    NSRect fromRect =
        tile.GetTitleStartRectRelativeTo(tileSet_->selected_tile());
    NSRect toRect = tile.title_rect();
    CGFloat scale = NSWidth(fromRect) / NSWidth(toRect);
    fromRect.size = toRect.size;

    // Add scale animation.
    CABasicAnimation* scaleAnimation =
        [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    scaleAnimation.fromValue = [NSNumber numberWithDouble:scale];
    scaleAnimation.toValue = [NSNumber numberWithDouble:1.0];
    scaleAnimation.duration = interval;
    scaleAnimation.timingFunction =
        [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    [titleLayer addAnimation:scaleAnimation forKey:@"transform.scale"];

    // Add the position and opacity animations.
    AnimateScaledCALayerFrameFromTo(
        titleLayer, fromRect, scale, toRect, 1.0, interval, nil);
    AnimateCALayerOpacityFromTo(faviconLayer, 0.0, 1.0, interval);
  } else {
    titleLayer.frame = NSRectToCGRect(tile.title_rect());
  }
  titleLayer.string = base::SysUTF16ToNSString(tile.title());
  titleLayer.fontSize = [font pointSize];
  titleLayer.truncationMode = kCATruncationEnd;
  titleLayer.font = font;
  titleLayer.zPosition = 1;  // On top of the thumb shadow.
  [bgLayer_ addSublayer:titleLayer];
  [allTitleLayers_ addObject:titleLayer];
}

- (void)setUpLayersInSlomo:(BOOL)slomo {
  // Root layer -- covers whole window.
  rootLayer_ = [CALayer layer];

  // In a block so that the layers don't fade in.
  {
    ScopedCAActionDisabler disabler;
    // Background layer -- the visible part of the window.
    gray_.reset(CGColorCreateGenericGray(kCentralGray, 1.0));
    bgLayer_ = [CALayer layer];
    bgLayer_.backgroundColor = gray_;
    bgLayer_.frame = NSRectToCGRect(containingRect_);
    bgLayer_.masksToBounds = YES;
    [rootLayer_ addSublayer:bgLayer_];

    // Selection highlight layer.
    darkBlue_.reset(CGColorCreateGenericRGB(0.25, 0.34, 0.86, 1.0));
    selectionHighlight_ = [CALayer layer];
    selectionHighlight_.backgroundColor = darkBlue_;
    selectionHighlight_.cornerRadius = 5.0;
    selectionHighlight_.zPosition = -1;  // Behind other layers.
    selectionHighlight_.hidden = YES;
    [bgLayer_ addSublayer:selectionHighlight_];

    // Bottom gradient.
    CALayer* gradientLayer = [[[GrayGradientLayer alloc]
        initWithStartGray:kCentralGray endGray:kBottomGray] autorelease];
    gradientLayer.frame = CGRectMake(
        0,
        0,
        NSWidth(containingRect_),
        kBottomGradientHeight);
    [gradientLayer setNeedsDisplay];  // Draw once.
    [bgLayer_ addSublayer:gradientLayer];
  }
  // Top gradient (fades in).
  CGFloat toolbarHeight = NSHeight([self frame]) - NSHeight(containingRect_);
  topGradient_ = [[[GrayGradientLayer alloc]
      initWithStartGray:kTopGray endGray:kCentralGray] autorelease];
  topGradient_.frame = CGRectMake(
      0,
      NSHeight([self frame]) - toolbarHeight,
      NSWidth(containingRect_),
      toolbarHeight);
  [topGradient_ setNeedsDisplay];  // Draw once.
  [rootLayer_ addSublayer:topGradient_];
  NSTimeInterval interval =
      kDefaultAnimationDuration * (slomo ? kSlomoFactor : 1);
  AnimateCALayerOpacityFromTo(topGradient_, 0, 1, interval);

  // Layers for the tab thumbnails.
  tileSet_->Build(tabStripModel_);
  tileSet_->Layout(containingRect_);
  allThumbnailLayers_.reset(
      [[NSMutableArray alloc] initWithCapacity:tabStripModel_->count()]);
  allFaviconLayers_.reset(
      [[NSMutableArray alloc] initWithCapacity:tabStripModel_->count()]);
  allTitleLayers_.reset(
      [[NSMutableArray alloc] initWithCapacity:tabStripModel_->count()]);

  for (int i = 0; i < tabStripModel_->count(); ++i) {
    // Add a delegate to one of the animations to get a notification once the
    // animations are done.
    [self  addLayersForTile:tileSet_->tile_at(i)
                 showZoom:YES
                    slomo:slomo
        animationDelegate:i == tileSet_->selected_index() ? self : nil];
    if (i == tileSet_->selected_index()) {
      CALayer* layer = [allThumbnailLayers_ objectAtIndex:i];
      CAAnimation* animation = [layer animationForKey:@"bounds"];
      DCHECK(animation);
      [animation setValue:kAnimationIdFadeIn forKey:kAnimationIdKey];
    }
  }
  [self selectTileAtIndexWithoutAnimation:tileSet_->selected_index()];

  // Needs to happen after all layers have been added to |rootLayer_|, else
  // there's a one frame flash of grey at the beginning of the animation
  // (|bgLayer_| showing through with none of its children visible yet).
  [[self contentView] setLayer:rootLayer_];
  [[self contentView] setWantsLayer:YES];
}

- (BOOL)canBecomeKeyWindow {
 return YES;
}

// Lets the traffic light buttons on the browser window keep their "active"
// state while an info bubble is open. Only has an effect on 10.7.
- (BOOL)_sharesParentKeyState {
  return YES;
}

// Handle key events that should be executed repeatedly while the key is down.
- (void)keyDown:(NSEvent*)event {
  if (state_ == tabpose::kFadingOut)
    return;
  NSString* characters = [event characters];
  if ([characters length] < 1)
    return;

  unichar character = [characters characterAtIndex:0];
  int newIndex = -1;
  switch (character) {
    case NSUpArrowFunctionKey:
      newIndex = tileSet_->up_index();
      break;
    case NSDownArrowFunctionKey:
      newIndex = tileSet_->down_index();
      break;
    case NSLeftArrowFunctionKey:
      newIndex = tileSet_->left_index();
      break;
    case NSRightArrowFunctionKey:
      newIndex = tileSet_->right_index();
      break;
    case NSTabCharacter:
      newIndex = tileSet_->next_index();
      break;
    case NSBackTabCharacter:
      newIndex = tileSet_->previous_index();
      break;
  }
  if (newIndex != -1)
    [self selectTileAtIndexWithoutAnimation:newIndex];
}

// Handle keyboard events that should be executed once when the key is released.
- (void)keyUp:(NSEvent*)event {
  if (state_ == tabpose::kFadingOut)
    return;
  NSString* characters = [event characters];
  if ([characters length] < 1)
    return;

  unichar character = [characters characterAtIndex:0];
  switch (character) {
    case NSEnterCharacter:
    case NSNewlineCharacter:
    case NSCarriageReturnCharacter:
    case ' ':
      [self fadeAwayInSlomo:([event modifierFlags] & NSShiftKeyMask) != 0];
      break;
    case '\e':  // Escape
      tileSet_->set_selected_index(tabStripModel_->active_index());
      [self fadeAwayInSlomo:([event modifierFlags] & NSShiftKeyMask) != 0];
      break;
  }
}

// Handle keyboard events that contain cmd or ctrl.
- (BOOL)performKeyEquivalent:(NSEvent*)event {
  if (state_ == tabpose::kFadingOut)
    return NO;
  NSString* characters = [event characters];
  if ([characters length] < 1)
    return NO;
  unichar character = [characters characterAtIndex:0];
  if ([event modifierFlags] & NSCommandKeyMask) {
    if (character >= '1' && character <= '9') {
      int index =
          character == '9' ? tabStripModel_->count() - 1 : character - '1';
      if (index < tabStripModel_->count()) {
        tileSet_->set_selected_index(index);
        [self fadeAwayInSlomo:([event modifierFlags] & NSShiftKeyMask) != 0];
        return YES;
      }
    }
  }
  return NO;
}

- (void)flagsChanged:(NSEvent*)event {
  showAllCloseLayers_ = ([event modifierFlags] & NSAlternateKeyMask) != 0;
  [self updateClosebuttonLayersVisibility];
}

- (void)selectTileFromMouseEvent:(NSEvent*)event {
  int newIndex = -1;
  CGPoint p = NSPointToCGPoint([event locationInWindow]);
  for (NSUInteger i = 0; i < [allThumbnailLayers_ count]; ++i) {
    CALayer* layer = [allThumbnailLayers_ objectAtIndex:i];
    CGPoint lp = [layer convertPoint:p fromLayer:rootLayer_];
    if ([static_cast<CALayer*>([layer presentationLayer]) containsPoint:lp])
      newIndex = i;
  }
  if (newIndex >= 0)
    [self selectTileAtIndexWithoutAnimation:newIndex];
}

- (void)mouseMoved:(NSEvent*)event {
  [self selectTileFromMouseEvent:event];
}

- (CALayer*)closebuttonLayerAtIndex:(NSUInteger)index {
  CALayer* layer = [allThumbnailLayers_ objectAtIndex:index];
  return [[layer sublayers] objectAtIndex:0];
}

- (void)updateClosebuttonLayersVisibility {
  for (NSUInteger i = 0; i < [allThumbnailLayers_ count]; ++i) {
    CALayer* layer = [self closebuttonLayerAtIndex:i];
    BOOL isSelectedTile = static_cast<int>(i) == tileSet_->selected_index();
    BOOL isVisible = state_ == tabpose::kFadedIn &&
                     (isSelectedTile || showAllCloseLayers_);
    layer.hidden = !isVisible;
  }
}

- (void)mouseDown:(NSEvent*)event {
  // Just in case the user clicked without ever moving the mouse.
  [self selectTileFromMouseEvent:event];

  // If the click occurred in a close box, close that tab and don't do anything
  // else.
  CGPoint p = NSPointToCGPoint([event locationInWindow]);
  for (NSUInteger i = 0; i < [allThumbnailLayers_ count]; ++i) {
    CALayer* layer = [self closebuttonLayerAtIndex:i];
    CGPoint lp = [layer convertPoint:p fromLayer:rootLayer_];
    if ([static_cast<CALayer*>([layer presentationLayer]) containsPoint:lp] &&
        !layer.hidden) {
      tabStripModel_->CloseWebContentsAt(i,
          TabStripModel::CLOSE_USER_GESTURE |
          TabStripModel::CLOSE_CREATE_HISTORICAL_TAB);
      return;
    }
  }

  [self fadeAwayInSlomo:([event modifierFlags] & NSShiftKeyMask) != 0];
}

- (void)swipeWithEvent:(NSEvent*)event {
  if (abs([event deltaY]) > 0.5)  // Swipe up or down.
    [self fadeAwayInSlomo:([event modifierFlags] & NSShiftKeyMask) != 0];
}

- (void)close {
  // Prevent parent window from disappearing.
  [[self parentWindow] removeChildWindow:self];

  // We're dealloc'd in an autorelease pool – by then the observer registry
  // might be dead, so explicitly reset the observer now.
  tabStripModelObserverBridge_.reset();

  [super close];
}

- (void)commandDispatch:(id)sender {
  if ([sender tag] == IDC_TABPOSE)
    [self fadeAwayInSlomo:NO];
}

- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item {
  // Disable all browser-related menu items except the tab overview toggle.
  SEL action = [item action];
  NSInteger tag = [item tag];
  return action == @selector(commandDispatch:) && tag == IDC_TABPOSE;
}

- (void)fadeAwayTileAtIndex:(int)index {
  const tabpose::Tile& tile = tileSet_->tile_at(index);
  CALayer* layer = [allThumbnailLayers_ objectAtIndex:index];
  // Add a delegate to one of the implicit animations to get a notification
  // once the animations are done.
  if (static_cast<int>(index) == tileSet_->selected_index()) {
    CAAnimation* animation = [CAAnimation animation];
    animation.delegate = self;
    [animation setValue:kAnimationIdFadeOut forKey:kAnimationIdKey];
    [layer addAnimation:animation forKey:@"frame"];
  }

  // Thumbnail.
  layer.frame = NSRectToCGRect(
      tile.GetStartRectRelativeTo(tileSet_->selected_tile()));

  if (static_cast<int>(index) == tileSet_->selected_index()) {
    // Redraw layer at big resolution, so that zoom-in isn't blocky.
    [layer setNeedsDisplay];
  }

  // Title.
  CALayer* faviconLayer = [allFaviconLayers_ objectAtIndex:index];
  faviconLayer.frame = NSRectToCGRect(
      tile.GetFaviconStartRectRelativeTo(tileSet_->selected_tile()));
  faviconLayer.opacity = 0;

  // Favicon.
  // The |fontSize| cannot be animated directly, animate the layer's scale
  // instead. |transform.scale| affects the rendered width, so keep the small
  // bounds.
  CALayer* titleLayer = [allTitleLayers_ objectAtIndex:index];
  NSRect titleRect = tile.title_rect();
  NSRect titleToRect =
      tile.GetTitleStartRectRelativeTo(tileSet_->selected_tile());
  CGFloat scale = NSWidth(titleToRect) / NSWidth(titleRect);
  titleToRect.origin.x +=
      NSWidth(titleRect) * scale * titleLayer.anchorPoint.x;
  titleToRect.origin.y +=
      NSHeight(titleRect) * scale * titleLayer.anchorPoint.y;
  titleLayer.position = NSPointToCGPoint(titleToRect.origin);
  [titleLayer setValue:[NSNumber numberWithDouble:scale]
            forKeyPath:@"transform.scale"];
  titleLayer.opacity = 0;
}

- (void)fadeAwayInSlomo:(BOOL)slomo {
  if (state_ == tabpose::kFadingOut)
    return;

  state_ = tabpose::kFadingOut;
  [self setAcceptsMouseMovedEvents:NO];

  // Select chosen tab.
  if (tileSet_->selected_index() < tabStripModel_->count()) {
    tabStripModel_->ActivateTabAt(tileSet_->selected_index(),
                                  /*user_gesture=*/true);
  } else {
    DCHECK_EQ(tileSet_->selected_index(), 0);
  }

  {
    ScopedCAActionDisabler disableCAActions;

    // Move the selected layer on top of all other layers.
    [self selectedLayer].zPosition = 1;

    selectionHighlight_.hidden = YES;
    // Running animations with shadows is slow, so turn shadows off before
    // running the exit animation.
    for (CALayer* layer in allThumbnailLayers_.get())
      layer.shadowOpacity = 0.0;

    [self updateClosebuttonLayersVisibility];
  }

  // Animate layers out, all in one transaction.
  CGFloat duration =
      1.3 * kDefaultAnimationDuration * (slomo ? kSlomoFactor : 1);
  ScopedCAActionSetDuration durationSetter(duration);
  for (int i = 0; i < tabStripModel_->count(); ++i)
    [self fadeAwayTileAtIndex:i];
  AnimateCALayerOpacityFromTo(topGradient_, 1, 0, duration);
}

- (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished {
  NSString* animationId = [animation valueForKey:kAnimationIdKey];
  if ([animationId isEqualToString:kAnimationIdFadeIn]) {
    if (finished && state_ == tabpose::kFadingIn) {
      // If the user clicks while the fade in animation is still running,
      // |state_| is already kFadingOut. In that case, don't do anything.
      state_ = tabpose::kFadedIn;

      selectionHighlight_.hidden = NO;

      // Running animations with shadows is slow, so turn shadows on only after
      // the animation is done.
      ScopedCAActionDisabler disableCAActions;
      for (CALayer* layer in allThumbnailLayers_.get())
        layer.shadowOpacity = 0.5;

      [self updateClosebuttonLayersVisibility];
    }
  } else if ([animationId isEqualToString:kAnimationIdFadeOut]) {
    DCHECK_EQ(tabpose::kFadingOut, state_);
    [self close];
  }
}

- (NSUInteger)thumbnailLayerCount {
  return [allThumbnailLayers_ count];
}

- (int)selectedIndex {
  return tileSet_->selected_index();
}

#pragma mark TabStripModelBridge

- (void)refreshLayerFramesAtIndex:(int)i {
  const tabpose::Tile& tile = tileSet_->tile_at(i);

  CALayer* thumbLayer = [allThumbnailLayers_ objectAtIndex:i];

  if (i == tileSet_->selected_index()) {
    AnimateCALayerFrameFromTo(
        selectionHighlight_,
        NSInsetRect(NSRectFromCGRect(thumbLayer.frame),
                    -kSelectionInset, -kSelectionInset),
        NSInsetRect(tile.thumb_rect(),
                    -kSelectionInset, -kSelectionInset),
        kObserverChangeAnimationDuration,
        nil);
  }

  // Repaint layer if necessary.
  if (!NSEqualSizes(NSRectFromCGRect(thumbLayer.frame).size,
                    tile.thumb_rect().size)) {
    [thumbLayer setNeedsDisplay];
  }

  // Use AnimateCALayerFrameFromTo() instead of just setting |frame| to let
  // the animation match the selection animation --
  // |kCAMediaTimingFunctionDefault| is 10.6-only.
  AnimateCALayerFrameFromTo(
      thumbLayer,
      NSRectFromCGRect(thumbLayer.frame),
      tile.thumb_rect(),
      kObserverChangeAnimationDuration,
      nil);

  CALayer* faviconLayer = [allFaviconLayers_ objectAtIndex:i];
  AnimateCALayerFrameFromTo(
      faviconLayer,
      NSRectFromCGRect(faviconLayer.frame),
      tile.favicon_rect(),
      kObserverChangeAnimationDuration,
      nil);

  CALayer* titleLayer = [allTitleLayers_ objectAtIndex:i];
  AnimateCALayerFrameFromTo(
      titleLayer,
      NSRectFromCGRect(titleLayer.frame),
      tile.title_rect(),
      kObserverChangeAnimationDuration,
      nil);
}

- (void)insertTabWithContents:(content::WebContents*)contents
                      atIndex:(NSInteger)index
                 inForeground:(bool)inForeground {
  // This happens if you cmd-click a link and then immediately open tabpose
  // on a slowish machine.
  ScopedCAActionSetDuration durationSetter(kObserverChangeAnimationDuration);

  // Insert new layer and relayout.
  tileSet_->InsertTileAt(index, contents);
  tileSet_->Layout(containingRect_);
  [self  addLayersForTile:tileSet_->tile_at(index)
                 showZoom:NO
                    slomo:NO
        animationDelegate:nil];

  // Update old layers.
  DCHECK_EQ(tabStripModel_->count(),
            static_cast<int>([allThumbnailLayers_ count]));
  DCHECK_EQ(tabStripModel_->count(),
            static_cast<int>([allTitleLayers_ count]));
  DCHECK_EQ(tabStripModel_->count(),
            static_cast<int>([allFaviconLayers_ count]));

  // Update selection.
  int selectedIndex = tileSet_->selected_index();
  if (selectedIndex >= index)
    selectedIndex++;
  [self selectTileAtIndexWithoutAnimation:selectedIndex];

  // Animate everything into its new place.
  for (int i = 0; i < tabStripModel_->count(); ++i) {
    if (i == index)  // The new layer.
      continue;
    [self refreshLayerFramesAtIndex:i];
  }
}

- (void)tabClosingWithContents:(content::WebContents*)contents
                       atIndex:(NSInteger)index {
  // We will also get a -tabDetachedWithContents:atIndex: notification for
  // closing tabs, so do nothing here.
}

- (void)tabDetachedWithContents:(content::WebContents*)contents
                        atIndex:(NSInteger)index {
  ScopedCAActionSetDuration durationSetter(kObserverChangeAnimationDuration);

  // Remove layer and relayout.
  tileSet_->RemoveTileAt(index);
  tileSet_->Layout(containingRect_);

  {
    ScopedCAActionDisabler disabler;
    [[allThumbnailLayers_ objectAtIndex:index] removeFromSuperlayer];
    [allThumbnailLayers_ removeObjectAtIndex:index];
    [[allTitleLayers_ objectAtIndex:index] removeFromSuperlayer];
    [allTitleLayers_ removeObjectAtIndex:index];
    [[allFaviconLayers_ objectAtIndex:index] removeFromSuperlayer];
    [allFaviconLayers_ removeObjectAtIndex:index];
  }

  // Update old layers.
  DCHECK_EQ(tabStripModel_->count(),
            static_cast<int>([allThumbnailLayers_ count]));
  DCHECK_EQ(tabStripModel_->count(),
            static_cast<int>([allTitleLayers_ count]));
  DCHECK_EQ(tabStripModel_->count(),
            static_cast<int>([allFaviconLayers_ count]));

  if (tabStripModel_->count() == 0)
    [self close];

  // Update selection.
  int selectedIndex = tileSet_->selected_index();
  if (selectedIndex > index || selectedIndex >= tabStripModel_->count())
    selectedIndex--;
  if (selectedIndex >= 0)
    [self selectTileAtIndexWithoutAnimation:selectedIndex];

  // Animate everything into its new place.
  for (int i = 0; i < tabStripModel_->count(); ++i)
    [self refreshLayerFramesAtIndex:i];
}

- (void)tabMovedWithContents:(content::WebContents*)contents
                    fromIndex:(NSInteger)from
                      toIndex:(NSInteger)to {
  ScopedCAActionSetDuration durationSetter(kObserverChangeAnimationDuration);

  // Move tile from |from| to |to|.
  tileSet_->MoveTileFromTo(from, to);

  // Move corresponding layers from |from| to |to|.
  base::scoped_nsobject<CALayer> thumbLayer(
      [[allThumbnailLayers_ objectAtIndex:from] retain]);
  [allThumbnailLayers_ removeObjectAtIndex:from];
  [allThumbnailLayers_ insertObject:thumbLayer.get() atIndex:to];
  base::scoped_nsobject<CALayer> faviconLayer(
      [[allFaviconLayers_ objectAtIndex:from] retain]);
  [allFaviconLayers_ removeObjectAtIndex:from];
  [allFaviconLayers_ insertObject:faviconLayer.get() atIndex:to];
  base::scoped_nsobject<CALayer> titleLayer(
      [[allTitleLayers_ objectAtIndex:from] retain]);
  [allTitleLayers_ removeObjectAtIndex:from];
  [allTitleLayers_ insertObject:titleLayer.get() atIndex:to];

  // Update selection.
  int selectedIndex = tileSet_->selected_index();
  if (from == selectedIndex)
    selectedIndex = to;
  else if (from < selectedIndex && selectedIndex <= to)
    selectedIndex--;
  else if (to <= selectedIndex && selectedIndex < from)
    selectedIndex++;
  [self selectTileAtIndexWithoutAnimation:selectedIndex];

  // Update frames of the layers.
  for (int i = std::min(from, to); i <= std::max(from, to); ++i)
    [self refreshLayerFramesAtIndex:i];
}

- (void)tabChangedWithContents:(content::WebContents*)contents
                       atIndex:(NSInteger)index
                    changeType:(TabStripModelObserver::TabChangeType)change {
  // Tell the window to update text, title, and thumb layers at |index| to get
  // their data from |contents|. |contents| can be different from the old
  // contents at that index!
  // While a tab is loading, this is unfortunately called quite often for
  // both the "loading" and the "all" change types, so we don't really want to
  // send thumb requests to the corresponding renderer when this is called.
  // For now, just make sure that we don't hold on to an invalid WebContents
  // object.
  tabpose::Tile& tile = tileSet_->tile_at(index);
  if (contents == tile.web_contents()) {
    // TODO(thakis): Install a timer to send a thumb request/update title/update
    // favicon after 20ms or so, and reset the timer every time this is called
    // to make sure we get an updated thumb, without requesting them all over.
    return;
  }

  tile.set_tab_contents(contents);
  ThumbnailLayer* thumbLayer = [allThumbnailLayers_ objectAtIndex:index];
  [thumbLayer setWebContents:contents];
}

- (void)tabStripModelDeleted {
  [self close];
}

@end
