// 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 "ash/magnifier/partial_magnification_controller.h"

#include "ash/shell.h"
#include "ash/system/palette/palette_utils.h"
#include "third_party/skia/include/core/SkDrawLooper.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_tree_host.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/paint_recorder.h"
#include "ui/events/event.h"
#include "ui/events/event_constants.h"
#include "ui/gfx/shadow_value.h"
#include "ui/gfx/skia_paint_util.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/core/coordinate_conversion.h"

namespace ash {
namespace {

// Ratio of magnifier scale.
const float kMagnificationScale = 2.f;
// Radius of the magnifying glass in DIP. This does not include the thickness
// of the magnifying glass shadow and border.
const int kMagnifierRadius = 188;
// Size of the border around the magnifying glass in DIP.
const int kBorderSize = 10;
// Thickness of the outline around magnifying glass border in DIP.
const int kBorderOutlineThickness = 1;
// Thickness of the shadow around the magnifying glass in DIP.
const int kShadowThickness = 24;
// Offset of the shadow around the magnifying glass in DIP. One of the shadows
// is lowered a bit, so we have to include |kShadowOffset| in our calculations
// to compensate.
const int kShadowOffset = 24;
// The color of the border and its outlines. The border has an outline on both
// sides, producing a black/white/black ring.
const SkColor kBorderColor = SkColorSetARGB(204, 255, 255, 255);
const SkColor kBorderOutlineColor = SkColorSetARGB(51, 0, 0, 0);
// The colors of the two shadow around the magnifiying glass.
const SkColor kTopShadowColor = SkColorSetARGB(26, 0, 0, 0);
const SkColor kBottomShadowColor = SkColorSetARGB(61, 0, 0, 0);
// Inset on the zoom filter.
const int kZoomInset = 0;
// Vertical offset between the center of the magnifier and the tip of the
// pointer. TODO(jdufault): The vertical offset should only apply to the window
// location, not the magnified contents. See crbug.com/637617.
const int kVerticalOffset = 0;

// Name of the magnifier window.
const char kPartialMagniferWindowName[] = "PartialMagnifierWindow";

gfx::Size GetWindowSize() {
  // The diameter of the window is the diameter of the magnifier, border and
  // shadow combined. We apply |kShadowOffset| on all sides even though the
  // shadow is only thicker on the bottom so as to keep the circle centered in
  // the view and keep calculations (border rendering and content masking)
  // simpler.
  int window_diameter =
      (kMagnifierRadius + kBorderSize + kShadowThickness + kShadowOffset) * 2;
  return gfx::Size(window_diameter, window_diameter);
}

gfx::Rect GetBounds(gfx::Point mouse) {
  gfx::Size size = GetWindowSize();
  gfx::Point origin(mouse.x() - (size.width() / 2),
                    mouse.y() - (size.height() / 2) - kVerticalOffset);
  return gfx::Rect(origin, size);
}

aura::Window* GetCurrentRootWindow() {
  aura::Window::Windows root_windows = ash::Shell::GetAllRootWindows();
  for (aura::Window* root_window : root_windows) {
    if (root_window->ContainsPointInRoot(
            root_window->GetHost()->dispatcher()->GetLastMouseLocationInRoot()))
      return root_window;
  }
  return nullptr;
}

}  // namespace

// The content mask provides a clipping layer for the magnification window so we
// can show a circular magnifier.
class PartialMagnificationController::ContentMask : public ui::LayerDelegate {
 public:
  // If |is_border| is true, the circle will be a stroke. This is useful if we
  // wish to clip a border.
  ContentMask(bool is_border, gfx::Size mask_bounds)
      : layer_(ui::LAYER_TEXTURED), is_border_(is_border) {
    layer_.set_delegate(this);
    layer_.SetFillsBoundsOpaquely(false);
    layer_.SetBounds(gfx::Rect(mask_bounds));
  }

  ~ContentMask() override { layer_.set_delegate(nullptr); }

  ui::Layer* layer() { return &layer_; }

 private:
  // ui::LayerDelegate:
  void OnPaintLayer(const ui::PaintContext& context) override {
    ui::PaintRecorder recorder(context, layer()->size());

    cc::PaintFlags flags;
    flags.setAlpha(255);
    flags.setAntiAlias(true);
    // Stroke is used for clipping the border which consists of the rendered
    // border |kBorderSize| and the magnifier shadow |kShadowThickness| and
    // |kShadowOffset|.
    flags.setStrokeWidth(kBorderSize + kShadowThickness + kShadowOffset);
    flags.setStyle(is_border_ ? cc::PaintFlags::kStroke_Style
                              : cc::PaintFlags::kFill_Style);

    // If we want to clip the magnifier zone use the magnifiers radius.
    // Otherwise we want to clip the border, shadow and shadow offset so we
    // start
    // at the halfway point of the stroke width.
    gfx::Rect rect(layer()->bounds().size());
    int clipping_radius = kMagnifierRadius;
    if (is_border_)
      clipping_radius += (kShadowThickness + kShadowOffset + kBorderSize) / 2;
    recorder.canvas()->DrawCircle(rect.CenterPoint(), clipping_radius, flags);
  }

  void OnDeviceScaleFactorChanged(float old_device_scale_factor,
                                  float new_device_scale_factor) override {
    // Redrawing will take care of scale factor change.
  }

  ui::Layer layer_;
  bool is_border_;
  DISALLOW_COPY_AND_ASSIGN(ContentMask);
};

// The border renderer draws the border as well as outline on both the outer and
// inner radius to increase visibility. The border renderer also handles drawing
// the shadow.
class PartialMagnificationController::BorderRenderer
    : public ui::LayerDelegate {
 public:
  explicit BorderRenderer(const gfx::Rect& window_bounds)
      : magnifier_window_bounds_(window_bounds) {
    magnifier_shadows_.push_back(gfx::ShadowValue(
        gfx::Vector2d(0, kShadowOffset), kShadowThickness, kBottomShadowColor));
    magnifier_shadows_.push_back(gfx::ShadowValue(
        gfx::Vector2d(0, 0), kShadowThickness, kTopShadowColor));
  }

  ~BorderRenderer() override = default;

 private:
  // ui::LayerDelegate:
  void OnPaintLayer(const ui::PaintContext& context) override {
    ui::PaintRecorder recorder(context, magnifier_window_bounds_.size());

    // Draw the shadow.
    cc::PaintFlags shadow_flags;
    shadow_flags.setAntiAlias(true);
    shadow_flags.setColor(SK_ColorTRANSPARENT);
    shadow_flags.setLooper(gfx::CreateShadowDrawLooper(magnifier_shadows_));
    gfx::Rect shadow_bounds(magnifier_window_bounds_.size());
    recorder.canvas()->DrawCircle(
        shadow_bounds.CenterPoint(),
        shadow_bounds.width() / 2 - kShadowThickness - kShadowOffset,
        shadow_flags);

    cc::PaintFlags border_flags;
    border_flags.setAntiAlias(true);
    border_flags.setStyle(cc::PaintFlags::kStroke_Style);

    // The radius of the magnifier and its border.
    const int magnifier_radius = kMagnifierRadius + kBorderSize;

    // Draw the inner border.
    border_flags.setStrokeWidth(kBorderSize);
    border_flags.setColor(kBorderColor);
    recorder.canvas()->DrawCircle(magnifier_window_bounds_.CenterPoint(),
                                  magnifier_radius - kBorderSize / 2,
                                  border_flags);

    // Draw border outer outline and then draw the border inner outline.
    border_flags.setStrokeWidth(kBorderOutlineThickness);
    border_flags.setColor(kBorderOutlineColor);
    recorder.canvas()->DrawCircle(
        magnifier_window_bounds_.CenterPoint(),
        magnifier_radius - kBorderOutlineThickness / 2, border_flags);
    recorder.canvas()->DrawCircle(
        magnifier_window_bounds_.CenterPoint(),
        magnifier_radius - kBorderSize + kBorderOutlineThickness / 2,
        border_flags);
  }

  void OnDeviceScaleFactorChanged(float old_device_scale_factor,
                                  float new_device_scale_factor) override {}

  gfx::Rect magnifier_window_bounds_;
  std::vector<gfx::ShadowValue> magnifier_shadows_;

  DISALLOW_COPY_AND_ASSIGN(BorderRenderer);
};

PartialMagnificationController::PartialMagnificationController() {
  Shell::Get()->AddPreTargetHandler(this);
}

PartialMagnificationController::~PartialMagnificationController() {
  CloseMagnifierWindow();

  Shell::Get()->RemovePreTargetHandler(this);
}

void PartialMagnificationController::SetEnabled(bool enabled) {
  is_enabled_ = enabled;
  SetActive(false);
}

void PartialMagnificationController::SwitchTargetRootWindowIfNeeded(
    aura::Window* new_root_window) {
  if (host_widget_ &&
      new_root_window == host_widget_->GetNativeView()->GetRootWindow())
    return;

  if (!new_root_window)
    new_root_window = GetCurrentRootWindow();

  if (is_enabled_ && is_active_) {
    CloseMagnifierWindow();
    CreateMagnifierWindow(new_root_window);
  }
}

void PartialMagnificationController::OnTouchEvent(ui::TouchEvent* event) {
  OnLocatedEvent(event, event->pointer_details());
}

void PartialMagnificationController::OnWindowDestroying(aura::Window* window) {
  CloseMagnifierWindow();

  aura::Window* new_root_window = GetCurrentRootWindow();
  if (new_root_window != window)
    SwitchTargetRootWindowIfNeeded(new_root_window);
}

void PartialMagnificationController::OnWidgetDestroying(views::Widget* widget) {
  DCHECK_EQ(widget, host_widget_);
  RemoveZoomWidgetObservers();
  host_widget_ = nullptr;
}

void PartialMagnificationController::SetActive(bool active) {
  // Fail if we're trying to activate while disabled.
  DCHECK(is_enabled_ || !active);

  is_active_ = active;
  if (is_active_) {
    CreateMagnifierWindow(GetCurrentRootWindow());
  } else {
    CloseMagnifierWindow();
  }
}

void PartialMagnificationController::OnLocatedEvent(
    ui::LocatedEvent* event,
    const ui::PointerDetails& pointer_details) {
  if (!is_enabled_)
    return;

  if (pointer_details.pointer_type != ui::EventPointerType::POINTER_TYPE_PEN)
    return;

  // Compute the event location in screen space.
  aura::Window* target = static_cast<aura::Window*>(event->target());
  aura::Window* event_root = target->GetRootWindow();
  gfx::Point screen_point = event->root_location();
  wm::ConvertPointToScreen(event_root, &screen_point);

  // If the stylus is pressed on the palette icon or widget, do not activate.
  if (event->type() == ui::ET_TOUCH_PRESSED &&
      !palette_utils::PaletteContainsPointInScreen(screen_point)) {
    SetActive(true);
  }

  if (event->type() == ui::ET_TOUCH_RELEASED)
    SetActive(false);

  if (!is_active_)
    return;

  // If the previous root window was detached host_widget_ will be null;
  // reconstruct it. We also need to change the root window if the cursor has
  // crossed display boundries.
  SwitchTargetRootWindowIfNeeded(GetCurrentRootWindow());

  // If that failed for any reason return.
  if (!host_widget_) {
    SetActive(false);
    return;
  }

  // Remap point from where it was captured to the display it is actually on.
  gfx::Point point = event->root_location();
  aura::Window::ConvertPointToTarget(
      event_root, host_widget_->GetNativeView()->GetRootWindow(), &point);
  host_widget_->SetBounds(GetBounds(point));

  // If the stylus is over the palette icon or widget, do not consume the event.
  if (!palette_utils::PaletteContainsPointInScreen(screen_point))
    event->StopPropagation();
}

void PartialMagnificationController::CreateMagnifierWindow(
    aura::Window* root_window) {
  if (host_widget_ || !root_window)
    return;

  root_window->AddObserver(this);

  gfx::Point mouse(
      root_window->GetHost()->dispatcher()->GetLastMouseLocationInRoot());

  host_widget_ = new views::Widget;
  views::Widget::InitParams params(
      views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
  params.activatable = views::Widget::InitParams::ACTIVATABLE_NO;
  params.accept_events = false;
  params.bounds = GetBounds(mouse);
  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
  params.parent = root_window;
  host_widget_->Init(params);
  host_widget_->set_focus_on_creation(false);
  host_widget_->Show();

  aura::Window* window = host_widget_->GetNativeView();
  window->SetName(kPartialMagniferWindowName);

  ui::Layer* root_layer = host_widget_->GetNativeView()->layer();

  zoom_layer_.reset(new ui::Layer(ui::LayerType::LAYER_SOLID_COLOR));
  zoom_layer_->SetBounds(gfx::Rect(GetWindowSize()));
  zoom_layer_->SetBackgroundZoom(kMagnificationScale, kZoomInset);
  root_layer->Add(zoom_layer_.get());

  border_layer_.reset(new ui::Layer(ui::LayerType::LAYER_TEXTURED));
  border_layer_->SetBounds(gfx::Rect(GetWindowSize()));
  border_renderer_.reset(new BorderRenderer(gfx::Rect(GetWindowSize())));
  border_layer_->set_delegate(border_renderer_.get());
  border_layer_->SetFillsBoundsOpaquely(false);
  root_layer->Add(border_layer_.get());

  border_mask_.reset(new ContentMask(true, GetWindowSize()));
  border_layer_->SetMaskLayer(border_mask_->layer());

  zoom_mask_.reset(new ContentMask(false, GetWindowSize()));
  zoom_layer_->SetMaskLayer(zoom_mask_->layer());

  host_widget_->AddObserver(this);
}

void PartialMagnificationController::CloseMagnifierWindow() {
  if (host_widget_) {
    RemoveZoomWidgetObservers();
    host_widget_->Close();
    host_widget_ = nullptr;
  }
}

void PartialMagnificationController::RemoveZoomWidgetObservers() {
  DCHECK(host_widget_);
  host_widget_->RemoveObserver(this);
  aura::Window* root_window = host_widget_->GetNativeView()->GetRootWindow();
  DCHECK(root_window);
  root_window->RemoveObserver(this);
}

}  // namespace ash
