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

#include "ui/views/controls/label.h"

#include <algorithm>
#include <cmath>
#include <limits>
#include <vector>

#include "base/i18n/rtl.h"
#include "base/logging.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/accessibility/ax_view_state.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/insets.h"
#include "ui/gfx/text_elider.h"
#include "ui/gfx/text_utils.h"
#include "ui/gfx/utf16_indexing.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/background.h"

namespace {

const int kCachedSizeLimit = 10;
const base::char16 kPasswordReplacementChar = '*';

}  // namespace

namespace views {

// static
const char Label::kViewClassName[] = "Label";
const int Label::kFocusBorderPadding = 1;

Label::Label() {
  Init(base::string16(), gfx::FontList());
}

Label::Label(const base::string16& text) {
  Init(text, gfx::FontList());
}

Label::Label(const base::string16& text, const gfx::FontList& font_list) {
  Init(text, font_list);
}

Label::~Label() {
}

void Label::SetFontList(const gfx::FontList& font_list) {
  font_list_ = font_list;
  ResetCachedSize();
  PreferredSizeChanged();
  SchedulePaint();
}

void Label::SetText(const base::string16& text) {
  if (text != text_)
    SetTextInternal(text);
}

void Label::SetTextInternal(const base::string16& text) {
  text_ = text;

  if (obscured_) {
    size_t obscured_text_length =
        static_cast<size_t>(gfx::UTF16IndexToOffset(text_, 0, text_.length()));
    layout_text_.assign(obscured_text_length, kPasswordReplacementChar);
  } else {
    layout_text_ = text_;
  }

  ResetCachedSize();
  PreferredSizeChanged();
  SchedulePaint();
}

void Label::SetAutoColorReadabilityEnabled(bool enabled) {
  auto_color_readability_ = enabled;
  RecalculateColors();
}

void Label::SetEnabledColor(SkColor color) {
  requested_enabled_color_ = color;
  enabled_color_set_ = true;
  RecalculateColors();
}

void Label::SetDisabledColor(SkColor color) {
  requested_disabled_color_ = color;
  disabled_color_set_ = true;
  RecalculateColors();
}

void Label::SetBackgroundColor(SkColor color) {
  background_color_ = color;
  background_color_set_ = true;
  RecalculateColors();
}

void Label::SetShadows(const gfx::ShadowValues& shadows) {
  shadows_ = shadows;
  text_size_valid_ = false;
}

void Label::SetSubpixelRenderingEnabled(bool subpixel_rendering_enabled) {
  subpixel_rendering_enabled_ = subpixel_rendering_enabled;
}

void Label::SetHorizontalAlignment(gfx::HorizontalAlignment alignment) {
  // If the UI layout is right-to-left, flip the alignment direction.
  if (base::i18n::IsRTL() &&
      (alignment == gfx::ALIGN_LEFT || alignment == gfx::ALIGN_RIGHT)) {
    alignment = (alignment == gfx::ALIGN_LEFT) ?
        gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT;
  }
  if (horizontal_alignment_ != alignment) {
    horizontal_alignment_ = alignment;
    SchedulePaint();
  }
}

gfx::HorizontalAlignment Label::GetHorizontalAlignment() const {
  if (horizontal_alignment_ != gfx::ALIGN_TO_HEAD)
    return horizontal_alignment_;

  const base::i18n::TextDirection dir =
      base::i18n::GetFirstStrongCharacterDirection(layout_text_);
  return dir == base::i18n::RIGHT_TO_LEFT ? gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT;
}

void Label::SetLineHeight(int height) {
  if (height != line_height_) {
    line_height_ = height;
    ResetCachedSize();
    PreferredSizeChanged();
    SchedulePaint();
  }
}

void Label::SetMultiLine(bool multi_line) {
  DCHECK(!multi_line || (elide_behavior_ == gfx::ELIDE_TAIL ||
                         elide_behavior_ == gfx::NO_ELIDE));
  if (multi_line != multi_line_) {
    multi_line_ = multi_line;
    ResetCachedSize();
    PreferredSizeChanged();
    SchedulePaint();
  }
}

void Label::SetObscured(bool obscured) {
  if (obscured != obscured_) {
    obscured_ = obscured;
    SetTextInternal(text_);
  }
}

void Label::SetAllowCharacterBreak(bool allow_character_break) {
  if (allow_character_break != allow_character_break_) {
    allow_character_break_ = allow_character_break;
    ResetCachedSize();
    PreferredSizeChanged();
    SchedulePaint();
  }
}

void Label::SetElideBehavior(gfx::ElideBehavior elide_behavior) {
  DCHECK(!multi_line_ || (elide_behavior_ == gfx::ELIDE_TAIL ||
                          elide_behavior_ == gfx::NO_ELIDE));
  if (elide_behavior != elide_behavior_) {
    elide_behavior_ = elide_behavior;
    ResetCachedSize();
    PreferredSizeChanged();
    SchedulePaint();
  }
}

void Label::SetTooltipText(const base::string16& tooltip_text) {
  DCHECK(handles_tooltips_);
  tooltip_text_ = tooltip_text;
}

void Label::SetHandlesTooltips(bool enabled) {
  handles_tooltips_ = enabled;
}

void Label::SizeToFit(int max_width) {
  DCHECK(multi_line_);

  std::vector<base::string16> lines;
  base::SplitString(layout_text_, '\n', &lines);

  int label_width = 0;
  for (std::vector<base::string16>::const_iterator iter = lines.begin();
       iter != lines.end(); ++iter) {
    label_width = std::max(label_width, gfx::GetStringWidth(*iter, font_list_));
  }

  label_width += GetInsets().width();

  if (max_width > 0)
    label_width = std::min(label_width, max_width);

  SetBounds(x(), y(), label_width, 0);
  SizeToPreferredSize();
}

const base::string16& Label::GetLayoutTextForTesting() const {
  return layout_text_;
}

gfx::Insets Label::GetInsets() const {
  gfx::Insets insets = View::GetInsets();
  if (focusable()) {
    insets += gfx::Insets(kFocusBorderPadding, kFocusBorderPadding,
                          kFocusBorderPadding, kFocusBorderPadding);
  }
  return insets;
}

int Label::GetBaseline() const {
  return GetInsets().top() + font_list_.GetBaseline();
}

gfx::Size Label::GetPreferredSize() const {
  // Return a size of (0, 0) if the label is not visible and if the
  // collapse_when_hidden_ flag is set.
  // TODO(munjal): This logic probably belongs to the View class. But for now,
  // put it here since putting it in View class means all inheriting classes
  // need ot respect the collapse_when_hidden_ flag.
  if (!visible() && collapse_when_hidden_)
    return gfx::Size();

  gfx::Size size(GetTextSize());
  gfx::Insets insets = GetInsets();
  size.Enlarge(insets.width(), insets.height());
  return size;
}

gfx::Size Label::GetMinimumSize() const {
  gfx::Size text_size(GetTextSize());
  if ((!visible() && collapse_when_hidden_) || text_size.IsEmpty())
    return gfx::Size();

  gfx::Size size(gfx::GetStringWidth(base::string16(gfx::kEllipsisUTF16),
                                     font_list_),
                 font_list_.GetHeight());
  size.SetToMin(text_size);  // The actual text may be shorter than an ellipsis.
  gfx::Insets insets = GetInsets();
  size.Enlarge(insets.width(), insets.height());
  return size;
}

int Label::GetHeightForWidth(int w) const {
  if (!multi_line_)
    return View::GetHeightForWidth(w);

  w = std::max(0, w - GetInsets().width());

  for (size_t i = 0; i < cached_heights_.size(); ++i) {
    const gfx::Size& s = cached_heights_[i];
    if (s.width() == w)
      return s.height() + GetInsets().height();
  }

  int cache_width = w;

  int h = font_list_.GetHeight();
  const int flags = ComputeDrawStringFlags();
  gfx::Canvas::SizeStringInt(
      layout_text_, font_list_, &w, &h, line_height_, flags);
  cached_heights_[cached_heights_cursor_] = gfx::Size(cache_width, h);
  cached_heights_cursor_ = (cached_heights_cursor_ + 1) % kCachedSizeLimit;
  return h + GetInsets().height();
}

const char* Label::GetClassName() const {
  return kViewClassName;
}

View* Label::GetTooltipHandlerForPoint(const gfx::Point& point) {
  if (!handles_tooltips_ ||
      (tooltip_text_.empty() && !ShouldShowDefaultTooltip()))
    return NULL;

  return HitTestPoint(point) ? this : NULL;
}

bool Label::CanProcessEventsWithinSubtree() const {
  // Send events to the parent view for handling.
  return false;
}

void Label::GetAccessibleState(ui::AXViewState* state) {
  state->role = ui::AX_ROLE_STATIC_TEXT;
  state->AddStateFlag(ui::AX_STATE_READ_ONLY);
  state->name = layout_text_;
}

bool Label::GetTooltipText(const gfx::Point& p, base::string16* tooltip) const {
  if (!handles_tooltips_)
    return false;

  if (!tooltip_text_.empty()) {
    tooltip->assign(tooltip_text_);
    return true;
  }

  if (ShouldShowDefaultTooltip()) {
    *tooltip = layout_text_;
    return true;
  }

  return false;
}

void Label::PaintText(gfx::Canvas* canvas,
                      const base::string16& text,
                      const gfx::Rect& text_bounds,
                      int flags) {
  SkColor color = enabled() ? actual_enabled_color_ : actual_disabled_color_;
  if (elide_behavior_ == gfx::FADE_TAIL) {
    canvas->DrawFadedString(text, font_list_, color, text_bounds, flags);
  } else {
    canvas->DrawStringRectWithShadows(text, font_list_, color, text_bounds,
                                      line_height_, flags, shadows_);
  }

  if (HasFocus()) {
    gfx::Rect focus_bounds = text_bounds;
    focus_bounds.Inset(-kFocusBorderPadding, -kFocusBorderPadding);
    canvas->DrawFocusRect(focus_bounds);
  }
}

gfx::Size Label::GetTextSize() const {
  if (!text_size_valid_) {
    // For single-line strings, we supply the largest possible width, because
    // while adding NO_ELLIPSIS to the flags works on Windows for forcing
    // SizeStringInt() to calculate the desired width, it doesn't seem to work
    // on Linux.
    int w = multi_line_ ?
        GetAvailableRect().width() : std::numeric_limits<int>::max();
    int h = font_list_.GetHeight();
    // For single-line strings, ignore the available width and calculate how
    // wide the text wants to be.
    int flags = ComputeDrawStringFlags();
    if (!multi_line_)
      flags |= gfx::Canvas::NO_ELLIPSIS;
    gfx::Canvas::SizeStringInt(
        layout_text_, font_list_, &w, &h, line_height_, flags);
    text_size_.SetSize(w, h);
    const gfx::Insets shadow_margin = -gfx::ShadowValue::GetMargin(shadows_);
    text_size_.Enlarge(shadow_margin.width(), shadow_margin.height());
    text_size_valid_ = true;
  }

  return text_size_;
}

void Label::OnBoundsChanged(const gfx::Rect& previous_bounds) {
  text_size_valid_ &= !multi_line_;
}

void Label::OnPaint(gfx::Canvas* canvas) {
  OnPaintBackground(canvas);
  // We skip painting the focus border because it is being handled seperately by
  // some subclasses of Label. We do not want View's focus border painting to
  // interfere with that.
  OnPaintBorder(canvas);

  base::string16 paint_text;
  gfx::Rect text_bounds;
  int flags = 0;
  CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
  PaintText(canvas, paint_text, text_bounds, flags);
}

void Label::OnNativeThemeChanged(const ui::NativeTheme* theme) {
  UpdateColorsFromTheme(theme);
}

void Label::Init(const base::string16& text, const gfx::FontList& font_list) {
  font_list_ = font_list;
  enabled_color_set_ = disabled_color_set_ = background_color_set_ = false;
  subpixel_rendering_enabled_ = true;
  auto_color_readability_ = true;
  UpdateColorsFromTheme(ui::NativeTheme::instance());
  horizontal_alignment_ = gfx::ALIGN_CENTER;
  line_height_ = 0;
  multi_line_ = false;
  obscured_ = false;
  allow_character_break_ = false;
  elide_behavior_ = gfx::ELIDE_TAIL;
  handles_tooltips_ = true;
  collapse_when_hidden_ = false;
  cached_heights_.resize(kCachedSizeLimit);
  ResetCachedSize();

  SetText(text);
}

void Label::RecalculateColors() {
  actual_enabled_color_ = auto_color_readability_ ?
      color_utils::GetReadableColor(requested_enabled_color_,
                                    background_color_) :
      requested_enabled_color_;
  actual_disabled_color_ = auto_color_readability_ ?
      color_utils::GetReadableColor(requested_disabled_color_,
                                    background_color_) :
      requested_disabled_color_;
}

gfx::Rect Label::GetTextBounds() const {
  gfx::Rect available(GetAvailableRect());
  gfx::Size text_size(GetTextSize());
  text_size.set_width(std::min(available.width(), text_size.width()));
  gfx::Point origin(GetInsets().left(), GetInsets().top());
  switch (GetHorizontalAlignment()) {
    case gfx::ALIGN_LEFT:
      break;
    case gfx::ALIGN_CENTER:
      // Put any extra margin pixel on the left to match the legacy behavior
      // from the use of GetTextExtentPoint32() on Windows.
      origin.Offset((available.width() + 1 - text_size.width()) / 2, 0);
      break;
    case gfx::ALIGN_RIGHT:
      origin.set_x(available.right() - text_size.width());
      break;
    default:
      NOTREACHED();
      break;
  }
  text_size.set_height(available.height());
  return gfx::Rect(origin, text_size);
}

int Label::ComputeDrawStringFlags() const {
  int flags = 0;

  // We can't use subpixel rendering if the background is non-opaque.
  if (SkColorGetA(background_color_) != 0xFF || !subpixel_rendering_enabled_)
    flags |= gfx::Canvas::NO_SUBPIXEL_RENDERING;

  base::i18n::TextDirection direction =
      base::i18n::GetFirstStrongCharacterDirection(layout_text_);
  if (direction == base::i18n::RIGHT_TO_LEFT)
    flags |= gfx::Canvas::FORCE_RTL_DIRECTIONALITY;
  else
    flags |= gfx::Canvas::FORCE_LTR_DIRECTIONALITY;

  switch (GetHorizontalAlignment()) {
    case gfx::ALIGN_LEFT:
      flags |= gfx::Canvas::TEXT_ALIGN_LEFT;
      break;
    case gfx::ALIGN_CENTER:
      flags |= gfx::Canvas::TEXT_ALIGN_CENTER;
      break;
    case gfx::ALIGN_RIGHT:
      flags |= gfx::Canvas::TEXT_ALIGN_RIGHT;
      break;
    default:
      NOTREACHED();
      break;
  }

  if (!multi_line_)
    return flags;

  flags |= gfx::Canvas::MULTI_LINE;
#if !defined(OS_WIN)
    // Don't elide multiline labels on Linux.
    // Todo(davemoore): Do we depend on eliding multiline text?
    // Pango insists on limiting the number of lines to one if text is
    // elided. You can get around this if you can pass a maximum height
    // but we don't currently have that data when we call the pango code.
    flags |= gfx::Canvas::NO_ELLIPSIS;
#endif
  if (allow_character_break_)
    flags |= gfx::Canvas::CHARACTER_BREAK;

  return flags;
}

gfx::Rect Label::GetAvailableRect() const {
  gfx::Rect bounds(size());
  bounds.Inset(GetInsets());
  return bounds;
}

void Label::CalculateDrawStringParams(base::string16* paint_text,
                                      gfx::Rect* text_bounds,
                                      int* flags) const {
  DCHECK(paint_text && text_bounds && flags);

  const bool forbid_ellipsis = elide_behavior_ == gfx::NO_ELIDE ||
                               elide_behavior_ == gfx::FADE_TAIL;
  if (multi_line_ || forbid_ellipsis) {
    *paint_text = layout_text_;
  } else {
    *paint_text = gfx::ElideText(layout_text_, font_list_,
                                 GetAvailableRect().width(), elide_behavior_);
  }

  *text_bounds = GetTextBounds();
  *flags = ComputeDrawStringFlags();
  // TODO(msw): Elide multi-line text with ElideRectangleText instead.
  if (!multi_line_ || forbid_ellipsis)
    *flags |= gfx::Canvas::NO_ELLIPSIS;
}

void Label::UpdateColorsFromTheme(const ui::NativeTheme* theme) {
  if (!enabled_color_set_) {
    requested_enabled_color_ = theme->GetSystemColor(
        ui::NativeTheme::kColorId_LabelEnabledColor);
  }
  if (!disabled_color_set_) {
    requested_disabled_color_ = theme->GetSystemColor(
        ui::NativeTheme::kColorId_LabelDisabledColor);
  }
  if (!background_color_set_) {
    background_color_ = theme->GetSystemColor(
        ui::NativeTheme::kColorId_LabelBackgroundColor);
  }
  RecalculateColors();
}

void Label::ResetCachedSize() {
  text_size_valid_ = false;
  cached_heights_cursor_ = 0;
  for (int i = 0; i < kCachedSizeLimit; ++i)
    cached_heights_[i] = gfx::Size();
}

bool Label::ShouldShowDefaultTooltip() const {
  const gfx::Size text_size = GetTextSize();
  const gfx::Size size = GetContentsBounds().size();
  return !obscured() && (text_size.width() > size.width() ||
                         (multi_line_ && text_size.height() > size.height()));
}

}  // namespace views
