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

#include <algorithm>

#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "grit/ui_resources.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "ui/accessibility/ax_view_state.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/events/event.h"
#include "ui/gfx/animation/slide_animation.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect.h"
#include "ui/views/widget/widget.h"

namespace {
const int kSlideValueChangeDurationMS = 150;

const int kBarImagesActive[] = {
    IDR_SLIDER_ACTIVE_LEFT,
    IDR_SLIDER_ACTIVE_CENTER,
    IDR_SLIDER_PRESSED_CENTER,
    IDR_SLIDER_PRESSED_RIGHT,
};

const int kBarImagesDisabled[] = {
    IDR_SLIDER_DISABLED_LEFT,
    IDR_SLIDER_DISABLED_CENTER,
    IDR_SLIDER_DISABLED_CENTER,
    IDR_SLIDER_DISABLED_RIGHT,
};

// The image chunks.
enum BorderElements {
  LEFT,
  CENTER_LEFT,
  CENTER_RIGHT,
  RIGHT,
};
}  // namespace

namespace views {

Slider::Slider(SliderListener* listener, Orientation orientation)
    : listener_(listener),
      orientation_(orientation),
      value_(0.f),
      keyboard_increment_(0.1f),
      animating_value_(0.f),
      value_is_valid_(false),
      accessibility_events_enabled_(true),
      focus_border_color_(0),
      bar_active_images_(kBarImagesActive),
      bar_disabled_images_(kBarImagesDisabled) {
  EnableCanvasFlippingForRTLUI(true);
  SetFocusable(true);
  UpdateState(true);
}

Slider::~Slider() {
}

void Slider::SetValue(float value) {
  SetValueInternal(value, VALUE_CHANGED_BY_API);
}

void Slider::SetKeyboardIncrement(float increment) {
  keyboard_increment_ = increment;
}

void Slider::SetValueInternal(float value, SliderChangeReason reason) {
  bool old_value_valid = value_is_valid_;

  value_is_valid_ = true;
  if (value < 0.0)
    value = 0.0;
  else if (value > 1.0)
    value = 1.0;
  if (value_ == value)
    return;
  float old_value = value_;
  value_ = value;
  if (listener_)
    listener_->SliderValueChanged(this, value_, old_value, reason);

  if (old_value_valid && base::MessageLoop::current()) {
    // Do not animate when setting the value of the slider for the first time.
    // There is no message-loop when running tests. So we cannot animate then.
    animating_value_ = old_value;
    move_animation_.reset(new gfx::SlideAnimation(this));
    move_animation_->SetSlideDuration(kSlideValueChangeDurationMS);
    move_animation_->Show();
    AnimationProgressed(move_animation_.get());
  } else {
    SchedulePaint();
  }
  if (accessibility_events_enabled_ && GetWidget()) {
    NotifyAccessibilityEvent(
        ui::AX_EVENT_VALUE_CHANGED, true);
  }
}

void Slider::PrepareForMove(const gfx::Point& point) {
  // Try to remember the position of the mouse cursor on the button.
  gfx::Insets inset = GetInsets();
  gfx::Rect content = GetContentsBounds();
  float value = move_animation_.get() && move_animation_->is_animating() ?
        animating_value_ : value_;

  // For the horizontal orientation.
  const int thumb_x = value * (content.width() - thumb_->width());
  const int candidate_x = (base::i18n::IsRTL() ?
      width() - (point.x() - inset.left()) :
      point.x() - inset.left()) - thumb_x;
  if (candidate_x >= 0 && candidate_x < thumb_->width())
    initial_button_offset_.set_x(candidate_x);
  else
    initial_button_offset_.set_x(thumb_->width() / 2);

  // For the vertical orientation.
  const int thumb_y = (1.0 - value) * (content.height() - thumb_->height());
  const int candidate_y = point.y() - thumb_y;
  if (candidate_y >= 0 && candidate_y < thumb_->height())
    initial_button_offset_.set_y(candidate_y);
  else
    initial_button_offset_.set_y(thumb_->height() / 2);
}

void Slider::MoveButtonTo(const gfx::Point& point) {
  gfx::Insets inset = GetInsets();
  // Calculate the value.
  if (orientation_ == HORIZONTAL) {
    int amount = base::i18n::IsRTL() ?
        width() - inset.left() - point.x() - initial_button_offset_.x() :
        point.x() - inset.left() - initial_button_offset_.x();
    SetValueInternal(static_cast<float>(amount) /
                         (width() - inset.width() - thumb_->width()),
                     VALUE_CHANGED_BY_USER);
  } else {
    SetValueInternal(
        1.0f - static_cast<float>(point.y() - initial_button_offset_.y()) /
            (height() - thumb_->height()),
        VALUE_CHANGED_BY_USER);
  }
}

void Slider::UpdateState(bool control_on) {
  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  if (control_on) {
    thumb_ = rb.GetImageNamed(IDR_SLIDER_ACTIVE_THUMB).ToImageSkia();
    for (int i = 0; i < 4; ++i)
      images_[i] = rb.GetImageNamed(bar_active_images_[i]).ToImageSkia();
  } else {
    thumb_ = rb.GetImageNamed(IDR_SLIDER_DISABLED_THUMB).ToImageSkia();
    for (int i = 0; i < 4; ++i)
      images_[i] = rb.GetImageNamed(bar_disabled_images_[i]).ToImageSkia();
  }
  bar_height_ = images_[LEFT]->height();
  SchedulePaint();
}

void Slider::SetAccessibleName(const base::string16& name) {
  accessible_name_ = name;
}

void Slider::OnPaintFocus(gfx::Canvas* canvas) {
  if (!HasFocus())
    return;

  if (!focus_border_color_) {
    canvas->DrawFocusRect(GetLocalBounds());
  } else if (HasFocus()) {
    canvas->DrawSolidFocusRect(
        gfx::Rect(1, 1, width() - 3, height() - 3),
        focus_border_color_);
  }
}

gfx::Size Slider::GetPreferredSize() const {
  const int kSizeMajor = 200;
  const int kSizeMinor = 40;

  if (orientation_ == HORIZONTAL)
    return gfx::Size(std::max(width(), kSizeMajor), kSizeMinor);
  return gfx::Size(kSizeMinor, std::max(height(), kSizeMajor));
}

void Slider::OnPaint(gfx::Canvas* canvas) {
  gfx::Rect content = GetContentsBounds();
  float value = move_animation_.get() && move_animation_->is_animating() ?
      animating_value_ : value_;
  if (orientation_ == HORIZONTAL) {
    // Paint slider bar with image resources.

    // Inset the slider bar a little bit, so that the left or the right end of
    // the slider bar will not be exposed under the thumb button when the thumb
    // button slides to the left most or right most position.
    const int kBarInsetX = 2;
    int bar_width = content.width() - kBarInsetX * 2;
    int bar_cy = content.height() / 2 - bar_height_ / 2;

    int w = content.width() - thumb_->width();
    int full = value * w;
    int middle = std::max(full, images_[LEFT]->width());

    canvas->Save();
    canvas->Translate(gfx::Vector2d(kBarInsetX, bar_cy));
    canvas->DrawImageInt(*images_[LEFT], 0, 0);
    canvas->DrawImageInt(*images_[RIGHT],
                         bar_width - images_[RIGHT]->width(),
                         0);
    canvas->TileImageInt(*images_[CENTER_LEFT],
                         images_[LEFT]->width(),
                         0,
                         middle - images_[LEFT]->width(),
                         bar_height_);
    canvas->TileImageInt(*images_[CENTER_RIGHT],
                         middle,
                         0,
                         bar_width - middle - images_[RIGHT]->width(),
                         bar_height_);
    canvas->Restore();

    // Paint slider thumb.
    int button_cx = content.x() + full;
    int thumb_y = content.height() / 2 - thumb_->height() / 2;
    canvas->DrawImageInt(*thumb_, button_cx, thumb_y);
  } else {
    // TODO(jennyz): draw vertical slider bar with resources.
    // TODO(sad): The painting code should use NativeTheme for various
    // platforms.
    const int kButtonRadius = thumb_->width() / 2;
    const int kLineThickness = bar_height_ / 2;
    const SkColor kFullColor = SkColorSetARGB(125, 0, 0, 0);
    const SkColor kEmptyColor = SkColorSetARGB(50, 0, 0, 0);

    int h = content.height() - thumb_->height();
    int full = value * h;
    int empty = h - full;
    int x = content.width() / 2 - kLineThickness / 2;
    canvas->FillRect(gfx::Rect(x, content.y() + kButtonRadius,
                               kLineThickness, empty),
                     kEmptyColor);
    canvas->FillRect(gfx::Rect(x, content.y() + empty + 2 * kButtonRadius,
                               kLineThickness, full),
                     kFullColor);

    // TODO(mtomasz): We draw a thumb here because so far it is the same
    // for horizontal and vertical orientations. If it is different, then
    // we will need a separate resource.
    int button_cy = content.y() + h - full;
    int thumb_x = content.width() / 2 - thumb_->width() / 2;
    canvas->DrawImageInt(*thumb_, thumb_x, button_cy);
  }
  View::OnPaint(canvas);
  OnPaintFocus(canvas);
}

bool Slider::OnMousePressed(const ui::MouseEvent& event) {
  if (!event.IsOnlyLeftMouseButton())
    return false;
  OnSliderDragStarted();
  PrepareForMove(event.location());
  MoveButtonTo(event.location());
  return true;
}

bool Slider::OnMouseDragged(const ui::MouseEvent& event) {
  MoveButtonTo(event.location());
  return true;
}

void Slider::OnMouseReleased(const ui::MouseEvent& event) {
  OnSliderDragEnded();
}

bool Slider::OnKeyPressed(const ui::KeyEvent& event) {
  if (orientation_ == HORIZONTAL) {
    if (event.key_code() == ui::VKEY_LEFT) {
      SetValueInternal(value_ - keyboard_increment_, VALUE_CHANGED_BY_USER);
      return true;
    } else if (event.key_code() == ui::VKEY_RIGHT) {
      SetValueInternal(value_ + keyboard_increment_, VALUE_CHANGED_BY_USER);
      return true;
    }
  } else {
    if (event.key_code() == ui::VKEY_DOWN) {
      SetValueInternal(value_ - keyboard_increment_, VALUE_CHANGED_BY_USER);
      return true;
    } else if (event.key_code() == ui::VKEY_UP) {
      SetValueInternal(value_ + keyboard_increment_, VALUE_CHANGED_BY_USER);
      return true;
    }
  }
  return false;
}

void Slider::OnFocus() {
  View::OnFocus();
  SchedulePaint();
}

void Slider::OnBlur() {
  View::OnBlur();
  SchedulePaint();
}

void Slider::OnGestureEvent(ui::GestureEvent* event) {
  switch (event->type()) {
    // In a multi point gesture only the touch point will generate
    // an ET_GESTURE_TAP_DOWN event.
    case ui::ET_GESTURE_TAP_DOWN:
      OnSliderDragStarted();
      PrepareForMove(event->location());
      // Intentional fall through to next case.
    case ui::ET_GESTURE_SCROLL_BEGIN:
    case ui::ET_GESTURE_SCROLL_UPDATE:
      MoveButtonTo(event->location());
      event->SetHandled();
      break;
    case ui::ET_GESTURE_END:
      MoveButtonTo(event->location());
      event->SetHandled();
      if (event->details().touch_points() <= 1)
        OnSliderDragEnded();
      break;
    default:
      break;
  }
}

void Slider::AnimationProgressed(const gfx::Animation* animation) {
  animating_value_ = animation->CurrentValueBetween(animating_value_, value_);
  SchedulePaint();
}

void Slider::GetAccessibleState(ui::AXViewState* state) {
  state->role = ui::AX_ROLE_SLIDER;
  state->name = accessible_name_;
  state->value = base::UTF8ToUTF16(
      base::StringPrintf("%d%%", static_cast<int>(value_ * 100 + 0.5)));
}

void Slider::OnSliderDragStarted() {
  if (listener_)
    listener_->SliderDragStarted(this);
}

void Slider::OnSliderDragEnded() {
  if (listener_)
    listener_->SliderDragEnded(this);
}

}  // namespace views
