// Copyright 2014 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 "ash/sticky_keys/sticky_keys_overlay.h"

#include "ash/public/cpp/shell_window_ids.h"
#include "ash/shell.h"
#include "ash/sticky_keys/sticky_keys_controller.h"
#include "ash/strings/grit/ash_strings.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/border.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"

namespace ash {

namespace {

// Horizontal offset of the overlay from the top left of the screen.
const int kHorizontalOverlayOffset = 18;

// Vertical offset of the overlay from the top left of the screen.
const int kVerticalOverlayOffset = 18;

// Font style used for modifier key labels.
const ui::ResourceBundle::FontStyle kKeyLabelFontStyle =
    ui::ResourceBundle::LargeFont;

// Duration of slide animation when overlay is shown or hidden.
const int kSlideAnimationDurationMs = 100;

///////////////////////////////////////////////////////////////////////////////
//  StickyKeyOverlayLabel
class StickyKeyOverlayLabel : public views::Label {
 public:
  explicit StickyKeyOverlayLabel(const std::string& key_name);

  ~StickyKeyOverlayLabel() override;

  StickyKeyState state() const { return state_; }

  void SetKeyState(StickyKeyState state);

 private:
  StickyKeyState state_;

  DISALLOW_COPY_AND_ASSIGN(StickyKeyOverlayLabel);
};

StickyKeyOverlayLabel::StickyKeyOverlayLabel(const std::string& key_name)
    : state_(STICKY_KEY_STATE_DISABLED) {
  ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();

  SetText(base::UTF8ToUTF16(key_name));
  SetHorizontalAlignment(gfx::ALIGN_LEFT);
  SetFontList(rb->GetFontList(kKeyLabelFontStyle));
  SetAutoColorReadabilityEnabled(false);
  SetEnabledColor(SkColorSetARGB(0x80, 0xFF, 0xFF, 0xFF));
  SetSubpixelRenderingEnabled(false);
}

StickyKeyOverlayLabel::~StickyKeyOverlayLabel() = default;

void StickyKeyOverlayLabel::SetKeyState(StickyKeyState state) {
  state_ = state;
  SkColor label_color;
  int style;
  switch (state) {
    case STICKY_KEY_STATE_ENABLED:
      style = gfx::Font::NORMAL;
      label_color = SkColorSetA(GetEnabledColor(), 0xFF);
      break;
    case STICKY_KEY_STATE_LOCKED:
      style = gfx::Font::UNDERLINE;
      label_color = SkColorSetA(GetEnabledColor(), 0xFF);
      break;
    default:
      style = gfx::Font::NORMAL;
      label_color = SkColorSetA(GetEnabledColor(), 0x80);
  }

  SetEnabledColor(label_color);
  SetFontList(font_list().DeriveWithStyle(style));
}

}  // namespace

///////////////////////////////////////////////////////////////////////////////
//  StickyKeysOverlayView
class StickyKeysOverlayView : public views::View {
 public:
  // This object is not owned by the views hiearchy or by the widget. The
  // StickyKeysOverlay is the only class that should create and destroy this
  // view.
  StickyKeysOverlayView();

  ~StickyKeysOverlayView() override;

  // views::View overrides:
  void OnPaint(gfx::Canvas* canvas) override;

  void SetKeyState(ui::EventFlags modifier, StickyKeyState state);

  StickyKeyState GetKeyState(ui::EventFlags modifier);

  void SetModifierVisible(ui::EventFlags modifier, bool visible);
  bool GetModifierVisible(ui::EventFlags modifier);

 private:
  void AddKeyLabel(ui::EventFlags modifier, const std::string& key_label);

  typedef std::map<ui::EventFlags, StickyKeyOverlayLabel*> ModifierLabelMap;
  ModifierLabelMap modifier_label_map_;

  DISALLOW_COPY_AND_ASSIGN(StickyKeysOverlayView);
};

StickyKeysOverlayView::StickyKeysOverlayView() {
  // The parent StickyKeysOverlay object owns this view.
  set_owned_by_client();

  const gfx::Font& font =
      ui::ResourceBundle::GetSharedInstance().GetFont(kKeyLabelFontStyle);
  int font_size = font.GetFontSize();
  int font_padding = font.GetHeight() - font.GetBaseline();

  // Text should have a margin of 0.5 times the font size on each side, so
  // the spacing between two labels will be the same as the font size.
  int horizontal_spacing = font_size / 2;
  int vertical_spacing = font_size / 2 - font_padding;
  int child_spacing = font_size - 2 * font_padding;

  SetLayoutManager(std::make_unique<views::BoxLayout>(
      views::BoxLayout::Orientation::kVertical,
      gfx::Insets(vertical_spacing, horizontal_spacing), child_spacing));
  AddKeyLabel(ui::EF_CONTROL_DOWN,
              l10n_util::GetStringUTF8(IDS_ASH_CONTROL_KEY));
  AddKeyLabel(ui::EF_ALT_DOWN, l10n_util::GetStringUTF8(IDS_ASH_ALT_KEY));
  AddKeyLabel(ui::EF_SHIFT_DOWN, l10n_util::GetStringUTF8(IDS_ASH_SHIFT_KEY));
  AddKeyLabel(ui::EF_COMMAND_DOWN,
              l10n_util::GetStringUTF8(IDS_ASH_SEARCH_KEY));
  AddKeyLabel(ui::EF_ALTGR_DOWN, l10n_util::GetStringUTF8(IDS_ASH_ALTGR_KEY));
  AddKeyLabel(ui::EF_MOD3_DOWN, l10n_util::GetStringUTF8(IDS_ASH_MOD3_KEY));
}

StickyKeysOverlayView::~StickyKeysOverlayView() = default;

void StickyKeysOverlayView::OnPaint(gfx::Canvas* canvas) {
  cc::PaintFlags flags;
  flags.setStyle(cc::PaintFlags::kFill_Style);
  flags.setColor(SkColorSetARGB(0xB3, 0x55, 0x55, 0x55));
  canvas->DrawRoundRect(GetLocalBounds(), 2, flags);
  views::View::OnPaint(canvas);
}

void StickyKeysOverlayView::SetKeyState(ui::EventFlags modifier,
                                        StickyKeyState state) {
  ModifierLabelMap::iterator it = modifier_label_map_.find(modifier);
  DCHECK(it != modifier_label_map_.end());
  if (it != modifier_label_map_.end()) {
    StickyKeyOverlayLabel* label = it->second;
    label->SetKeyState(state);
  }
}

StickyKeyState StickyKeysOverlayView::GetKeyState(ui::EventFlags modifier) {
  ModifierLabelMap::iterator it = modifier_label_map_.find(modifier);
  DCHECK(it != modifier_label_map_.end());
  return it->second->state();
}

void StickyKeysOverlayView::SetModifierVisible(ui::EventFlags modifier,
                                               bool visible) {
  ModifierLabelMap::iterator it = modifier_label_map_.find(modifier);
  DCHECK(it != modifier_label_map_.end());
  it->second->SetVisible(visible);
}

bool StickyKeysOverlayView::GetModifierVisible(ui::EventFlags modifier) {
  ModifierLabelMap::iterator it = modifier_label_map_.find(modifier);
  DCHECK(it != modifier_label_map_.end());
  return it->second->GetVisible();
}

void StickyKeysOverlayView::AddKeyLabel(ui::EventFlags modifier,
                                        const std::string& key_label) {
  StickyKeyOverlayLabel* label = new StickyKeyOverlayLabel(key_label);
  AddChildView(label);
  modifier_label_map_[modifier] = label;
}

///////////////////////////////////////////////////////////////////////////////
//  StickyKeysOverlay
StickyKeysOverlay::StickyKeysOverlay()
    : is_visible_(false),
      overlay_view_(new StickyKeysOverlayView),
      widget_size_(overlay_view_->GetPreferredSize()) {
  views::Widget::InitParams params;
  params.type = views::Widget::InitParams::TYPE_POPUP;
  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
  params.accept_events = false;
  params.z_order = ui::ZOrderLevel::kFloatingUIElement;
  params.bounds = CalculateOverlayBounds();
  params.parent = Shell::GetContainer(Shell::GetRootWindowForNewWindows(),
                                      kShellWindowId_OverlayContainer);
  overlay_widget_.reset(new views::Widget);
  overlay_widget_->Init(std::move(params));
  overlay_widget_->SetVisibilityChangedAnimationsEnabled(false);
  overlay_widget_->SetContentsView(overlay_view_.get());
  overlay_widget_->GetNativeView()->SetName("StickyKeysOverlay");
}

StickyKeysOverlay::~StickyKeysOverlay() {
  // Remove ourself from the animator to avoid being re-entrantly called in
  // |overlay_widget_|'s destructor.
  StopObservingImplicitAnimations();
}

void StickyKeysOverlay::Show(bool visible) {
  if (is_visible_ == visible)
    return;

  is_visible_ = visible;
  if (is_visible_)
    overlay_widget_->Show();
  overlay_widget_->SetBounds(CalculateOverlayBounds());

  ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator();

  // Ensure transform is correct before beginning animation.
  if (!animator->is_animating()) {
    int sign = is_visible_ ? -1 : 1;
    gfx::Transform transform;
    transform.Translate(
        sign * (widget_size_.width() + kHorizontalOverlayOffset), 0);
    overlay_widget_->GetLayer()->SetTransform(transform);
  }

  ui::ScopedLayerAnimationSettings settings(animator);
  settings.AddObserver(this);
  settings.SetPreemptionStrategy(
      ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
  settings.SetTweenType(visible ? gfx::Tween::EASE_OUT : gfx::Tween::EASE_IN);
  settings.SetTransitionDuration(
      base::TimeDelta::FromMilliseconds(kSlideAnimationDurationMs));

  overlay_widget_->GetLayer()->SetTransform(gfx::Transform());
}

void StickyKeysOverlay::SetModifierVisible(ui::EventFlags modifier,
                                           bool visible) {
  overlay_view_->SetModifierVisible(modifier, visible);
  widget_size_ = overlay_view_->GetPreferredSize();
}

bool StickyKeysOverlay::GetModifierVisible(ui::EventFlags modifier) {
  return overlay_view_->GetModifierVisible(modifier);
}

void StickyKeysOverlay::SetModifierKeyState(ui::EventFlags modifier,
                                            StickyKeyState state) {
  overlay_view_->SetKeyState(modifier, state);
}

StickyKeyState StickyKeysOverlay::GetModifierKeyState(ui::EventFlags modifier) {
  return overlay_view_->GetKeyState(modifier);
}

views::Widget* StickyKeysOverlay::GetWidgetForTesting() {
  return overlay_widget_.get();
}

gfx::Rect StickyKeysOverlay::CalculateOverlayBounds() {
  int x = is_visible_ ? kHorizontalOverlayOffset : -widget_size_.width();
  return gfx::Rect(gfx::Point(x, kVerticalOverlayOffset), widget_size_);
}

void StickyKeysOverlay::OnImplicitAnimationsCompleted() {
  if (WasAnimationAbortedForProperty(ui::LayerAnimationElement::TRANSFORM))
    return;
  DCHECK(
      WasAnimationCompletedForProperty(ui::LayerAnimationElement::TRANSFORM));
  if (!is_visible_)
    overlay_widget_->Hide();
}

}  // namespace ash
