// 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/accessibility/accessibility_focus_ring_controller.h"

#include <stddef.h>

#include <algorithm>
#include <memory>
#include <set>
#include <utility>
#include <vector>

#include "ash/accessibility/accessibility_cursor_ring_layer.h"
#include "ash/accessibility/accessibility_focus_ring_group.h"
#include "ash/accessibility/accessibility_focus_ring_layer.h"
#include "ash/accessibility/accessibility_highlight_layer.h"
#include "ash/accessibility/focus_ring_layer.h"
#include "ash/accessibility/layer_animation_info.h"
#include "base/logging.h"

namespace ash {

namespace {

// Cursor constants.
constexpr int kCursorFadeInTimeMilliseconds = 400;
constexpr int kCursorFadeOutTimeMilliseconds = 1200;
constexpr int kCursorRingColorRed = 255;
constexpr int kCursorRingColorGreen = 51;
constexpr int kCursorRingColorBlue = 51;

// Caret constants.
constexpr int kCaretFadeInTimeMilliseconds = 100;
constexpr int kCaretFadeOutTimeMilliseconds = 1600;
constexpr int kCaretRingColorRed = 51;
constexpr int kCaretRingColorGreen = 51;
constexpr int kCaretRingColorBlue = 255;

// Highlight constants.
constexpr float kHighlightOpacity = 0.3f;

}  // namespace

AccessibilityFocusRingController::AccessibilityFocusRingController()
    : binding_(this) {
  cursor_animation_info_.fade_in_time =
      base::TimeDelta::FromMilliseconds(kCursorFadeInTimeMilliseconds);
  cursor_animation_info_.fade_out_time =
      base::TimeDelta::FromMilliseconds(kCursorFadeOutTimeMilliseconds);
  caret_animation_info_.fade_in_time =
      base::TimeDelta::FromMilliseconds(kCaretFadeInTimeMilliseconds);
  caret_animation_info_.fade_out_time =
      base::TimeDelta::FromMilliseconds(kCaretFadeOutTimeMilliseconds);
}

AccessibilityFocusRingController::~AccessibilityFocusRingController() = default;

void AccessibilityFocusRingController::BindRequest(
    mojom::AccessibilityFocusRingControllerRequest request) {
  binding_.Bind(std::move(request));
}

void AccessibilityFocusRingController::SetFocusRing(
    const std::string& focus_ring_id,
    mojom::FocusRingPtr focus_ring) {
  AccessibilityFocusRingGroup* focus_ring_group =
      GetFocusRingGroupForId(focus_ring_id, true /* Create if missing */);

  if (focus_ring_group->UpdateFocusRing(std::move(focus_ring), this))
    OnLayerChange(focus_ring_group->focus_animation_info());
}

void AccessibilityFocusRingController::HideFocusRing(
    const std::string& focus_ring_id) {
  AccessibilityFocusRingGroup* focus_ring_group =
      GetFocusRingGroupForId(focus_ring_id, false /* Do not create */);
  if (!focus_ring_group)
    return;
  focus_ring_group->ClearFocusRects(this);
  OnLayerChange(focus_ring_group->focus_animation_info());
}

void AccessibilityFocusRingController::SetHighlights(
    const std::vector<gfx::Rect>& rects,
    SkColor color) {
  highlight_rects_ = rects;
  GetColorAndOpacityFromColor(color, kHighlightOpacity, &highlight_color_,
                              &highlight_opacity_);
  UpdateHighlightFromHighlightRects();
}

void AccessibilityFocusRingController::HideHighlights() {
  highlight_rects_.clear();
  UpdateHighlightFromHighlightRects();
}

void AccessibilityFocusRingController::UpdateHighlightFromHighlightRects() {
  if (!highlight_layer_)
    highlight_layer_ = std::make_unique<AccessibilityHighlightLayer>(this);
  highlight_layer_->Set(highlight_rects_, highlight_color_);
  highlight_layer_->SetOpacity(highlight_opacity_);
}

void AccessibilityFocusRingController::OnLayerChange(
    LayerAnimationInfo* animation_info) {
  animation_info->change_time = base::TimeTicks::Now();
  if (animation_info->opacity == 0)
    animation_info->start_time = animation_info->change_time;
}

void AccessibilityFocusRingController::SetCursorRing(
    const gfx::Point& location) {
  cursor_location_ = location;
  if (!cursor_layer_) {
    cursor_layer_.reset(new AccessibilityCursorRingLayer(
        this, kCursorRingColorRed, kCursorRingColorGreen,
        kCursorRingColorBlue));
  }
  cursor_layer_->Set(location);
  OnLayerChange(&cursor_animation_info_);
}

void AccessibilityFocusRingController::HideCursorRing() {
  cursor_layer_.reset();
}

void AccessibilityFocusRingController::SetCaretRing(
    const gfx::Point& location) {
  caret_location_ = location;

  if (!caret_layer_) {
    caret_layer_.reset(new AccessibilityCursorRingLayer(
        this, kCaretRingColorRed, kCaretRingColorGreen, kCaretRingColorBlue));
  }

  caret_layer_->Set(location);
  OnLayerChange(&caret_animation_info_);
}

void AccessibilityFocusRingController::HideCaretRing() {
  caret_layer_.reset();
}

void AccessibilityFocusRingController::SetNoFadeForTesting() {
  no_fade_for_testing_ = true;
  for (auto iter = focus_ring_groups_.begin(); iter != focus_ring_groups_.end();
       ++iter) {
    iter->second->set_no_fade_for_testing();
    iter->second->focus_animation_info()->fade_in_time = base::TimeDelta();
    iter->second->focus_animation_info()->fade_out_time =
        base::TimeDelta::FromHours(1);
  }
  cursor_animation_info_.fade_in_time = base::TimeDelta();
  cursor_animation_info_.fade_out_time = base::TimeDelta::FromHours(1);
  caret_animation_info_.fade_in_time = base::TimeDelta();
  caret_animation_info_.fade_out_time = base::TimeDelta::FromHours(1);
}

const AccessibilityFocusRingGroup*
AccessibilityFocusRingController::GetFocusRingGroupForTesting(
    const std::string& focus_ring_id) {
  return GetFocusRingGroupForId(focus_ring_id, false /* create if missing */);
}

void AccessibilityFocusRingController::GetColorAndOpacityFromColor(
    SkColor color,
    float default_opacity,
    SkColor* result_color,
    float* result_opacity) {
  int alpha = SkColorGetA(color);
  if (alpha == 0xFF) {
    *result_opacity = default_opacity;
  } else {
    *result_opacity = SkColor4f::FromColor(color).fA;
  }
  *result_color = SkColorSetA(color, 0xFF);
}

void AccessibilityFocusRingController::OnDeviceScaleFactorChanged() {
  for (auto iter = focus_ring_groups_.begin(); iter != focus_ring_groups_.end();
       ++iter)
    iter->second->UpdateFocusRingsFromInfo(this);
}

void AccessibilityFocusRingController::OnAnimationStep(
    base::TimeTicks timestamp) {
  for (auto iter = focus_ring_groups_.begin(); iter != focus_ring_groups_.end();
       ++iter) {
    if (iter->second->CanAnimate())
      iter->second->AnimateFocusRings(timestamp);
  }

  if (cursor_layer_ && cursor_layer_->CanAnimate())
    AnimateCursorRing(timestamp);

  if (caret_layer_ && caret_layer_->CanAnimate())
    AnimateCaretRing(timestamp);
}

void AccessibilityFocusRingController::AnimateCursorRing(
    base::TimeTicks timestamp) {
  CHECK(cursor_layer_);

  ComputeOpacity(&cursor_animation_info_, timestamp);
  if (cursor_animation_info_.opacity == 0.0) {
    cursor_layer_.reset();
    return;
  }
  cursor_layer_->SetOpacity(cursor_animation_info_.opacity);
}

void AccessibilityFocusRingController::AnimateCaretRing(
    base::TimeTicks timestamp) {
  CHECK(caret_layer_);

  ComputeOpacity(&caret_animation_info_, timestamp);
  if (caret_animation_info_.opacity == 0.0) {
    caret_layer_.reset();
    return;
  }
  caret_layer_->SetOpacity(caret_animation_info_.opacity);
}

AccessibilityFocusRingGroup*
AccessibilityFocusRingController::GetFocusRingGroupForId(
    const std::string& focus_ring_id,
    bool create) {
  auto iter = focus_ring_groups_.find(focus_ring_id);
  if (iter != focus_ring_groups_.end())
    return iter->second.get();

  if (!create)
    return nullptr;

  // Add it and then return it.
  focus_ring_groups_[focus_ring_id] =
      std::make_unique<AccessibilityFocusRingGroup>();
  if (no_fade_for_testing_)
    SetNoFadeForTesting();

  return focus_ring_groups_[focus_ring_id].get();
}

}  // namespace ash
