// 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/dock_icon.h"

#include "base/memory/scoped_nsobject.h"

// The fraction of the size of the dock icon that the badge is.
static const float kBadgeFraction = 0.4f;

// The indentation of the badge.
static const float kBadgeIndent = 5.0f;

// A view that draws our dock tile.
@interface DockTileView : NSView {
 @private
  int downloads_;
  BOOL indeterminate_;
  float progress_;
}

// Indicates how many downloads are in progress.
@property (nonatomic) int downloads;

// Indicates whether the progress indicator should be in an indeterminate state
// or not.
@property (nonatomic) BOOL indeterminate;

// Indicates the amount of progress made of the download. Ranges from [0..1].
@property (nonatomic) float progress;

@end

@implementation DockTileView

@synthesize downloads = downloads_;
@synthesize indeterminate = indeterminate_;
@synthesize progress = progress_;

- (void)drawRect:(NSRect)dirtyRect {
  // Not -[NSApplication applicationIconImage]; that fails to return a pasted
  // custom icon.
  NSString* appPath = [[NSBundle mainBundle] bundlePath];
  NSImage* appIcon = [[NSWorkspace sharedWorkspace] iconForFile:appPath];
  [appIcon drawInRect:[self bounds]
             fromRect:NSZeroRect
            operation:NSCompositeSourceOver
             fraction:1.0];

  if (downloads_ == 0)
    return;

  NSRect badgeRect = [self bounds];
  badgeRect.size.height = (int)(kBadgeFraction * badgeRect.size.height);
  int newWidth = kBadgeFraction * badgeRect.size.width;
  badgeRect.origin.x = badgeRect.size.width - newWidth;
  badgeRect.size.width = newWidth;

  CGFloat badgeRadius = NSMidY(badgeRect);

  badgeRect.origin.x -= kBadgeIndent;
  badgeRect.origin.y += kBadgeIndent;

  NSPoint badgeCenter = NSMakePoint(NSMidX(badgeRect),
                                    NSMidY(badgeRect));

  // Background
  NSColor* backgroundColor = [NSColor colorWithCalibratedRed:0.85
                                                       green:0.85
                                                        blue:0.85
                                                       alpha:1.0];
  NSColor* backgroundHighlight =
      [backgroundColor blendedColorWithFraction:0.85
                                        ofColor:[NSColor whiteColor]];
  scoped_nsobject<NSGradient> backgroundGradient(
      [[NSGradient alloc] initWithStartingColor:backgroundHighlight
                                    endingColor:backgroundColor]);
  NSBezierPath* badgeEdge = [NSBezierPath bezierPathWithOvalInRect:badgeRect];
  [NSGraphicsContext saveGraphicsState];
  [badgeEdge addClip];
  [backgroundGradient drawFromCenter:badgeCenter
                              radius:0.0
                            toCenter:badgeCenter
                              radius:badgeRadius
                             options:0];
  [NSGraphicsContext restoreGraphicsState];

  // Slice
  if (!indeterminate_) {
    NSColor* sliceColor = [NSColor colorWithCalibratedRed:0.45
                                                    green:0.8
                                                     blue:0.25
                                                    alpha:1.0];
    NSColor* sliceHighlight =
        [sliceColor blendedColorWithFraction:0.4
                                     ofColor:[NSColor whiteColor]];
    scoped_nsobject<NSGradient> sliceGradient(
        [[NSGradient alloc] initWithStartingColor:sliceHighlight
                                      endingColor:sliceColor]);
    NSBezierPath* progressSlice;
    if (progress_ >= 1.0) {
      progressSlice = [NSBezierPath bezierPathWithOvalInRect:badgeRect];
    } else {
      CGFloat endAngle = 90.0 - 360.0 * progress_;
      if (endAngle < 0.0)
        endAngle += 360.0;
      progressSlice = [NSBezierPath bezierPath];
      [progressSlice moveToPoint:badgeCenter];
      [progressSlice appendBezierPathWithArcWithCenter:badgeCenter
                                                radius:badgeRadius
                                            startAngle:90.0
                                              endAngle:endAngle
                                             clockwise:YES];
      [progressSlice closePath];
    }
    [NSGraphicsContext saveGraphicsState];
    [progressSlice addClip];
    [sliceGradient drawFromCenter:badgeCenter
                           radius:0.0
                         toCenter:badgeCenter
                           radius:badgeRadius
                          options:0];
    [NSGraphicsContext restoreGraphicsState];
  }

  // Edge
  [NSGraphicsContext saveGraphicsState];
  [[NSColor whiteColor] set];
  scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]);
  [shadow.get() setShadowOffset:NSMakeSize(0, -2)];
  [shadow setShadowBlurRadius:2];
  [shadow set];
  [badgeEdge setLineWidth:2];
  [badgeEdge stroke];
  [NSGraphicsContext restoreGraphicsState];

  // Download count
  scoped_nsobject<NSNumberFormatter> formatter(
      [[NSNumberFormatter alloc] init]);
  NSString* countString =
      [formatter stringFromNumber:[NSNumber numberWithInt:downloads_]];

  scoped_nsobject<NSShadow> countShadow([[NSShadow alloc] init]);
  [countShadow setShadowBlurRadius:3.0];
  [countShadow.get() setShadowColor:[NSColor whiteColor]];
  [countShadow.get() setShadowOffset:NSMakeSize(0.0, 0.0)];
  NSMutableDictionary* countAttrsDict =
      [NSMutableDictionary dictionaryWithObjectsAndKeys:
          [NSColor blackColor], NSForegroundColorAttributeName,
          countShadow.get(), NSShadowAttributeName,
          nil];
  CGFloat countFontSize = badgeRadius;
  NSSize countSize = NSZeroSize;
  scoped_nsobject<NSAttributedString> countAttrString;
  while (1) {
    NSFont* countFont = [NSFont fontWithName:@"Helvetica-Bold"
                                        size:countFontSize];
    [countAttrsDict setObject:countFont forKey:NSFontAttributeName];
    countAttrString.reset(
        [[NSAttributedString alloc] initWithString:countString
                                        attributes:countAttrsDict]);
    countSize = [countAttrString size];
    if (countSize.width > badgeRadius * 1.5) {
      countFontSize -= 1.0;
    } else {
      break;
    }
  }

  NSPoint countOrigin = badgeCenter;
  countOrigin.x -= countSize.width / 2;
  countOrigin.y -= countSize.height / 2.2;  // tweak; otherwise too low

  [countAttrString.get() drawAtPoint:countOrigin];
}

@end


@implementation DockIcon

+ (DockIcon*)sharedDockIcon {
  static DockIcon* icon;
  if (!icon) {
    NSDockTile* dockTile = [[NSApplication sharedApplication] dockTile];

    scoped_nsobject<DockTileView> dockTileView([[DockTileView alloc] init]);
    [dockTile setContentView:dockTileView];

    icon = [[DockIcon alloc] init];
  }

  return icon;
}

- (void)updateIcon {
  NSDockTile* dockTile = [[NSApplication sharedApplication] dockTile];

  [dockTile display];
}

- (void)setDownloads:(int)downloads {
  NSDockTile* dockTile = [[NSApplication sharedApplication] dockTile];
  DockTileView* dockTileView = (DockTileView*)([dockTile contentView]);

  [dockTileView setDownloads:downloads];
}

- (void)setIndeterminate:(BOOL)indeterminate {
  NSDockTile* dockTile = [[NSApplication sharedApplication] dockTile];
  DockTileView* dockTileView = (DockTileView*)([dockTile contentView]);

  [dockTileView setIndeterminate:indeterminate];
}

- (void)setProgress:(float)progress {
  NSDockTile* dockTile = [[NSApplication sharedApplication] dockTile];
  DockTileView* dockTileView = (DockTileView*)([dockTile contentView]);

  [dockTileView setProgress:progress];
}

@end