// Copyright (c) 2019 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/system/unified/page_indicator_view.h"

#include <algorithm>
#include <memory>
#include <utility>

#include "ash/app_list/app_list_metrics.h"
#include "ash/public/cpp/pagination/pagination_model.h"
#include "ash/system/tray/tray_constants.h"
#include "ash/system/unified/unified_system_tray_controller.h"
#include "base/i18n/number_formatting.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
#include "third_party/skia/include/core/SkPath.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/animation/throb_animation.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/skia_util.h"
#include "ui/strings/grit/ui_strings.h"
#include "ui/views/animation/flood_fill_ink_drop_ripple.h"
#include "ui/views/animation/ink_drop_highlight.h"
#include "ui/views/animation/ink_drop_impl.h"
#include "ui/views/animation/ink_drop_mask.h"
#include "ui/views/animation/ink_drop_painted_layer_delegates.h"
#include "ui/views/background.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/layout/box_layout.h"

namespace ash {

namespace {

constexpr int kInkDropRadius = 3 * kUnifiedPageIndicatorButtonRadius;

constexpr SkColor kInkDropRippleColor =
    SkColorSetA(kUnifiedPageIndicatorButtonInkDropColor, 0xF);
constexpr SkColor kInkDropHighlightColor =
    SkColorSetA(kUnifiedPageIndicatorButtonInkDropColor, 0x14);

}  // namespace

// Button internally used in PageIndicatorView. Each button
// stores a page number which it switches to if pressed.
class PageIndicatorView::PageIndicatorButton : public views::Button,
                                               public views::ButtonListener {
 public:
  explicit PageIndicatorButton(UnifiedSystemTrayController* controller,
                               int page)
      : views::Button(this), controller_(controller), page_number_(page) {
    SetInkDropMode(InkDropMode::ON);
  }

  ~PageIndicatorButton() override {}

  void SetSelected(bool selected) {
    if (selected == selected_)
      return;

    selected_ = selected;
    SchedulePaint();
    if (selected)
      NotifyAccessibilityEvent(ax::mojom::Event::kAlert, true);
  }

  gfx::Size CalculatePreferredSize() const override {
    return gfx::Size(kInkDropRadius * 2, kInkDropRadius * 2);
  }

  void PaintButtonContents(gfx::Canvas* canvas) override {
    gfx::Rect rect(GetContentsBounds());

    SkColor current_color = selected_
                                ? kUnifiedPageIndicatorButtonColor
                                : SkColorSetA(kUnifiedPageIndicatorButtonColor,
                                              kUnifiedPageIndicatorButtonAlpha);

    cc::PaintFlags flags;
    flags.setAntiAlias(true);
    flags.setStyle(cc::PaintFlags::kFill_Style);
    flags.setColor(current_color);
    canvas->DrawCircle(rect.CenterPoint(), kUnifiedPageIndicatorButtonRadius,
                       flags);
  }
  void ButtonPressed(views::Button* sender, const ui::Event& event) override {
    DCHECK(controller_);
    controller_->HandlePageSwitchAction(page_number_);
  }

  bool selected() { return selected_; }

 protected:
  std::unique_ptr<views::InkDrop> CreateInkDrop() override {
    std::unique_ptr<views::InkDropImpl> ink_drop =
        Button::CreateDefaultInkDropImpl();
    ink_drop->SetShowHighlightOnHover(true);
    ink_drop->SetAutoHighlightMode(
        views::InkDropImpl::AutoHighlightMode::SHOW_ON_RIPPLE);
    return std::move(ink_drop);
  }

  std::unique_ptr<views::InkDropMask> CreateInkDropMask() const override {
    return std::make_unique<views::CircleInkDropMask>(
        size(), GetLocalBounds().CenterPoint(), kInkDropRadius);
  }

  std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override {
    gfx::Point center = GetLocalBounds().CenterPoint();
    gfx::Rect bounds(center.x() - kInkDropRadius, center.y() - kInkDropRadius,
                     2 * kInkDropRadius, 2 * kInkDropRadius);
    return std::make_unique<views::FloodFillInkDropRipple>(
        size(), GetLocalBounds().InsetsFrom(bounds),
        GetInkDropCenterBasedOnLastEvent(), kInkDropRippleColor, 1.0f);
  }

  std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight()
      const override {
    return std::make_unique<views::InkDropHighlight>(
        gfx::PointF(GetLocalBounds().CenterPoint()),
        std::make_unique<views::CircleLayerDelegate>(kInkDropHighlightColor,
                                                     kInkDropRadius));
  }

  void NotifyClick(const ui::Event& event) override {
    Button::NotifyClick(event);
    GetInkDrop()->AnimateToState(views::InkDropState::ACTION_TRIGGERED);
  }

 private:
  bool selected_ = false;
  UnifiedSystemTrayController* const controller_;
  const int page_number_ = 0;

  DISALLOW_COPY_AND_ASSIGN(PageIndicatorButton);
};

PageIndicatorView::PageIndicatorView(UnifiedSystemTrayController* controller,
                                     bool initially_expanded)
    : controller_(controller),
      model_(controller->model()->pagination_model()),
      expanded_amount_(initially_expanded ? 1 : 0),
      buttons_container_(new views::View) {
  SetVisible(initially_expanded);
  SetPaintToLayer();
  layer()->SetFillsBoundsOpaquely(false);

  buttons_container_->SetLayoutManager(std::make_unique<views::BoxLayout>(
      views::BoxLayout::kHorizontal, gfx::Insets()));

  AddChildView(buttons_container_);

  TotalPagesChanged();

  DCHECK(model_);
  model_->AddObserver(this);
}

PageIndicatorView::~PageIndicatorView() {
  model_->RemoveObserver(this);
}

gfx::Size PageIndicatorView::CalculatePreferredSize() const {
  gfx::Size size = buttons_container_->GetPreferredSize();
  size.set_height(size.height() * expanded_amount_);
  return size;
}

void PageIndicatorView::Layout() {
  gfx::Rect rect(GetContentsBounds());

  gfx::Size buttons_container_size(buttons_container_->GetPreferredSize());
  rect.ClampToCenteredSize(buttons_container_size);
  buttons_container_->SetBoundsRect(rect);
}

void PageIndicatorView::SetExpandedAmount(double expanded_amount) {
  DCHECK(0.0 <= expanded_amount && expanded_amount <= 1.0);
  SetVisible(expanded_amount > 0.0);
  expanded_amount_ = expanded_amount;
  InvalidateLayout();
  layer()->SetOpacity(expanded_amount_);
}

void PageIndicatorView::TotalPagesChanged() {
  DCHECK(model_);

  buttons_container_->RemoveAllChildViews(true);
  for (int i = 0; i < model_->total_pages(); ++i) {
    PageIndicatorButton* button = new PageIndicatorButton(controller_, i);
    button->SetAccessibleName(l10n_util::GetStringFUTF16(
        IDS_APP_LIST_PAGE_SWITCHER, base::FormatNumber(i + 1),
        base::FormatNumber(model_->total_pages())));
    button->SetSelected(i == model_->selected_page());
    buttons_container_->AddChildView(button);
  }
  buttons_container_->SetVisible(model_->total_pages() > 1);
  Layout();
}

PageIndicatorView::PageIndicatorButton* PageIndicatorView::GetButtonByIndex(
    int index) {
  return static_cast<PageIndicatorButton*>(
      buttons_container_->children().at(index));
}

void PageIndicatorView::SelectedPageChanged(int old_selected,
                                            int new_selected) {
  size_t total_children = buttons_container_->children().size();

  if (old_selected >= 0 && size_t{old_selected} < total_children)
    GetButtonByIndex(old_selected)->SetSelected(false);
  if (new_selected >= 0 && size_t{old_selected} < total_children)
    GetButtonByIndex(new_selected)->SetSelected(true);
}

bool PageIndicatorView::IsPageSelectedForTesting(int index) {
  return GetButtonByIndex(index)->selected();
}

}  // namespace ash