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

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

#include "base/memory/scoped_nsobject.h"
#include "grit/generated_resources.h"
#import "third_party/molokocacao/NSBezierPath+MCAdditions.h"
#include "ui/base/l10n/l10n_util.h"

namespace  {
const CGFloat kCircleRadius = 0.415 * 16;
const CGFloat kCircleHoverWhite = 0.565;
const CGFloat kCircleClickWhite = 0.396;
const CGFloat kXShadowAlpha = 0.75;
const CGFloat kXShadowCircleAlpha = 0.1;
}  // namespace

@interface HoverCloseButton(Private)
- (void)updatePaths;
- (void)setUpDrawingPaths;
@end

@implementation HoverCloseButton

- (id)initWithFrame:(NSRect)frameRect {
  if ((self = [super initWithFrame:frameRect])) {
    [self commonInit];
  }
  return self;
}

- (void)awakeFromNib {
  [super awakeFromNib];
  [self commonInit];
}

- (void)drawRect:(NSRect)rect {
  if (!circlePath_.get() || !xPath_.get())
    [self setUpDrawingPaths];

  // Only call updatePaths if the size changed.
  if (!NSEqualSizes(oldSize_, [self bounds].size))
    [self updatePaths];

  // If the user is hovering over the button, a light/dark gray circle is drawn
  // behind the 'x'.
  if (hoverState_ != kHoverStateNone) {
    // Adjust the darkness of the circle depending on whether it is being
    // clicked.
    CGFloat white = (hoverState_ == kHoverStateMouseOver) ?
        kCircleHoverWhite : kCircleClickWhite;
    [[NSColor colorWithCalibratedWhite:white alpha:1.0] set];
    [circlePath_ fill];
  }

  [[NSColor whiteColor] set];
  [xPath_ fill];

  // Give the 'x' an inner shadow for depth. If the button is in a hover state
  // (circle behind it), then adjust the shadow accordingly (not as harsh).
  NSShadow* shadow = [[[NSShadow alloc] init] autorelease];
  CGFloat alpha = (hoverState_ != kHoverStateNone) ?
      kXShadowCircleAlpha : kXShadowAlpha;
  [shadow setShadowColor:[NSColor colorWithCalibratedWhite:0.15
                                                     alpha:alpha]];
  [shadow setShadowOffset:NSMakeSize(0.0, 0.0)];
  [shadow setShadowBlurRadius:2.5];
  [xPath_ fillWithInnerShadow:shadow];
}

- (void)commonInit {
  // Set accessibility description.
  NSString* description = l10n_util::GetNSStringWithFixup(IDS_ACCNAME_CLOSE);
  [[self cell]
      accessibilitySetOverrideValue:description
                       forAttribute:NSAccessibilityDescriptionAttribute];

  // Add a tooltip.
  [self setToolTip:l10n_util::GetNSStringWithFixup(IDS_TOOLTIP_CLOSE_TAB)];
}

- (void)setUpDrawingPaths {
  // Keep the paths centered around the origin in this function. It is then
  // translated in -updatePaths.
  NSPoint xCenter = NSZeroPoint;

  circlePath_.reset([[NSBezierPath bezierPath] retain]);
  [circlePath_ moveToPoint:xCenter];
  CGFloat radius = kCircleRadius;
  [circlePath_ appendBezierPathWithArcWithCenter:xCenter
                                          radius:radius
                                      startAngle:0.0
                                        endAngle:365.0];

  // Construct an 'x' by drawing two intersecting rectangles in the shape of a
  // cross and then rotating the path by 45 degrees.
  xPath_.reset([[NSBezierPath bezierPath] retain]);
  [xPath_ appendBezierPathWithRect:NSMakeRect(3.5, 7.0, 9.0, 2.0)];
  [xPath_ appendBezierPathWithRect:NSMakeRect(7.0, 3.5, 2.0, 9.0)];

  NSRect pathBounds = [xPath_ bounds];
  NSPoint pathCenter = NSMakePoint(NSMidX(pathBounds), NSMidY(pathBounds));

  NSAffineTransform* transform = [NSAffineTransform transform];
  [transform translateXBy:xCenter.x yBy:xCenter.y];
  [transform rotateByDegrees:45.0];
  [transform translateXBy:-pathCenter.x yBy:-pathCenter.y];

  [xPath_ transformUsingAffineTransform:transform];
}

- (void)updatePaths {
  oldSize_ = [self bounds].size;

  // Revert the current transform for the two points.
  if (transform_.get()) {
    [transform_.get() invert];
    [circlePath_.get() transformUsingAffineTransform:transform_.get()];
    [xPath_.get() transformUsingAffineTransform:transform_.get()];
  }

  // Create the new transform. [self bounds] is prefered in case aRect wasn't
  // literally taken as bounds (e.g. cropped).
  NSPoint xCenter = NSMakePoint(8, oldSize_.height / 2.0f);

  // Retain here, as scoped_* don't retain.
  transform_.reset([[NSAffineTransform transform] retain]);
  [transform_.get() translateXBy:xCenter.x yBy:xCenter.y];
  [circlePath_.get() transformUsingAffineTransform:transform_.get()];
  [xPath_.get() transformUsingAffineTransform:transform_.get()];
}

@end