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

#include "content/browser/android/selection/selection_popup_controller.h"

#include <cstdlib>

#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/feature_list.h"
#include "content/browser/android/selection/composited_touch_handle_drawable.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/web_contents/web_contents_view_android.h"
#include "content/common/features.h"
#include "content/public/browser/android/selection_popup_delegate.h"
#include "content/public/browser/context_menu_params.h"
#include "content/public/common/content_features.h"
#include "third_party/blink/public/common/context_menu_data/edit_flags.h"
#include "third_party/blink/public/mojom/context_menu/context_menu.mojom.h"
#include "third_party/blink/public/mojom/input/input_handler.mojom.h"
#include "ui/base/models/menu_model.h"
#include "ui/base/mojom/menu_source_type.mojom.h"
#include "ui/gfx/android/android_surface_control_compat.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/menus/android/menu_model_bridge.h"

// Must come after all headers that specialize FromJniType() / ToJniType().
#include "content/public/android/content_jni_headers/SelectionPopupControllerImpl_jni.h"

using base::android::AttachCurrentThread;
using base::android::ConvertUTF16ToJavaString;
using base::android::ConvertUTF8ToJavaString;
using base::android::JavaParamRef;
using base::android::ScopedJavaGlobalRef;
using base::android::ScopedJavaLocalRef;

namespace content {
namespace {

const int kMaxOffsetAdjust = 50;
const int kMaxOffsetExtendedAdjust = 250;

bool IsOffsetAdjustValid(
    int startOffset,
    int endOffset,
    int surroundingTextLength,
    const blink::mojom::SelectAroundCaretResultPtr& result) {
  return std::abs(result->word_start_adjust) < kMaxOffsetAdjust &&
         std::abs(result->word_end_adjust) < kMaxOffsetAdjust &&
         std::abs(result->extended_start_adjust) < kMaxOffsetExtendedAdjust &&
         std::abs(result->extended_end_adjust) < kMaxOffsetExtendedAdjust &&
         startOffset + result->extended_start_adjust >= 0 &&
         startOffset + result->extended_start_adjust <= surroundingTextLength &&
         endOffset + result->extended_end_adjust >= 0 &&
         endOffset + result->extended_end_adjust <= surroundingTextLength;
}

}  // namespace

namespace {

BASE_FEATURE(kDismissMagnifierOnViewSwap, base::FEATURE_ENABLED_BY_DEFAULT);

}  // namespace

static jboolean
JNI_SelectionPopupControllerImpl_IsMagnifierWithSurfaceControlSupported(
    JNIEnv* env) {
  static bool enabled = gfx::SurfaceControl::SupportsSurfacelessControl();
  return enabled;
}

jlong JNI_SelectionPopupControllerImpl_Init(
    JNIEnv* env,
    const JavaParamRef<jobject>& obj,
    const JavaParamRef<jobject>& jweb_contents) {
  WebContents* web_contents = WebContents::FromJavaWebContents(jweb_contents);
  DCHECK(web_contents);

  // Owns itself and gets destroyed when |WebContentsDestroyed| is called.
  auto* controller = new SelectionPopupController(env, obj, web_contents);
  controller->Initialize();
  return reinterpret_cast<intptr_t>(controller);
}

SelectionPopupController* SelectionPopupController::FromWebContents(
    WebContents& web_contents) {
  ScopedJavaLocalRef<jobject> jweb_contents = web_contents.GetJavaWebContents();
  JNIEnv* env = AttachCurrentThread();
  // Call the Java-side fromWebContents method. This gets the Java
  // SelectionPopupController if it already exists. Otherwise, this will
  // instantiate the Java SelectionPopupController and store it in the web
  // contents.
  ScopedJavaLocalRef<jobject> jselection_popup_controller =
      Java_SelectionPopupControllerImpl_fromWebContents(env, jweb_contents);
  // Then get the native pointer from the newly-created
  // SelectionPopupController. The Java SelectionPopupController owns the C++
  // SelectionPopupController.
  jlong selection_popup_controller =
      Java_SelectionPopupControllerImpl_getNativePtr(
          env, jselection_popup_controller);
  return reinterpret_cast<SelectionPopupController*>(
      selection_popup_controller);
}

SelectionPopupController::SelectionPopupController(
    JNIEnv* env,
    const JavaParamRef<jobject>& obj,
    WebContents* web_contents)
    : RenderWidgetHostConnector(web_contents) {
  java_obj_ = JavaObjectWeakGlobalRef(env, obj);
}

SelectionPopupController::~SelectionPopupController() {
  JNIEnv* env = AttachCurrentThread();
  ScopedJavaLocalRef<jobject> obj = java_obj_.get(env);
  if (!obj.is_null()) {
    Java_SelectionPopupControllerImpl_nativeSelectionPopupControllerDestroyed(
        env, obj);
  }
}

ScopedJavaLocalRef<jobject> SelectionPopupController::GetContext() const {
  JNIEnv* env = AttachCurrentThread();

  ScopedJavaLocalRef<jobject> obj = java_obj_.get(env);
  if (obj.is_null())
    return nullptr;

  return Java_SelectionPopupControllerImpl_getContext(env, obj);
}

void SelectionPopupController::SetTextHandlesHiddenForDropdownMenu(
    JNIEnv* env,
    jboolean hidden) {
  if (rwhva_) {
    rwhva_->SetTextHandlesHiddenForDropdownMenu(hidden);
  }
}

void SelectionPopupController::SetTextHandlesTemporarilyHidden(
    JNIEnv* env,
    jboolean hidden) {
  if (rwhva_)
    rwhva_->SetTextHandlesTemporarilyHidden(hidden);
}

ScopedJavaLocalRef<jobjectArray> SelectionPopupController::GetTouchHandleRects(
    JNIEnv* env) {
  if (!rwhva_ || !rwhva_->touch_selection_controller()) {
    return nullptr;
  }
  gfx::RectF start_handle =
      rwhva_->touch_selection_controller()->GetStartHandleRect();
  gfx::RectF end_handle =
      rwhva_->touch_selection_controller()->GetEndHandleRect();
  std::vector<ScopedJavaLocalRef<jobject>> handle_rects;
  ScopedJavaLocalRef<jobject> start = ScopedJavaLocalRef<jobject>(
      Java_SelectionPopupControllerImpl_createJavaRect(
          env, start_handle.x(), start_handle.y(), start_handle.right(),
          start_handle.bottom()));
  ScopedJavaLocalRef<jobject> end = ScopedJavaLocalRef<jobject>(
      Java_SelectionPopupControllerImpl_createJavaRect(
          env, end_handle.x(), end_handle.y(), end_handle.right(),
          end_handle.bottom()));
  handle_rects.push_back(start);
  handle_rects.push_back(end);
  return base::android::ToJavaArrayOfObjects(env, handle_rects);
}

std::unique_ptr<ui::TouchHandleDrawable>
SelectionPopupController::CreateTouchHandleDrawable(
    gfx::NativeView parent_native_view,
    cc::slim::Layer* parent_layer) {
  ScopedJavaLocalRef<jobject> activityContext = GetContext();
  // If activityContext is null then Application context is used instead on
  // the java side in CompositedTouchHandleDrawable.
  return std::make_unique<CompositedTouchHandleDrawable>(
      parent_native_view, parent_layer, activityContext);
}

void SelectionPopupController::MoveRangeSelectionExtent(
    const gfx::PointF& extent) {
  auto* web_contents_impl = static_cast<WebContentsImpl*>(web_contents());
  if (!web_contents_impl)
    return;

  web_contents_impl->MoveRangeSelectionExtent(gfx::ToRoundedPoint(extent));
}

void SelectionPopupController::SelectBetweenCoordinates(
    const gfx::PointF& base,
    const gfx::PointF& extent) {
  auto* web_contents_impl = static_cast<WebContentsImpl*>(web_contents());
  if (!web_contents_impl)
    return;

  gfx::Point base_point = gfx::ToRoundedPoint(base);
  gfx::Point extent_point = gfx::ToRoundedPoint(extent);
  if (base_point == extent_point)
    return;

  web_contents_impl->SelectRange(base_point, extent_point);
}

void SelectionPopupController::UpdateRenderProcessConnection(
    RenderWidgetHostViewAndroid* old_rwhva,
    RenderWidgetHostViewAndroid* new_rwhva) {
  if (old_rwhva)
    old_rwhva->set_selection_popup_controller(nullptr);
  if (new_rwhva)
    new_rwhva->set_selection_popup_controller(this);
  rwhva_ = new_rwhva;

  if (!base::FeatureList::IsEnabled(kDismissMagnifierOnViewSwap)) {
    return;
  }
  JNIEnv* env = AttachCurrentThread();
  ScopedJavaLocalRef<jobject> obj = java_obj_.get(env);
  if (obj.is_null()) {
    return;
  }

  Java_SelectionPopupControllerImpl_renderWidgetHostViewChanged(env, obj);
}

void SelectionPopupController::OnSelectionEvent(
    ui::SelectionEventType event,
    const gfx::RectF& selection_rect) {
  JNIEnv* env = AttachCurrentThread();
  ScopedJavaLocalRef<jobject> obj = java_obj_.get(env);
  if (obj.is_null())
    return;

  Java_SelectionPopupControllerImpl_onSelectionEvent(
      env, obj, event, selection_rect.x(), selection_rect.y(),
      selection_rect.right(), selection_rect.bottom());
}

void SelectionPopupController::OnDragUpdate(
    const ui::TouchSelectionDraggable::Type type,
    const gfx::PointF& position) {
  JNIEnv* env = AttachCurrentThread();
  ScopedJavaLocalRef<jobject> obj = java_obj_.get(env);
  if (obj.is_null())
    return;

  Java_SelectionPopupControllerImpl_onDragUpdate(
      env, obj, static_cast<int>(type), position.x(), position.y());
}

void SelectionPopupController::OnSelectionChanged(const std::string& text) {
  JNIEnv* env = AttachCurrentThread();
  ScopedJavaLocalRef<jobject> obj = java_obj_.get(env);
  if (obj.is_null())
    return;
  ScopedJavaLocalRef<jstring> jtext = ConvertUTF8ToJavaString(env, text);
  Java_SelectionPopupControllerImpl_onSelectionChanged(env, obj, jtext);
}

bool SelectionPopupController::ShowSelectionMenu(
    RenderFrameHost* render_frame_host,
    const ContextMenuParams& params,
    int handle_height) {
  JNIEnv* env = AttachCurrentThread();
  ScopedJavaLocalRef<jobject> obj = java_obj_.get(env);
  if (obj.is_null())
    return false;

  // Display paste pop-up only when selection is empty and editable.
  const bool from_touch =
      params.source_type == ui::mojom::MenuSourceType::kTouch ||
      params.source_type == ui::mojom::MenuSourceType::kLongPress ||
      params.source_type == ui::mojom::MenuSourceType::kTouchHandle ||
      params.source_type == ui::mojom::MenuSourceType::kStylus;

  const bool from_mouse =
      params.source_type == ui::mojom::MenuSourceType::kMouse;

  const bool from_selection_adjustment =
      params.source_type == ui::mojom::MenuSourceType::kAdjustSelection ||
      params.source_type == ui::mojom::MenuSourceType::kAdjustSelectionReset;

  // If source_type is not in the list then return.
  if (!from_touch && !from_mouse && !from_selection_adjustment)
    return false;

  // Don't show paste pop-up for non-editable textarea.
  if (!params.is_editable && params.selection_text.empty()) {
    return false;
  }

  const bool can_select_all =
      !!(params.edit_flags & blink::ContextMenuDataEditFlags::kCanSelectAll);
  const bool can_edit_richly =
      !!(params.edit_flags & blink::ContextMenuDataEditFlags::kCanEditRichly);
  const bool is_password_type =
      params.form_control_type == blink::mojom::FormControlType::kInputPassword;
  const ScopedJavaLocalRef<jstring> jselected_text =
      ConvertUTF16ToJavaString(env, params.selection_text);
  const bool should_suggest =
      params.source_type == ui::mojom::MenuSourceType::kTouch ||
      params.source_type == ui::mojom::MenuSourceType::kLongPress;

    extra_items_menu_model_.reset();
    extra_items_menu_model_ =
        selection_popup_delegate_
            ? selection_popup_delegate_->GetSelectionPopupExtraItems(
                  *render_frame_host, params)
            : nullptr;
    ui::MenuModel* menu_model = extra_items_menu_model_.get();
    menu_model_bridge_ = std::make_unique<ui::MenuModelBridge>(
        menu_model ? menu_model->AsWeakPtr() : nullptr);

    Java_SelectionPopupControllerImpl_showSelectionMenu(
        env, obj, params.x, params.y, params.selection_rect.x(),
        params.selection_rect.y(), params.selection_rect.right(),
        params.selection_rect.bottom(), handle_height, params.is_editable,
        is_password_type, jselected_text, params.selection_start_offset,
        can_select_all, can_edit_richly, should_suggest,
        static_cast<int>(params.source_type),
        render_frame_host->GetJavaRenderFrameHost(),
        menu_model_bridge_->GetJavaObject());
    return true;
}

void SelectionPopupController::OnSelectAroundCaretAck(
    int startOffset,
    int endOffset,
    int surroundingTextLength,
    blink::mojom::SelectAroundCaretResultPtr result) {
  JNIEnv* env = AttachCurrentThread();
  ScopedJavaLocalRef<jobject> obj = java_obj_.get(env);
  if (obj.is_null()) {
    return;
  }
  if (result.is_null() || !IsOffsetAdjustValid(startOffset, endOffset,
                                               surroundingTextLength, result)) {
    Java_SelectionPopupControllerImpl_onSelectAroundCaretFailure(env, obj);
    return;
  }

  Java_SelectionPopupControllerImpl_onSelectAroundCaretSuccess(
      env, obj, result->extended_start_adjust, result->extended_end_adjust,
      result->word_start_adjust, result->word_end_adjust);
}

void SelectionPopupController::HidePopupsAndPreserveSelection() {
  JNIEnv* env = AttachCurrentThread();
  ScopedJavaLocalRef<jobject> obj = java_obj_.get(env);
  if (obj.is_null())
    return;

  menu_model_bridge_.reset();
  extra_items_menu_model_.reset();
  Java_SelectionPopupControllerImpl_hidePopupsAndPreserveSelection(env, obj);
}

void SelectionPopupController::RestoreSelectionPopupsIfNecessary() {
  JNIEnv* env = AttachCurrentThread();
  ScopedJavaLocalRef<jobject> obj = java_obj_.get(env);
  if (obj.is_null())
    return;
  Java_SelectionPopupControllerImpl_restoreSelectionPopupsIfNecessary(env, obj);
}

void SelectionPopupController::ChildLocalSurfaceIdChanged() {
  JNIEnv* env = AttachCurrentThread();
  ScopedJavaLocalRef<jobject> obj = java_obj_.get(env);
  if (obj.is_null()) {
    return;
  }

  Java_SelectionPopupControllerImpl_childLocalSurfaceIdChanged(env, obj);
}

}  // namespace content
