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

#include <stdint.h>

#include <limits>

#include "ash/display/window_tree_host_manager.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/shell.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkPath.h"
#include "ui/aura/window.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/paint_recorder.h"
#include "ui/display/manager/display_manager.h"
#include "ui/display/manager/managed_display_info.h"
#include "ui/gfx/canvas.h"

namespace ash {
namespace {

// The opacity for the arrows of the overscan calibration.
const float kArrowOpacity = 0.8;

// The height in pixel for the arrows to show the overscan calibration.
const int kCalibrationArrowHeight = 70;

// The gap between the boundary and calibration arrows.
const int kArrowGapWidth = 0;

// Draw the arrow for the overscan calibration to |canvas|.
void DrawTriangle(int x_offset,
                  int y_offset,
                  double rotation_degree,
                  gfx::Canvas* canvas) {
  // Draw triangular arrows.
  cc::PaintFlags content_flags;
  content_flags.setStyle(cc::PaintFlags::kFill_Style);
  content_flags.setColor(SkColorSetA(
      SK_ColorBLACK, std::numeric_limits<uint8_t>::max() * kArrowOpacity));
  cc::PaintFlags border_flags;
  border_flags.setStyle(cc::PaintFlags::kStroke_Style);
  border_flags.setColor(SkColorSetA(
      SK_ColorWHITE, std::numeric_limits<uint8_t>::max() * kArrowOpacity));

  SkPath base_path;
  base_path.moveTo(0, 0);
  base_path.lineTo(SkIntToScalar(-kCalibrationArrowHeight),
                   SkIntToScalar(-kCalibrationArrowHeight));
  base_path.lineTo(SkIntToScalar(kCalibrationArrowHeight),
                   SkIntToScalar(-kCalibrationArrowHeight));
  base_path.close();

  SkPath path;
  gfx::Transform rotate_transform;
  rotate_transform.Rotate(rotation_degree);
  gfx::Transform move_transform;
  move_transform.Translate(x_offset, y_offset);
  rotate_transform.ConcatTransform(move_transform);
  base_path.transform(rotate_transform.matrix(), &path);

  canvas->DrawPath(path, content_flags);
  canvas->DrawPath(path, border_flags);
}

}  // namespace

OverscanCalibrator::OverscanCalibrator(const display::Display& target_display,
                                       const gfx::Insets& initial_insets)
    : display_(target_display),
      insets_(initial_insets),
      initial_insets_(initial_insets),
      committed_(false) {
  // Undo the overscan calibration temporarily so that the user can see
  // dark boundary and current overscan region.
  ash::Shell::Get()->window_tree_host_manager()->SetOverscanInsets(
      display_.id(), gfx::Insets());

  display::ManagedDisplayInfo info =
      ash::Shell::Get()->display_manager()->GetDisplayInfo(display_.id());

  aura::Window* root = ash::Shell::GetRootWindowForDisplayId(display_.id());
  ui::Layer* parent_layer =
      ash::Shell::GetContainer(root, ash::kShellWindowId_OverlayContainer)
          ->layer();

  calibration_layer_.reset(new ui::Layer());
  calibration_layer_->SetOpacity(0.5f);
  calibration_layer_->SetBounds(parent_layer->bounds());
  calibration_layer_->set_delegate(this);
  parent_layer->Add(calibration_layer_.get());
}

OverscanCalibrator::~OverscanCalibrator() {
  // Overscan calibration has finished without commit, so the display has to
  // be the original offset.
  if (!committed_) {
    ash::Shell::Get()->window_tree_host_manager()->SetOverscanInsets(
        display_.id(), initial_insets_);
  }
}

void OverscanCalibrator::Commit() {
  ash::Shell::Get()->window_tree_host_manager()->SetOverscanInsets(
      display_.id(), insets_);
  committed_ = true;
}

void OverscanCalibrator::Reset() {
  insets_ = initial_insets_;
  calibration_layer_->SchedulePaint(calibration_layer_->bounds());
}

void OverscanCalibrator::UpdateInsets(const gfx::Insets& insets) {
  insets_.Set(std::max(insets.top(), 0), std::max(insets.left(), 0),
              std::max(insets.bottom(), 0), std::max(insets.right(), 0));
  calibration_layer_->SchedulePaint(calibration_layer_->bounds());
}

void OverscanCalibrator::OnPaintLayer(const ui::PaintContext& context) {
  ui::PaintRecorder recorder(context, calibration_layer_->size());
  static const SkColor kTransparent = SkColorSetARGB(0, 0, 0, 0);
  gfx::Rect full_bounds = calibration_layer_->bounds();
  gfx::Rect inner_bounds = full_bounds;
  inner_bounds.Inset(insets_);
  recorder.canvas()->FillRect(full_bounds, SK_ColorBLACK);
  recorder.canvas()->FillRect(inner_bounds, kTransparent, SkBlendMode::kClear);

  gfx::Point center = inner_bounds.CenterPoint();
  int vertical_offset = inner_bounds.height() / 2 - kArrowGapWidth;
  int horizontal_offset = inner_bounds.width() / 2 - kArrowGapWidth;

  gfx::Canvas* canvas = recorder.canvas();
  DrawTriangle(center.x(), center.y() + vertical_offset, 0, canvas);
  DrawTriangle(center.x(), center.y() - vertical_offset, 180, canvas);
  DrawTriangle(center.x() - horizontal_offset, center.y(), 90, canvas);
  DrawTriangle(center.x() + horizontal_offset, center.y(), -90, canvas);
}

void OverscanCalibrator::OnDeviceScaleFactorChanged(
    float old_device_scale_factor,
    float new_device_scale_factor) {
  // TODO(mukai): Cancel the overscan calibration when the device
  // configuration has changed.
}

}  // namespace ash
