// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/views/find_bar_host.h"

#include <algorithm>

#include "base/check_is_test.h"
#include "base/i18n/rtl.h"
#include "build/build_config.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/find_bar/find_bar_controller.h"
#include "chrome/browser/ui/view_ids.h"
#include "chrome/browser/ui/views/find_bar_view.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/theme_copying_widget.h"
#include "components/find_in_page/find_tab_helper.h"
#include "components/find_in_page/find_types.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_user_data.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/compositor/layer.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/animation/slide_animation.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/views/border.h"
#include "ui/views/focus/external_focus_tracker.h"
#include "ui/views/widget/root_view.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"

#if BUILDFLAG(IS_WIN)
#include <windows.h>
#endif

#if defined(IS_AURA)
#include "ui/aura/window.h"
#include "ui/views/view_constants_aura.h"
#endif

using input::NativeWebKeyboardEvent;

namespace {

class FindBarHostHelper
    : public content::WebContentsUserData<FindBarHostHelper> {
 public:
  static FindBarHostHelper* CreateOrGetFromWebContents(
      content::WebContents* web_contents) {
    CreateForWebContents(web_contents);
    return FromWebContents(web_contents);
  }

  void SetExternalFocusTracker(
      std::unique_ptr<views::ExternalFocusTracker> external_focus_tracker) {
    external_focus_tracker_ = std::move(external_focus_tracker);
  }

  std::unique_ptr<views::ExternalFocusTracker> TakeExternalFocusTracker() {
    return std::move(external_focus_tracker_);
  }

  views::ExternalFocusTracker* focus_tracker() {
    return external_focus_tracker_.get();
  }

 private:
  friend class content::WebContentsUserData<FindBarHostHelper>;

  explicit FindBarHostHelper(content::WebContents* web_contents)
      : content::WebContentsUserData<FindBarHostHelper>(*web_contents) {}

  std::unique_ptr<views::ExternalFocusTracker> external_focus_tracker_;

  WEB_CONTENTS_USER_DATA_KEY_DECL();
};

WEB_CONTENTS_USER_DATA_KEY_IMPL(FindBarHostHelper);

gfx::Rect GetLocationForFindBarView(gfx::Rect view_location,
                                    const gfx::Rect& clipping_box,
                                    const gfx::Rect& avoid_overlapping_rect) {
  // Clamp to the `clipping_box`.
  view_location.set_width(
      std::min(view_location.width(), clipping_box.width()));
  if (base::i18n::IsRTL()) {
    int boundary = clipping_box.width() - view_location.width();
    view_location.set_x(std::min(view_location.x(), boundary));
  } else {
    view_location.set_x(std::max(view_location.x(), clipping_box.x()));
  }

  gfx::Rect new_pos = view_location;

  // The minimum space between the FindInPage window and the search result.
  constexpr int kMinFindWndDistanceFromSelection = 5;

  // If the selection rectangle intersects the current position on screen then
  // we try to move our dialog to the left (right for RTL) of the selection
  // rectangle.
  if (!avoid_overlapping_rect.IsEmpty() &&
      avoid_overlapping_rect.Intersects(new_pos)) {
    if (base::i18n::IsRTL()) {
      new_pos.set_x(avoid_overlapping_rect.x() +
                    avoid_overlapping_rect.width() +
                    (2 * kMinFindWndDistanceFromSelection));

      // If we moved it to be clipped on the right, we won't move it at all.
      if (new_pos.x() + new_pos.width() > clipping_box.width()) {
        new_pos = view_location;  // Reset.
      }
    } else {
      new_pos.set_x(avoid_overlapping_rect.x() - new_pos.width() -
                    kMinFindWndDistanceFromSelection);

      // If we moved it off-screen to the left, we won't move it at all.
      if (new_pos.x() < 0) {
        new_pos = view_location;  // Reset.
      }
    }
  }

  return new_pos;
}

// During testing we can disable animations by setting this flag to true,
// so that opening and closing the dropdown bar is shown instantly, instead of
// having to poll it while it animates to open/closed status.
// TODO(https://crbug.com/40183900): Make this private and push disabling for
// testing into here instead of `find_bar_host_unittest_util`.
static bool kDisableAnimationsForTesting = false;

}  // namespace

////////////////////////////////////////////////////////////////////////////////
// FindBarHost, public:

FindBarHost::FindBarHost(FindBarOwner* find_bar_owner)
    : AnimationDelegateViews(find_bar_owner->GetOwnerWidget()),
      find_bar_owner_(find_bar_owner) {
  auto find_bar_view = std::make_unique<FindBarView>(this);
  // The |clip_view| exists to paint to a layer so that it can clip descendent
  // Views which also paint to a Layer. See http://crbug.com/589497
  auto clip_view = std::make_unique<views::View>();
  clip_view->SetPaintToLayer();
  clip_view->layer()->SetFillsBoundsOpaquely(false);
  clip_view->layer()->SetMasksToBounds(true);
  view_ = clip_view->AddChildView(std::move(find_bar_view));

  // Initialize the host.
  host_ =
      std::make_unique<ThemeCopyingWidget>(find_bar_owner_->GetOwnerWidget());
  views::Widget::InitParams params(
      views::Widget::InitParams::CLIENT_OWNS_WIDGET,
      views::Widget::InitParams::TYPE_CONTROL);
  params.delegate = this;
  params.name = "FindBarHost";
  params.parent = find_bar_owner_->GetWidgetForAnchoring()->GetNativeView();
  params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent;
#if BUILDFLAG(IS_MAC)
  params.activatable = views::Widget::InitParams::Activatable::kYes;
#endif
  host_->Init(std::move(params));
  host_->SetContentsView(std::move(clip_view));
#if defined(IS_AURA)
  host_->GetNativeView()->SetProperty(views::kHostViewKey,
                                      browser_view->find_bar_host_view());
#endif

  // Start listening to focus changes, so we can register and unregister our
  // own handler for Escape.
  focus_manager_ = host_->GetFocusManager();
  focus_manager_observation_.Observe(focus_manager_.get());

  animation_ = std::make_unique<gfx::SlideAnimation>(this);
  if (!gfx::Animation::ShouldRenderRichAnimation()) {
    animation_->SetSlideDuration(base::TimeDelta());
  }

  // Update the widget and |view_| bounds to the hidden state.
  AnimationProgressed(animation_.get());
  SetAccessibleWindowRole(ax::mojom::Role::kDialog);
}

FindBarHost::~FindBarHost() {
  focus_tracker_.reset();
}

bool FindBarHost::MaybeForwardKeyEventToWebpage(const ui::KeyEvent& key_event) {
  switch (key_event.key_code()) {
    case ui::VKEY_DOWN:
    case ui::VKEY_UP:
    case ui::VKEY_PRIOR:
    case ui::VKEY_NEXT:
      break;
    case ui::VKEY_HOME:
    case ui::VKEY_END:
      if (key_event.IsControlDown()) {
        break;
      }
      [[fallthrough]];
    default:
      return false;
  }

  if (!web_contents()) {
    return false;
  }

  // Make sure we don't have a text field element interfering with keyboard
  // input. Otherwise Up and Down arrow key strokes get eaten. "Nom Nom Nom".
  web_contents()->ClearFocusedElement();
  NativeWebKeyboardEvent event(key_event);
  web_contents()
      ->GetPrimaryMainFrame()
      ->GetRenderViewHost()
      ->GetWidget()
      ->ForwardKeyboardEventWithLatencyInfo(event, *key_event.latency());
  return true;
}

bool FindBarHost::IsVisible() const {
  return is_visible_;
}

#if BUILDFLAG(IS_MAC)
views::Widget* FindBarHost::GetHostWidget() {
  return host_.get();
}
#endif

FindBarController* FindBarHost::GetFindBarController() const {
  return find_bar_controller_;
}

bool FindBarHost::HasFocus() const {
  return view_->ContainsFocus();
}

void FindBarHost::SetFindBarController(FindBarController* find_bar_controller) {
  find_bar_controller_ = find_bar_controller;

  if (GetWidget()) {
    GetWidget()->UpdateAccessibleNameForRootView();
  }
}

void FindBarHost::Show(bool animate, bool focus) {
  RestoreOrCreateFocusTracker();
  DCHECK(host_);

  SetDialogPosition(GetDialogPosition(gfx::Rect()));

  // If we're in the middle of a close animation, stop it and skip to the end.
  // This ensures that the state is consistent and prepared to show the drop-
  // down bar.
  if (animation_->IsClosing()) {
    animation_->End();
  }

  if (focus) {
    host_->Show();
  } else {
    host_->ShowInactive();
  }

  bool was_visible = is_visible_;
  is_visible_ = true;
  if (!animate || kDisableAnimationsForTesting) {
    animation_->Reset(1);
    AnimationProgressed(animation_.get());
  } else if (!was_visible) {
    // Don't re-start the animation.
    animation_->Reset();
    animation_->Show();
  }

  if (!was_visible) {
    OnVisibilityChanged();
  }
}

void FindBarHost::Hide(bool animate) {
  // Restore/Save is non-symmetric as hiding the FindBarHost could change
  // the focus state of the external view. Saving the focus tracker before the
  // hide preserves the appropriate view in the event the FindBarHost visibility
  // is restored as part of a tab change.
  SaveFocusTracker();
  if (!is_visible_) {
    return;
  }

  if (animate && !kDisableAnimationsForTesting && !animation_->IsClosing()) {
    animation_->Hide();
  } else {
    if (animation_->IsClosing()) {
      // If we're in the middle of a close animation, skip immediately to the
      // end of the animation.
      animation_->End();
    } else {
      // Otherwise we need to set both the animation state to ended and the
      // DropdownBarHost state to ended/hidden, otherwise the next time we try
      // to show the bar, it might refuse to do so. Note that we call
      // AnimationEnded ourselves as Reset does not call it if we are not
      // animating here.
      animation_->Reset();
      AnimationEnded(animation_.get());
    }
  }
}

void FindBarHost::SetFocusAndSelection() {
  view_->FocusAndSelectAll();
  SetFindBarIsFocusedOnCurrentTab(true);
}

void FindBarHost::ClearResults(
    const find_in_page::FindNotificationDetails& results) {
  view_->UpdateForResult(results, std::u16string());
}

void FindBarHost::StopAnimation() {
  animation_->End();
}

void FindBarHost::MoveWindowIfNecessary() {
  MoveWindowIfNecessaryWithRect(gfx::Rect());
}

void FindBarHost::SetFindTextAndSelectedRange(
    const std::u16string& find_text,
    const gfx::Range& selected_range) {
  view_->SetFindTextAndSelectedRange(find_text, selected_range);
}

std::u16string_view FindBarHost::GetFindText() const {
  return view_->GetFindText();
}

gfx::Range FindBarHost::GetSelectedRange() const {
  return view_->GetSelectedRange();
}

void FindBarHost::UpdateUIForFindResult(
    const find_in_page::FindNotificationDetails& result,
    const std::u16string& find_text) {
  if (!find_text.empty()) {
    view_->UpdateForResult(result, find_text);
  } else {
    view_->ClearMatchCount();
  }

  // We now need to check if the window is obscuring the search results.
  MoveWindowIfNecessaryWithRect(result.selection_rect());

  // Once we find a match we no longer want to keep track of what had
  // focus. EndFindSession will then set the focus to the page content.
  if (result.number_of_matches() > 0) {
    focus_tracker_.reset();
  }
}

void FindBarHost::AudibleAlert() {
  ++audible_alerts_;
#if BUILDFLAG(IS_WIN)
  MessageBeep(MB_OK);
#endif
}

bool FindBarHost::IsFindBarVisible() const {
  return is_visible_;
}

void FindBarHost::RestoreSavedFocus() {
  SetFindBarIsFocusedOnCurrentTab(false);

  std::unique_ptr<views::ExternalFocusTracker> focus_tracker_from_web_contents;
  views::ExternalFocusTracker* tracker = focus_tracker_.get();
  if (!tracker && web_contents()) {
    auto* helper = FindBarHostHelper::FromWebContents(web_contents());
    if (helper) {
      focus_tracker_from_web_contents = helper->TakeExternalFocusTracker();
      tracker = focus_tracker_from_web_contents.get();
    }
  }

  if (tracker) {
    tracker->FocusLastFocusedExternalView();
    focus_tracker_.reset();
  } else {
    // TODO(brettw): Focus() should be on WebContentsView.
    web_contents()->Focus();
  }
}

bool FindBarHost::HasGlobalFindPasteboard() const {
#if BUILDFLAG(IS_MAC)
  return true;
#else
  return false;
#endif
}

void FindBarHost::UpdateFindBarForChangedWebContents() {
  if (GetWidget()) {
    GetWidget()->UpdateAccessibleNameForRootView();
  }
}

const FindBarTesting* FindBarHost::GetFindBarTesting() const {
  return this;
}

////////////////////////////////////////////////////////////////////////////////
// FindBarWin, ui::AcceleratorTarget implementation:

bool FindBarHost::AcceleratorPressed(const ui::Accelerator& accelerator) {
  ui::KeyboardCode key = accelerator.key_code();
  if (key == ui::VKEY_RETURN && accelerator.IsCtrlDown()) {
    // Ctrl+Enter closes the Find session and navigates any link that is active.
    find_bar_controller_->EndFindSession(
        find_in_page::SelectionAction::kActivate,
        find_in_page::ResultAction::kClear);
    return true;
  }

  CHECK_EQ(key, ui::VKEY_ESCAPE);
  // This will end the Find session and hide the window, causing it to loose
  // focus and in the process unregister us as the handler for the Escape
  // accelerator through the OnWillChangeFocus event.
  find_bar_controller_->EndFindSession(find_in_page::SelectionAction::kKeep,
                                       find_in_page::ResultAction::kKeep);
  return true;
}

bool FindBarHost::CanHandleAccelerators() const {
  return true;
}

////////////////////////////////////////////////////////////////////////////////
// FindBarTesting implementation:

bool FindBarHost::GetFindBarWindowInfo(gfx::Point* position,
                                       bool* fully_visible) const {
  if (!find_bar_controller_) {
    if (position) {
      *position = gfx::Point();
    }
    if (fully_visible) {
      *fully_visible = false;
    }
    return false;
  }

  gfx::Rect window_rect = host_->GetWindowBoundsInScreen();
  if (position) {
    *position = window_rect.origin();
  }
  if (fully_visible) {
    *fully_visible = is_visible_ && !animation_->is_animating();
  }
  return true;
}

std::u16string_view FindBarHost::GetFindSelectedText() const {
  return view_->GetFindSelectedText();
}

std::u16string_view FindBarHost::GetMatchCountText() const {
  return view_->GetMatchCountText();
}

int FindBarHost::GetContentsWidth() const {
  return view_->GetContentsBounds().width();
}

size_t FindBarHost::GetAudibleAlertCount() const {
  return audible_alerts_;
}

std::u16string FindBarHost::GetAccessibleWindowTitle() const {
  // This can be called in tests by AccessibilityChecker before the controller
  // is registered with this object. So to handle that case, we need to bail out
  // if there is no controller.
  const FindBarController* const controller = GetFindBarController();
  if (!controller) {
    return std::u16string();
  }
  return find_bar_owner_->GetFindBarAccessibleWindowTitle();
}

FindBarView* FindBarHost::GetFindBarViewForTesting() {
  CHECK_IS_TEST();
  return view_;
}

void FindBarHost::SetEnableAnimationsForTesting(bool enable_animations) {
  CHECK_IS_TEST();
  kDisableAnimationsForTesting = !enable_animations;
}
////////////////////////////////////////////////////////////////////////////////
// private:

void FindBarHost::GetWidgetPositionNative(gfx::Rect* avoid_overlapping_rect) {
  gfx::Rect frame_rect = host_->GetTopLevelWidget()->GetWindowBoundsInScreen();
  gfx::Rect webcontents_rect = web_contents()->GetViewBounds();
  avoid_overlapping_rect->Offset(0, webcontents_rect.y() - frame_rect.y());
}

void FindBarHost::MoveWindowIfNecessaryWithRect(
    const gfx::Rect& selection_rect) {
  // We only move the window if one is active for the current WebContents. If we
  // don't check this, then SetDialogPosition below will end up making the Find
  // Bar visible.
  if (!web_contents()) {
    return;
  }

  find_in_page::FindTabHelper* find_tab_helper =
      find_in_page::FindTabHelper::FromWebContents(web_contents());
  if (!find_tab_helper || !find_tab_helper->find_ui_active()) {
    return;
  }

  gfx::Rect new_pos = GetDialogPosition(selection_rect);
  SetDialogPosition(new_pos);

  // May need to redraw our frame to accommodate bookmark bar styles.
  view_->DeprecatedLayoutImmediately();  // Bounds may have changed.
  view_->SchedulePaint();
}

void FindBarHost::SaveFocusTracker() {
  if (!web_contents()) {
    return;
  }

  if (focus_tracker_) {
    focus_tracker_->SetFocusManager(nullptr);
    FindBarHostHelper::CreateOrGetFromWebContents(web_contents())
        ->SetExternalFocusTracker(std::move(focus_tracker_));
  }
}

void FindBarHost::RestoreOrCreateFocusTracker() {
  if (!web_contents()) {
    return;
  }

  std::unique_ptr<views::ExternalFocusTracker> focus_tracker =
      FindBarHostHelper::CreateOrGetFromWebContents(web_contents())
          ->TakeExternalFocusTracker();
  if (focus_tracker) {
    focus_tracker_ = std::move(focus_tracker);
    focus_tracker_->SetFocusManager(host_->GetFocusManager());
  } else {
    focus_tracker_ =
        std::make_unique<views::ExternalFocusTracker>(view_, focus_manager_);
  }
}

void FindBarHost::SetFindBarIsFocusedOnCurrentTab(bool focus) {
  if (web_contents()) {
    find_in_page::FindTabHelper::FromWebContents(web_contents())
        ->set_find_ui_focused(focus);
  }
}

void FindBarHost::OnVisibilityChanged() {
  // Tell the immersive mode controller about the find bar's bounds. The
  // immersive mode controller uses the bounds to keep the top-of-window views
  // revealed when the mouse is hovered over the find bar.
  gfx::Rect visible_bounds;
  if (is_visible_) {
    visible_bounds = host_->GetWindowBoundsInScreen();
  }
  find_bar_owner_->OnFindBarVisibilityChanged(visible_bounds);
}

void FindBarHost::RegisterAccelerators() {
  DCHECK(!esc_accel_target_registered_);
  ui::Accelerator escape(ui::VKEY_ESCAPE, ui::EF_NONE);
  focus_manager_->RegisterAccelerator(
      escape, ui::AcceleratorManager::kNormalPriority, this);
  esc_accel_target_registered_ = true;
  // Register for Ctrl+Return.
  ui::Accelerator ctrl_ret(ui::VKEY_RETURN, ui::EF_CONTROL_DOWN);
  focus_manager_->RegisterAccelerator(
      ctrl_ret, ui::AcceleratorManager::kNormalPriority, this);
}

void FindBarHost::UnregisterAccelerators() {
  // Unregister Ctrl+Return.
  ui::Accelerator ctrl_ret(ui::VKEY_RETURN, ui::EF_CONTROL_DOWN);
  focus_manager_->UnregisterAccelerator(ctrl_ret, this);

  DCHECK(esc_accel_target_registered_);
  ui::Accelerator escape(ui::VKEY_ESCAPE, ui::EF_NONE);
  focus_manager_->UnregisterAccelerator(escape, this);
  esc_accel_target_registered_ = false;
}

gfx::Rect FindBarHost::GetDialogPosition(gfx::Rect avoid_overlapping_rect) {
  // Find the area we have to work with (after accounting for scrollbars, etc).
  // The owner does layout for the components that we care about
  // positioning relative to, so we ask it to tell us where we should go.
  gfx::Rect find_bar_bounds = find_bar_owner_->GetFindBarBoundingBox();
  if (find_bar_bounds.IsEmpty()) {
    return gfx::Rect();
  }

  // Ask the view how large an area it needs to draw on.
  gfx::Size prefsize = view_->GetPreferredSize();

  // Don't show the find bar if |widget_bounds| is not tall enough to fit.
  gfx::Insets insets = view_->GetInsets();
  if (find_bar_bounds.height() < prefsize.height() - insets.height()) {
    return gfx::Rect();
  }

  // Place the view in the top right corner of the widget boundaries (top left
  // for RTL languages). Adjust for the view insets to ensure the border lines
  // up with the location bar.
  int x = find_bar_bounds.x() - insets.left();
  if (!base::i18n::IsRTL()) {
    x += find_bar_bounds.width() - prefsize.width() + insets.width();
  }
  int y = find_bar_bounds.y() - insets.top();
  const gfx::Rect view_location(x, y, prefsize.width(), prefsize.height());

  // When we get Find results back, we specify a selection rect, which we
  // should strive to avoid overlapping. But first, we need to offset the
  // selection rect (if one was provided).
  if (!avoid_overlapping_rect.IsEmpty()) {
    // For comparison (with the Intersects function below) we need to account
    // for the fact that we draw the Find widget relative to the Chrome frame,
    // whereas the selection rect is relative to the page.
    GetWidgetPositionNative(&avoid_overlapping_rect);
  }

  gfx::Rect clipping_box = find_bar_owner_->GetFindBarClippingBox();

  return GetLocationForFindBarView(view_location, clipping_box,
                                   avoid_overlapping_rect);
}

void FindBarHost::SetDialogPosition(const gfx::Rect& new_pos) {
  view_->SetSize(new_pos.size());

  if (new_pos.IsEmpty()) {
    return;
  }

  host_->SetBounds(new_pos);

  find_bar_owner_->OnFindBarVisibilityChanged(host_->GetWindowBoundsInScreen());
}

void FindBarHost::OnWillChangeFocus(views::View* focused_before,
                                    views::View* focused_now) {
  // First we need to determine if one or both of the views passed in are child
  // views of our view.
  bool our_view_before = focused_before && view_->Contains(focused_before);
  bool our_view_now = focused_now && view_->Contains(focused_now);

  // When both our_view_before and our_view_now are false, it means focus is
  // changing hands elsewhere in the application (and we shouldn't do anything).
  // Similarly, when both are true, focus is changing hands within the dropdown
  // widget (and again, we should not do anything). We therefore only need to
  // look at when we gain initial focus and when we loose it.
  if (!our_view_before && our_view_now) {
    // We are gaining focus from outside the dropdown widget so we must register
    // a handler for Escape.
    RegisterAccelerators();
    SetFindBarIsFocusedOnCurrentTab(true);
  } else if (our_view_before && !our_view_now) {
    // We are losing focus to something outside our widget so we restore the
    // original handler for Escape.
    UnregisterAccelerators();
  }

  if (!our_view_now) {
    SetFindBarIsFocusedOnCurrentTab(false);
  }
}

void FindBarHost::AnimationProgressed(const gfx::Animation* animation) {
  // First, we calculate how many pixels to slide the widget.
  gfx::Size pref_size = view_->GetPreferredSize();
  int view_offset = static_cast<int>((animation_->GetCurrentValue() - 1.0) *
                                     pref_size.height());

  // This call makes sure |view_| appears in the right location, the size and
  // shape is correct and that it slides in the right direction.
  view_->SetPosition(gfx::Point(0, view_offset));
}

void FindBarHost::AnimationEnded(const gfx::Animation* animation) {
  // Ensure the position gets a final update.  This is important when ending the
  // animation early (e.g. closing a tab with an open find bar), since otherwise
  // the position will be out of date at the start of the next animation.
  AnimationProgressed(animation);

  if (!animation_->IsShowing()) {
    // Animation has finished closing.
    DCHECK(host_);
    host_->Hide();
    is_visible_ = false;
    OnVisibilityChanged();
  }
}
