// 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 "ui/native_theme/native_theme_mac.h"

#import <Cocoa/Cocoa.h>

#include "base/basictypes.h"
#include "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/mac/sdk_forward_declarations.h"
#include "ui/native_theme/common_theme.h"
#import "skia/ext/skia_utils_mac.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/skia_util.h"

namespace {

const SkColor kScrollerTrackGradientColors[] = {
    SkColorSetRGB(0xEF, 0xEF, 0xEF),
    SkColorSetRGB(0xF9, 0xF9, 0xF9),
    SkColorSetRGB(0xFD, 0xFD, 0xFD),
    SkColorSetRGB(0xF6, 0xF6, 0xF6) };
const SkColor kScrollerTrackInnerBorderColor = SkColorSetRGB(0xE4, 0xE4, 0xE4);
const SkColor kScrollerTrackOuterBorderColor = SkColorSetRGB(0xEF, 0xEF, 0xEF);
const SkColor kScrollerThumbColor = SkColorSetARGB(0x38, 0, 0, 0);
const SkColor kScrollerThumbHoverColor = SkColorSetARGB(0x80, 0, 0, 0);
const int kScrollerTrackBorderWidth = 1;

// The amount the thumb is inset from both the ends and the sides of the track.
const int kScrollerThumbInset = 3;

// Values calculated by reading pixels and solving simultaneous equations
// derived from "A over B" alpha compositing. Steps: Sample the semi-transparent
// pixel over two backgrounds; P1, P2 over backgrounds B1, B2. Use the color
// value between 0.0 and 1.0 (i.e. divide by 255.0). Then,
// alpha = (P2 - P1 + B1 - B2) / (B1 - B2)
// color = (P1 - B1 + alpha * B1) / alpha.
const SkColor kMenuPopupBackgroundColor = SkColorSetARGB(251, 255, 255, 255);
const SkColor kMenuSeparatorColor = SkColorSetARGB(243, 228, 228, 228);
const SkColor kMenuBorderColor = SkColorSetARGB(60, 0, 0, 0);

// Hardcoded color used for some existing dialogs in Chrome's Cocoa UI.
const SkColor kDialogBackgroundColor = SkColorSetRGB(251, 251, 251);

// On 10.6 and 10.7 there is no way to get components from system colors. Here,
// system colors are just opaque objects that can paint themselves and otherwise
// tell you nothing. In 10.8, some of the system color classes have incomplete
// implementations and throw exceptions even attempting to convert using
// -[NSColor colorUsingColorSpace:], so don't bother there either.
// This function paints a single pixel to a 1x1 swatch and reads it back.
SkColor GetSystemColorUsingSwatch(NSColor* color) {
  SkColor swatch;
  base::ScopedCFTypeRef<CGColorSpaceRef> color_space(
      CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB));
  const size_t bytes_per_row = 4;
  COMPILE_ASSERT(sizeof(swatch) == bytes_per_row, skcolor_not_4_bytes);
  CGBitmapInfo bitmap_info =
      kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
  base::ScopedCFTypeRef<CGContextRef> context(CGBitmapContextCreate(
      &swatch, 1, 1, 8, bytes_per_row, color_space, bitmap_info));

  NSGraphicsContext* drawing_context =
      [NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:NO];
  [NSGraphicsContext saveGraphicsState];
  [NSGraphicsContext setCurrentContext:drawing_context];
  [color drawSwatchInRect:NSMakeRect(0, 0, 1, 1)];
  [NSGraphicsContext restoreGraphicsState];
  return swatch;
}

// NSColor has a number of methods that return system colors (i.e. controlled by
// user preferences). This function converts the color given by an NSColor class
// method to an SkColor. Official documentation suggests developers only rely on
// +[NSColor selectedTextBackgroundColor] and +[NSColor selectedControlColor],
// but other colors give a good baseline. For many, a gradient is involved; the
// palette chosen based on the enum value given by +[NSColor currentColorTint].
// Apple's documentation also suggests to use NSColorList, but the system color
// list is just populated with class methods on NSColor.
SkColor NSSystemColorToSkColor(NSColor* color) {
  if (base::mac::IsOSMountainLionOrEarlier())
    return GetSystemColorUsingSwatch(color);

  // System colors use the an NSNamedColorSpace called "System", so first step
  // is to convert the color into something that can be worked with.
  NSColor* device_color =
      [color colorUsingColorSpace:[NSColorSpace deviceRGBColorSpace]];
  if (device_color)
    return gfx::NSDeviceColorToSkColor(device_color);

  // Sometimes the conversion is not possible, but we can get an approximation
  // by going through a CGColorRef. Note that simply using NSColor methods for
  // accessing components for system colors results in exceptions like
  // "-numberOfComponents not valid for the NSColor NSNamedColorSpace System
  // windowBackgroundColor; need to first convert colorspace." Hence the
  // conversion first to CGColor.
  CGColorRef cg_color = [color CGColor];
  if (CGColorGetNumberOfComponents(cg_color) == 4)
    return gfx::CGColorRefToSkColor(cg_color);

  CHECK_EQ(2u, CGColorGetNumberOfComponents(cg_color));
  // Two components means a grayscale channel and an alpha channel, which
  // CGColorRefToSkColor will not like. But RGB is additive, so the conversion
  // is easy (RGB to grayscale is less easy).
  const CGFloat* components = CGColorGetComponents(cg_color);
  return SkColorSetARGB(SkScalarRoundToInt(255.0 * components[1]),
                        SkScalarRoundToInt(255.0 * components[0]),
                        SkScalarRoundToInt(255.0 * components[0]),
                        SkScalarRoundToInt(255.0 * components[0]));
}

}  // namespace

namespace ui {

// static
NativeTheme* NativeTheme::instance() {
  return NativeThemeMac::instance();
}

// static
NativeThemeMac* NativeThemeMac::instance() {
  CR_DEFINE_STATIC_LOCAL(NativeThemeMac, s_native_theme, ());
  return &s_native_theme;
}

SkColor NativeThemeMac::GetSystemColor(ColorId color_id) const {
  // TODO(tapted): Add caching for these, and listen for
  // NSSystemColorsDidChangeNotification.
  switch (color_id) {
    case kColorId_WindowBackground:
      return NSSystemColorToSkColor([NSColor windowBackgroundColor]);
    case kColorId_DialogBackground:
      return kDialogBackgroundColor;

    case kColorId_FocusedBorderColor:
    case kColorId_FocusedMenuButtonBorderColor:
      return NSSystemColorToSkColor([NSColor keyboardFocusIndicatorColor]);
    case kColorId_UnfocusedBorderColor:
      return NSSystemColorToSkColor([NSColor controlColor]);

    // Buttons and labels.
    case kColorId_ButtonBackgroundColor:
    case kColorId_ButtonHoverBackgroundColor:
    case kColorId_HoverMenuButtonBorderColor:
    case kColorId_LabelBackgroundColor:
      return NSSystemColorToSkColor([NSColor controlBackgroundColor]);
    case kColorId_ButtonEnabledColor:
    case kColorId_EnabledMenuButtonBorderColor:
    case kColorId_LabelEnabledColor:
      return NSSystemColorToSkColor([NSColor controlTextColor]);
    case kColorId_ButtonDisabledColor:
    case kColorId_LabelDisabledColor:
      return NSSystemColorToSkColor([NSColor disabledControlTextColor]);
    case kColorId_ButtonHighlightColor:
    case kColorId_ButtonHoverColor:
      return NSSystemColorToSkColor([NSColor selectedControlTextColor]);

    // Menus.
    case kColorId_EnabledMenuItemForegroundColor:
      return NSSystemColorToSkColor([NSColor controlTextColor]);
    case kColorId_DisabledMenuItemForegroundColor:
    case kColorId_DisabledEmphasizedMenuItemForegroundColor:
      return NSSystemColorToSkColor([NSColor disabledControlTextColor]);
    case kColorId_SelectedMenuItemForegroundColor:
      return NSSystemColorToSkColor([NSColor selectedMenuItemTextColor]);
    case kColorId_FocusedMenuItemBackgroundColor:
    case kColorId_HoverMenuItemBackgroundColor:
      return NSSystemColorToSkColor([NSColor selectedMenuItemColor]);
    case kColorId_MenuBackgroundColor:
      return kMenuPopupBackgroundColor;
    case kColorId_MenuSeparatorColor:
      return kMenuSeparatorColor;
    case kColorId_MenuBorderColor:
      return kMenuBorderColor;

    // Text fields.
    case kColorId_TextfieldDefaultColor:
    case kColorId_TextfieldReadOnlyColor:
      return NSSystemColorToSkColor([NSColor textColor]);
    case kColorId_TextfieldDefaultBackground:
    case kColorId_TextfieldReadOnlyBackground:
      return NSSystemColorToSkColor([NSColor textBackgroundColor]);
    case kColorId_TextfieldSelectionColor:
      return NSSystemColorToSkColor([NSColor selectedTextColor]);
    case kColorId_TextfieldSelectionBackgroundFocused:
      return NSSystemColorToSkColor([NSColor selectedTextBackgroundColor]);

    default:
      break;  // TODO(tapted): Handle all values and remove the default case.
  }

  SkColor color;
  if (CommonThemeGetSystemColor(color_id, &color))
    return color;

  NOTIMPLEMENTED() << " Invalid color_id: " << color_id;
  return FallbackTheme::GetSystemColor(color_id);
}

void NativeThemeMac::PaintScrollbarTrack(
    SkCanvas* canvas,
    Part part,
    State state,
    const ScrollbarTrackExtraParams& extra_params,
    const gfx::Rect& rect) const {
  // Emulate the non-overlay scroller style from OSX 10.7 and later.
  SkPoint gradient_bounds[2];
  if (part == kScrollbarVerticalTrack) {
    gradient_bounds[0].set(rect.x(), rect.y());
    gradient_bounds[1].set(rect.right(), rect.y());
  } else {
    DCHECK_EQ(part, kScrollbarHorizontalTrack);
    gradient_bounds[0].set(rect.x(), rect.y());
    gradient_bounds[1].set(rect.x(), rect.bottom());
  }
  skia::RefPtr<SkShader> shader = skia::AdoptRef(
      SkGradientShader::CreateLinear(gradient_bounds,
                                     kScrollerTrackGradientColors,
                                     NULL,
                                     arraysize(kScrollerTrackGradientColors),
                                     SkShader::kClamp_TileMode));
  SkPaint gradient;
  gradient.setShader(shader.get());

  SkIRect track_rect = gfx::RectToSkIRect(rect);
  canvas->drawIRect(track_rect, gradient);

  // Draw inner and outer line borders.
  if (part == kScrollbarVerticalTrack) {
    SkPaint paint;
    paint.setColor(kScrollerTrackInnerBorderColor);
    canvas->drawRectCoords(track_rect.left(),
                           track_rect.top(),
                           track_rect.left() + kScrollerTrackBorderWidth,
                           track_rect.bottom(),
                           paint);
    paint.setColor(kScrollerTrackOuterBorderColor);
    canvas->drawRectCoords(track_rect.right() - kScrollerTrackBorderWidth,
                           track_rect.top(),
                           track_rect.right(),
                           track_rect.bottom(),
                           paint);
  } else {
    SkPaint paint;
    paint.setColor(kScrollerTrackInnerBorderColor);
    canvas->drawRectCoords(track_rect.left(),
                           track_rect.top(),
                           track_rect.right(),
                           track_rect.top() + kScrollerTrackBorderWidth,
                           paint);
    paint.setColor(kScrollerTrackOuterBorderColor);
    canvas->drawRectCoords(track_rect.left(),
                           track_rect.bottom() - kScrollerTrackBorderWidth,
                           track_rect.right(),
                           track_rect.bottom(),
                           paint);
  }
}

void NativeThemeMac::PaintScrollbarThumb(SkCanvas* canvas,
                                         Part part,
                                         State state,
                                         const gfx::Rect& rect) const {
  gfx::Rect thumb_rect(rect);
  switch (part) {
    case kScrollbarHorizontalThumb:
      thumb_rect.Inset(0, kScrollerTrackBorderWidth, 0, 0);
      break;
    case kScrollbarVerticalThumb:
      thumb_rect.Inset(kScrollerTrackBorderWidth, 0, 0, 0);
      break;
    default:
      NOTREACHED();
      break;
  }

  thumb_rect.Inset(kScrollerThumbInset, kScrollerThumbInset);

  SkPaint paint;
  paint.setAntiAlias(true);
  paint.setColor(state == kHovered ? thumb_active_color_
                                   : thumb_inactive_color_);
  const SkScalar radius = std::min(rect.width(), rect.height());
  canvas->drawRoundRect(gfx::RectToSkRect(thumb_rect), radius, radius, paint);
}

void NativeThemeMac::PaintScrollbarCorner(SkCanvas* canvas,
                                          State state,
                                          const gfx::Rect& rect) const {
  DCHECK_GT(rect.width(), 0);
  DCHECK_GT(rect.height(), 0);

  // Draw radial gradient from top-left corner.
  skia::RefPtr<SkShader> shader = skia::AdoptRef(
      SkGradientShader::CreateRadial(SkPoint::Make(rect.x(), rect.y()),
                                     rect.width(),
                                     kScrollerTrackGradientColors,
                                     NULL,
                                     arraysize(kScrollerTrackGradientColors),
                                     SkShader::kClamp_TileMode));
  SkPaint gradient;
  gradient.setStyle(SkPaint::kFill_Style);
  gradient.setAntiAlias(true);
  gradient.setShader(shader.get());
  canvas->drawRect(gfx::RectToSkRect(rect), gradient);

  // Draw inner border corner point.
  canvas->drawPoint(rect.x(), rect.y(), kScrollerTrackInnerBorderColor);

  // Draw outer borders.
  SkPaint paint;
  paint.setColor(kScrollerTrackOuterBorderColor);
  canvas->drawRectCoords(rect.right() - kScrollerTrackBorderWidth,
                         rect.y(),
                         rect.right(),
                         rect.bottom(),
                         paint);
  canvas->drawRectCoords(rect.x(),
                         rect.bottom() - kScrollerTrackBorderWidth,
                         rect.right(),
                         rect.bottom(),
                         paint);
}

void NativeThemeMac::PaintMenuPopupBackground(
    SkCanvas* canvas,
    const gfx::Size& size,
    const MenuBackgroundExtraParams& menu_background) const {
  canvas->drawColor(kMenuPopupBackgroundColor, SkXfermode::kSrc_Mode);
}

void NativeThemeMac::PaintMenuItemBackground(
    SkCanvas* canvas,
    State state,
    const gfx::Rect& rect,
    const MenuListExtraParams& menu_list) const {
  SkPaint paint;
  switch (state) {
    case NativeTheme::kNormal:
    case NativeTheme::kDisabled:
      // Draw nothing over the regular background.
      break;
    case NativeTheme::kHovered:
      // TODO(tapted): Draw a gradient, and use [NSColor currentControlTint] to
      // pick colors. The System color "selectedMenuItemColor" is actually still
      // blue for Graphite. And while "keyboardFocusIndicatorColor" does change,
      // and is a good shade of gray, it's not blue enough for the Blue theme.
      paint.setColor(GetSystemColor(kColorId_HoverMenuItemBackgroundColor));
      canvas->drawRect(gfx::RectToSkRect(rect), paint);
      break;
    default:
      NOTREACHED();
      break;
  }
}

NativeThemeMac::NativeThemeMac() {
  set_scrollbar_button_length(0);
  SetScrollbarColors(kScrollerThumbColor,
                     kScrollerThumbHoverColor,
                     kScrollerTrackGradientColors[0]);
}

NativeThemeMac::~NativeThemeMac() {
}

}  // namespace ui
