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

#include <algorithm>
#include <map>
#include <memory>
#include <string>
#include <utility>

#include "ash/accessibility/accessibility_controller_impl.h"
#include "ash/app_list/app_list_controller_impl.h"
#include "ash/public/cpp/ash_features.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/public/cpp/window_properties.h"
#include "ash/shell.h"
#include "ash/style/ash_color_provider.h"
#include "ash/wm/mru_window_tracker.h"
#include "ash/wm/window_mini_view.h"
#include "ash/wm/window_preview_view.h"
#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "base/metrics/histogram_functions.h"
#include "base/numerics/ranges.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/scoped_window_targeter.h"
#include "ui/aura/window.h"
#include "ui/aura/window_targeter.h"
#include "ui/compositor/animation_metrics_reporter.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/display/display.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/painter.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/wm/core/visibility_controller.h"
#include "ui/wm/core/window_animations.h"

namespace ash {

namespace {

bool g_disable_initial_delay = false;

// Shield rounded corner radius
constexpr gfx::RoundedCornersF kBackgroundCornerRadius{4.f};

// Shield background blur sigma.
constexpr float kBackgroundBlurSigma =
    static_cast<float>(AshColorProvider::LayerBlurSigma::kBlurDefault);

// Quality of the shield background blur.
constexpr float kBackgroundBlurQuality = 0.33f;

// All previews are the same height (this is achieved via a combination of
// scaling and padding).
constexpr int kFixedPreviewHeightDp = 256;

// The min and max width for preview size are in relation to the fixed height.
constexpr int kMinPreviewWidthDp = kFixedPreviewHeightDp / 2;
constexpr int kMaxPreviewWidthDp = kFixedPreviewHeightDp * 2;

// Padding between the alt-tab bandshield and the window previews.
constexpr int kInsideBorderHorizontalPaddingDp = 64;
constexpr int kInsideBorderVerticalPaddingDp = 60;

// Padding between the window previews within the alt-tab bandshield.
constexpr int kBetweenChildPaddingDp = 10;

// The alt-tab cycler widget is not activatable (except when ChromeVox is on),
// so we use WindowTargeter to send input events to the widget.
class CustomWindowTargeter : public aura::WindowTargeter {
 public:
  explicit CustomWindowTargeter(aura::Window* tab_cycler)
      : tab_cycler_(tab_cycler) {}
  ~CustomWindowTargeter() override = default;

  // aura::WindowTargeter
  ui::EventTarget* FindTargetForEvent(ui::EventTarget* root,
                                      ui::Event* event) override {
    if (event->IsLocatedEvent())
      return aura::WindowTargeter::FindTargetForEvent(root, event);
    return tab_cycler_;
  }

 private:
  aura::Window* tab_cycler_;

  DISALLOW_COPY_AND_ASSIGN(CustomWindowTargeter);
};

// The UMA histogram that logs smoothness of the fade-in animation.
constexpr char kWindowCycleShowAnimationSmoothness[] =
    "Ash.WindowCycleView.AnimationSmoothness.Show";
// The UMA histogram that logs smoothness of the window container animation.
constexpr char kContainerAnimationSmoothness[] =
    "Ash.WindowCycleView.AnimationSmoothness.Container";

class WindowCycleAnimationMetricsReporter
    : public ui::AnimationMetricsReporter {
 public:
  explicit WindowCycleAnimationMetricsReporter(const char* name)
      : name_(name) {}
  ~WindowCycleAnimationMetricsReporter() override = default;
  WindowCycleAnimationMetricsReporter(
      const WindowCycleAnimationMetricsReporter&) = delete;
  WindowCycleAnimationMetricsReporter& operator=(
      const WindowCycleAnimationMetricsReporter&) = delete;

  // ui::AnimationMetricsReporter:
  void Report(int value) override {
    base::UmaHistogramPercentage(name_, value);
  }

 private:
  const std::string name_;
};

class WindowCycleAnimationObserver : public ui::LayerAnimationObserver {
 public:
  WindowCycleAnimationObserver()
      : animation_metrics_reporter_(
            std::make_unique<WindowCycleAnimationMetricsReporter>(
                kContainerAnimationSmoothness)) {}

  // ui::LayerAnimationObserver:
  void OnLayerAnimationStarted(ui::LayerAnimationSequence* sequence) override {}
  void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override {}
  void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override {}
  void OnLayerAnimationScheduled(
      ui::LayerAnimationSequence* sequence) override {
    sequence->SetAnimationMetricsReporter(animation_metrics_reporter_.get());
  }

  std::unique_ptr<WindowCycleAnimationMetricsReporter>
      animation_metrics_reporter_;
};

}  // namespace

// This view represents a single aura::Window by displaying a title and a
// thumbnail of the window's contents.
class WindowCycleItemView : public WindowMiniView {
 public:
  explicit WindowCycleItemView(aura::Window* window) : WindowMiniView(window) {
    SetShowPreview(/*show=*/true);
    UpdatePreviewRoundedCorners(/*show=*/true);
    SetFocusBehavior(FocusBehavior::ALWAYS);
    UpdateIconView();
  }
  ~WindowCycleItemView() override = default;

 private:
  // WindowMiniView:
  // Returns the size for the preview view, scaled to fit within the max bounds.
  // Scaling is always 1:1 and we only scale down, never up.
  gfx::Size GetPreviewViewSize() const override {
    gfx::Size preview_pref_size = preview_view()->GetPreferredSize();
    if (preview_pref_size.width() > kMaxPreviewWidthDp ||
        preview_pref_size.height() > kFixedPreviewHeightDp) {
      const float scale =
          std::min(kMaxPreviewWidthDp / float{preview_pref_size.width()},
                   kFixedPreviewHeightDp / float{preview_pref_size.height()});
      preview_pref_size =
          gfx::ScaleToFlooredSize(preview_pref_size, scale, scale);
    }

    return preview_pref_size;
  }

  // views::View:
  void Layout() override {
    WindowMiniView::Layout();

    // Show the backdrop if the preview view does not take up all the bounds
    // allocated for it.
    gfx::Rect preview_max_bounds = GetContentsBounds();
    preview_max_bounds.Subtract(GetHeaderBounds());
    const gfx::Rect preview_area_bounds = preview_view()->bounds();
    SetBackdropVisibility(preview_max_bounds.size() !=
                          preview_area_bounds.size());
  }

  gfx::Size CalculatePreferredSize() const override {
    // Previews can range in width from half to double of
    // |kFixedPreviewHeightDp|. Padding will be added to the sides to achieve
    // this if the preview is too narrow.
    // TODO(sammiequon): Investigate whether we can remove some of these
    // calculations and use the views framework to layout the children.
    gfx::Size preview_size = GetPreviewViewSize();

    // All previews are the same height (this may add padding on top and
    // bottom).
    preview_size.set_height(kFixedPreviewHeightDp);

    // Previews should never be narrower than half or wider than double their
    // fixed height.
    preview_size.set_width(base::ClampToRange(
        preview_size.width(), kMinPreviewWidthDp, kMaxPreviewWidthDp));

    const int margin = GetInsets().width();
    preview_size.Enlarge(margin, margin + WindowMiniView::kHeaderHeightDp);
    return preview_size;
  }

  DISALLOW_COPY_AND_ASSIGN(WindowCycleItemView);
};

// A view that shows a collection of windows the user can tab through.
class WindowCycleView : public views::WidgetDelegateView {
 public:
  explicit WindowCycleView(const WindowCycleList::WindowList& windows)
      : target_window_(nullptr),
        animation_metrics_reporter_(
            std::make_unique<WindowCycleAnimationMetricsReporter>(
                kWindowCycleShowAnimationSmoothness)) {
    DCHECK(!windows.empty());
    SetPaintToLayer();
    layer()->SetFillsBoundsOpaquely(false);
    layer()->SetMasksToBounds(true);
    layer()->SetOpacity(0.0);
    {
      ui::ScopedLayerAnimationSettings animate_fade(layer()->GetAnimator());
      animate_fade.SetAnimationMetricsReporter(
          animation_metrics_reporter_.get());
      animate_fade.SetTransitionDuration(
          base::TimeDelta::FromMilliseconds(100));
      layer()->SetOpacity(1.0);
    }

    mirror_container_ = AddChildView(std::make_unique<views::View>());
    views::BoxLayout* layout =
        mirror_container_->SetLayoutManager(std::make_unique<views::BoxLayout>(
            views::BoxLayout::Orientation::kHorizontal,
            gfx::Insets(kInsideBorderVerticalPaddingDp,
                        kInsideBorderHorizontalPaddingDp),
            kBetweenChildPaddingDp));
    layout->set_cross_axis_alignment(
        views::BoxLayout::CrossAxisAlignment::kStart);
    mirror_container_->SetPaintToLayer(ui::LAYER_SOLID_COLOR);
    mirror_container_->layer()->SetFillsBoundsOpaquely(false);
    SkColor background_color = AshColorProvider::Get()->GetBaseLayerColor(
        AshColorProvider::BaseLayerType::kTransparent80,
        AshColorProvider::AshColorMode::kDark);
    mirror_container_->layer()->SetColor(background_color);
    mirror_container_->layer()->SetBackgroundBlur(kBackgroundBlurSigma);
    mirror_container_->layer()->SetBackdropFilterQuality(
        kBackgroundBlurQuality);
    mirror_container_->layer()->AddCacheRenderSurfaceRequest();
    mirror_container_->layer()->SetName("windowCycleList/MirrorContainer");

    for (auto* window : windows) {
      // |mirror_container_| owns |view|. The |preview_view_| in |view| will
      // use trilinear filtering in InitLayerOwner().
      auto* view = mirror_container_->AddChildView(
          std::make_unique<WindowCycleItemView>(window));
      window_view_map_[window] = view;
    }

    // The insets in the WindowCycleItemView are coming from its border, which
    // paints the focus ring around the view when it is highlighted. Exclude the
    // insets such that the spacing between the contents of the views rather
    // than the views themselves is |kBetweenChildPaddingDp|.
    const gfx::Insets cycle_item_insets =
        window_view_map_.begin()->second->GetInsets();
    layout->set_between_child_spacing(kBetweenChildPaddingDp -
                                      cycle_item_insets.width());
  }

  ~WindowCycleView() override = default;

  void SetTargetWindow(aura::Window* target) {
    // Hide the focus border of the previous target window and show the focus
    // border of the new one.
    if (target_window_) {
      auto target_it = window_view_map_.find(target_window_);
      if (target_it != window_view_map_.end())
        target_it->second->UpdateBorderState(/*show=*/false);
    }
    target_window_ = target;
    auto target_it = window_view_map_.find(target_window_);
    if (target_it != window_view_map_.end())
      target_it->second->UpdateBorderState(/*show=*/true);

    if (GetWidget()) {
      Layout();
      if (target_window_)
        window_view_map_[target_window_]->RequestFocus();
    }
  }

  void HandleWindowDestruction(aura::Window* destroying_window,
                               aura::Window* new_target) {
    auto view_iter = window_view_map_.find(destroying_window);
    views::View* preview = view_iter->second;
    views::View* parent = preview->parent();
    DCHECK_EQ(mirror_container_, parent);
    window_view_map_.erase(view_iter);
    delete preview;
    // With one of its children now gone, we must re-layout
    // |mirror_container_|. This must happen before SetTargetWindow() to make
    // sure our own Layout() works correctly when it's calculating highlight
    // bounds.
    parent->Layout();
    SetTargetWindow(new_target);
  }

  void DestroyContents() {
    window_view_map_.clear();
    target_window_ = nullptr;
    RemoveAllChildViews(true);
  }

  // views::WidgetDelegateView overrides:
  gfx::Size CalculatePreferredSize() const override {
    return mirror_container_->GetPreferredSize();
  }

  void Layout() override {
    if (!target_window_ || bounds().IsEmpty())
      return;

    bool first_layout = mirror_container_->bounds().IsEmpty();
    // If |mirror_container_| has not yet been laid out, we must lay it and
    // its descendants out so that the calculations based on |target_view|
    // work properly.
    if (first_layout) {
      mirror_container_->SizeToPreferredSize();
      if (mirror_container_->GetPreferredSize().width() < width()) {
        mirror_container_->layer()->SetRoundedCornerRadius(
            kBackgroundCornerRadius);
      }
    }

    views::View* target_view = window_view_map_[target_window_];
    gfx::RectF target_bounds(target_view->GetLocalBounds());
    views::View::ConvertRectToTarget(target_view, mirror_container_,
                                     &target_bounds);
    gfx::Rect container_bounds(mirror_container_->GetPreferredSize());
    // Case one: the container is narrower than the screen. Center the
    // container.
    int x_offset = (width() - container_bounds.width()) / 2;
    if (x_offset < 0) {
      // Case two: the container is wider than the screen. Center the target
      // view by moving the list just enough to ensure the target view is in
      // the center.
      x_offset = width() / 2 - mirror_container_->GetMirroredXInView(
                                   target_bounds.CenterPoint().x());

      // However, the container must span the screen, i.e. the maximum x is 0
      // and the minimum for its right boundary is the width of the screen.
      x_offset = std::min(x_offset, 0);
      x_offset = std::max(x_offset, width() - container_bounds.width());
    }
    container_bounds.set_x(x_offset);
    mirror_container_->SetBoundsRect(container_bounds);

    // Enable animations only after the first Layout() pass.
    if (first_layout) {
      // The preview list animates bounds changes (other animatable properties
      // never change).
      ui::LayerAnimator* animator = ui::LayerAnimator::CreateImplicitAnimator();
      animator->AddObserver(&container_animation_observer_);
      mirror_container_->layer()->SetAnimator(animator);
    }
  }

  View* GetInitiallyFocusedView() override {
    return window_view_map_[target_window_];
  }

 private:
  std::map<aura::Window*, WindowCycleItemView*> window_view_map_;
  views::View* mirror_container_;
  aura::Window* target_window_;

  // Metric reporter for animation.
  const std::unique_ptr<WindowCycleAnimationMetricsReporter>
      animation_metrics_reporter_;

  WindowCycleAnimationObserver container_animation_observer_;

  DISALLOW_COPY_AND_ASSIGN(WindowCycleView);
};

WindowCycleList::WindowCycleList(const WindowList& windows)
    : windows_(windows) {
  if (!ShouldShowUi())
    Shell::Get()->mru_window_tracker()->SetIgnoreActivations(true);

  for (auto* window : windows_)
    window->AddObserver(this);

  if (ShouldShowUi()) {
    if (g_disable_initial_delay) {
      InitWindowCycleView();
    } else {
      show_ui_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(150),
                           this, &WindowCycleList::InitWindowCycleView);
    }
  }
}

WindowCycleList::~WindowCycleList() {
  if (!ShouldShowUi())
    Shell::Get()->mru_window_tracker()->SetIgnoreActivations(false);

  for (auto* window : windows_)
    window->RemoveObserver(this);

  if (cycle_ui_widget_)
    cycle_ui_widget_->Close();

  // |this| is responsible for notifying |cycle_view_| when windows are
  // destroyed. Since |this| is going away, clobber |cycle_view_|. Otherwise
  // there will be a race where a window closes after now but before the
  // Widget::Close() call above actually destroys |cycle_view_|. See
  // crbug.com/681207
  if (cycle_view_)
    cycle_view_->DestroyContents();

  // While the cycler widget is shown, the windows listed in the cycler is
  // marked as force-visible and don't contribute to occlusion. In order to
  // work occlusion calculation properly, we need to activate a window after
  // the widget has been destroyed. See b/138914552.
  if (!windows_.empty() && user_did_accept_) {
    auto* target_window = windows_[current_index_];
    SelectWindow(target_window);
  }
}

void WindowCycleList::Step(WindowCycleController::Direction direction) {
  if (windows_.empty())
    return;

  // When there is only one window, we should give feedback to the user. If
  // the window is minimized, we should also show it.
  if (windows_.size() == 1) {
    ::wm::AnimateWindow(windows_[0], ::wm::WINDOW_ANIMATION_TYPE_BOUNCE);
    SelectWindow(windows_[0]);
    return;
  }

  DCHECK(static_cast<size_t>(current_index_) < windows_.size());

  if (!cycle_view_ && current_index_ == 0) {
    // Special case the situation where we're cycling forward but the MRU
    // window is not active. This occurs when all windows are minimized. The
    // starting window should be the first one rather than the second.
    if (direction == WindowCycleController::FORWARD &&
        !wm::IsActiveWindow(windows_[0]))
      current_index_ = -1;
  }

  // We're in a valid cycle, so step forward or backward.
  current_index_ += direction == WindowCycleController::FORWARD ? 1 : -1;

  // Wrap to window list size.
  current_index_ = (current_index_ + windows_.size()) % windows_.size();
  DCHECK(windows_[current_index_]);

  if (ShouldShowUi()) {
    if (current_index_ > 1)
      InitWindowCycleView();

    if (cycle_view_)
      cycle_view_->SetTargetWindow(windows_[current_index_]);
  }
}

// static
void WindowCycleList::DisableInitialDelayForTesting() {
  g_disable_initial_delay = true;
}

void WindowCycleList::OnWindowDestroying(aura::Window* window) {
  window->RemoveObserver(this);

  WindowList::iterator i = std::find(windows_.begin(), windows_.end(), window);
  // TODO(oshima): Change this back to DCHECK once crbug.com/483491 is fixed.
  CHECK(i != windows_.end());
  int removed_index = static_cast<int>(i - windows_.begin());
  windows_.erase(i);
  if (current_index_ > removed_index ||
      current_index_ == static_cast<int>(windows_.size())) {
    current_index_--;
  }

  if (cycle_view_) {
    auto* new_target_window =
        windows_.empty() ? nullptr : windows_[current_index_];
    cycle_view_->HandleWindowDestruction(window, new_target_window);
    if (windows_.empty()) {
      // This deletes us.
      Shell::Get()->window_cycle_controller()->CancelCycling();
      return;
    }
  }
}

void WindowCycleList::OnDisplayMetricsChanged(const display::Display& display,
                                              uint32_t changed_metrics) {
  if (cycle_ui_widget_ &&
      display.id() ==
          display::Screen::GetScreen()
              ->GetDisplayNearestWindow(cycle_ui_widget_->GetNativeWindow())
              .id() &&
      (changed_metrics & (DISPLAY_METRIC_BOUNDS | DISPLAY_METRIC_ROTATION))) {
    Shell::Get()->window_cycle_controller()->CancelCycling();
    // |this| is deleted.
    return;
  }
}

bool WindowCycleList::ShouldShowUi() {
  return windows_.size() > 1;
}

void WindowCycleList::InitWindowCycleView() {
  if (cycle_view_)
    return;

  cycle_view_ = new WindowCycleView(windows_);
  cycle_view_->SetTargetWindow(windows_[current_index_]);

  // We need to activate the widget if ChromeVox is enabled as ChromeVox
  // relies on activation.
  const bool spoken_feedback_enabled =
      Shell::Get()->accessibility_controller()->spoken_feedback_enabled();

  views::Widget* widget = new views::Widget;
  views::Widget::InitParams params;
  params.delegate = cycle_view_;
  params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
  params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent;
  // Don't let the alt-tab cycler be activatable. This lets the currently
  // activated window continue to be in the foreground. This may affect
  // things such as video automatically pausing/playing.
  if (!spoken_feedback_enabled)
    params.activatable = views::Widget::InitParams::ACTIVATABLE_NO;
  params.accept_events = true;
  params.name = "WindowCycleList (Alt+Tab)";
  // TODO(estade): make sure nothing untoward happens when the lock screen
  // or a system modal dialog is shown.
  aura::Window* root_window = Shell::GetRootWindowForNewWindows();
  params.parent = root_window->GetChildById(kShellWindowId_OverlayContainer);
  gfx::Rect widget_rect = display::Screen::GetScreen()
                              ->GetDisplayNearestWindow(root_window)
                              .bounds();
  const int widget_height = cycle_view_->GetPreferredSize().height();
  widget_rect.set_y(widget_rect.y() +
                    (widget_rect.height() - widget_height) / 2);
  widget_rect.set_height(widget_height);
  params.bounds = widget_rect;
  widget->Init(std::move(params));

  screen_observer_.Add(display::Screen::GetScreen());
  widget->Show();
  cycle_ui_widget_ = widget;

  // Since this window is not activated, grab events.
  if (!spoken_feedback_enabled) {
    window_targeter_ = std::make_unique<aura::ScopedWindowTargeter>(
        widget->GetNativeWindow()->GetRootWindow(),
        std::make_unique<CustomWindowTargeter>(widget->GetNativeWindow()));
  }
  // Close the app list, if it's open in clamshell mode.
  if (!Shell::Get()->tablet_mode_controller()->InTabletMode())
    Shell::Get()->app_list_controller()->DismissAppList();
}

void WindowCycleList::SelectWindow(aura::Window* window) {
  // If the list has only one window, the window can be selected twice (in
  // Step() and the destructor). This causes ARC PIP windows to be restored
  // twice, which leads to a wrong window state.
  if (window_selected_)
    return;

  if (window->GetProperty(kPipOriginalWindowKey)) {
    window_util::ExpandArcPipWindow();
  } else {
    window->Show();
    WindowState::Get(window)->Activate();
  }

  window_selected_ = true;
}

}  // namespace ash
