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

#include "ash/quick_insert/quick_insert_controller.h"

#include <algorithm>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <utility>
#include <variant>
#include <vector>

#include "ash/accessibility/accessibility_controller.h"
#include "ash/constants/ash_features.h"
#include "ash/constants/ash_pref_names.h"
#include "ash/constants/ash_switches.h"
#include "ash/public/cpp/clipboard_history_controller.h"
#include "ash/public/cpp/new_window_delegate.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/quick_insert/model/quick_insert_action_type.h"
#include "ash/quick_insert/model/quick_insert_caps_lock_position.h"
#include "ash/quick_insert/model/quick_insert_emoji_history_model.h"
#include "ash/quick_insert/model/quick_insert_emoji_suggester.h"
#include "ash/quick_insert/model/quick_insert_mode_type.h"
#include "ash/quick_insert/model/quick_insert_model.h"
#include "ash/quick_insert/model/quick_insert_search_results_section.h"
#include "ash/quick_insert/quick_insert_action_on_next_focus_request.h"
#include "ash/quick_insert/quick_insert_asset_fetcher.h"
#include "ash/quick_insert/quick_insert_asset_fetcher_impl.h"
#include "ash/quick_insert/quick_insert_caps_lock_bubble_controller.h"
#include "ash/quick_insert/quick_insert_client.h"
#include "ash/quick_insert/quick_insert_copy_media.h"
#include "ash/quick_insert/quick_insert_insert_media_request.h"
#include "ash/quick_insert/quick_insert_paste_request.h"
#include "ash/quick_insert/quick_insert_rich_media.h"
#include "ash/quick_insert/quick_insert_search_result.h"
#include "ash/quick_insert/quick_insert_suggestions_controller.h"
#include "ash/quick_insert/quick_insert_transform_case.h"
#include "ash/quick_insert/search/quick_insert_search_controller.h"
#include "ash/quick_insert/views/quick_insert_caps_lock_state_view.h"
#include "ash/quick_insert/views/quick_insert_icons.h"
#include "ash/quick_insert/views/quick_insert_positioning.h"
#include "ash/quick_insert/views/quick_insert_view.h"
#include "ash/quick_insert/views/quick_insert_view_delegate.h"
#include "ash/quick_insert/views/quick_insert_widget.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/wm/window_util.h"
#include "base/check.h"
#include "base/check_is_test.h"
#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/hash/sha1.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/notreached.h"
#include "base/strings/utf_string_conversions.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "third_party/abseil-cpp/absl/functional/overload.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/window.h"
#include "ui/base/emoji/emoji_panel_helper.h"
#include "ui/base/ime/ash/ime_bridge.h"
#include "ui/base/ime/ash/ime_keyboard.h"
#include "ui/base/ime/ash/input_method_manager.h"
#include "ui/base/ime/ash/text_input_target.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/display/screen.h"
#include "ui/events/ash/keyboard_capability.h"
#include "ui/events/devices/device_data_manager.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"

namespace ash {

namespace {

bool g_feature_tour_enabled = true;

// When spoken feedback is enabled, closing the widget after an insert is
// delayed by this amount.
constexpr base::TimeDelta kCloseWidgetDelay = base::Milliseconds(200);

// Time to wait for a focus event after triggering caps lock.
constexpr base::TimeDelta kCapsLockRequestTimeout = base::Seconds(1);

constexpr int kCapsLockMinimumTopDisplayCount = 5;
constexpr float kCapsLockRatioThresholdForTop = 0.8;
constexpr float kCapsLockRatioThresholdForBottom = 0.2;

constexpr std::string_view kSupportUrl =
    "https://support.google.com/chromebook?p=dugong";

ui::TextInputClient* GetFocusedTextInputClient() {
  const ui::InputMethod* input_method =
      IMEBridge::Get()->GetInputContextHandler()->GetInputMethod();
  if (!input_method || !input_method->GetTextInputClient()) {
    return nullptr;
  }
  return input_method->GetTextInputClient();
}

// Gets the current caret bounds in universal screen coordinates in DIP. Returns
// an empty rect if there is no active caret or the caret bounds can't be
// determined (e.g. no focused input field).
gfx::Rect GetCaretBounds() {
  if (ui::TextInputClient* client = GetFocusedTextInputClient()) {
    return client->GetCaretBounds();
  }
  return gfx::Rect();
}

// Gets the current cursor point in universal screen coordinates in DIP.
gfx::Point GetCursorPoint() {
  return display::Screen::Get()->GetCursorScreenPoint();
}

// Gets the bounds of the current focused window in universal screen coordinates
// in DIP. Returns an empty rect if there is no currently focused window.
gfx::Rect GetFocusedWindowBounds() {
  return window_util::GetFocusedWindow()
             ? window_util::GetFocusedWindow()->GetBoundsInScreen()
             : gfx::Rect();
}

input_method::ImeKeyboard& GetImeKeyboard() {
  auto* input_method_manager = input_method::InputMethodManager::Get();
  CHECK(input_method_manager);
  input_method::ImeKeyboard* ime_keyboard =
      input_method_manager->GetImeKeyboard();
  CHECK(ime_keyboard);
  return *ime_keyboard;
}

// The user can ask to insert rich media, a clipboard item, or insert nothing.
using InsertionContent = std::
    variant<QuickInsertRichMedia, QuickInsertClipboardResult, std::monostate>;

InsertionContent GetInsertionContentForResult(
    const QuickInsertSearchResult& result) {
  using ReturnType = InsertionContent;
  return std::visit(
      absl::Overload{
          [](const QuickInsertTextResult& data) -> ReturnType {
            return QuickInsertTextMedia(data.primary_text);
          },
          [](const QuickInsertEmojiResult& data) -> ReturnType {
            return QuickInsertTextMedia(data.text);
          },
          [](const QuickInsertClipboardResult& data) -> ReturnType {
            return data;
          },
          [](const QuickInsertBrowsingHistoryResult& data) -> ReturnType {
            return QuickInsertLinkMedia(data.url,
                                        base::UTF16ToUTF8(data.title));
          },
          [](const QuickInsertGifResult& data) -> ReturnType {
            return QuickInsertImageMedia(data.full_url, data.full_dimensions,
                                         data.content_description);
          },
          [](const QuickInsertLocalFileResult& data) -> ReturnType {
            return QuickInsertLocalFileMedia(data.file_path);
          },
          [](const QuickInsertDriveFileResult& data) -> ReturnType {
            return QuickInsertLinkMedia(data.url,
                                        base::UTF16ToUTF8(data.title));
          },
          [](const QuickInsertCategoryResult& data) -> ReturnType {
            return std::monostate();
          },
          [](const QuickInsertSearchRequestResult& data) -> ReturnType {
            return std::monostate();
          },
          [](const QuickInsertEditorResult& data) -> ReturnType {
            return std::monostate();
          },
          [](const QuickInsertLobsterResult& data) -> ReturnType {
            return std::monostate();
          },
          [](const QuickInsertNewWindowResult& data) -> ReturnType {
            return std::monostate();
          },
          [](const QuickInsertCapsLockResult& data) -> ReturnType {
            return std::monostate();
          },
          [](const QuickInsertCaseTransformResult& data) -> ReturnType {
            return std::monostate();
          },
      },
      result);
}

std::vector<QuickInsertSearchResultsSection>
CreateSingleSectionForCategoryResults(
    QuickInsertSectionType section_type,
    std::vector<QuickInsertSearchResult> results) {
  if (results.empty()) {
    return {};
  }
  return {QuickInsertSearchResultsSection(section_type, std::move(results),
                                          /*has_more_results=*/false)};
}

std::u16string TransformText(std::u16string_view text,
                             QuickInsertCaseTransformResult::Type type) {
  switch (type) {
    case QuickInsertCaseTransformResult::Type::kUpperCase:
      return QuickInsertTransformToUpperCase(text);
    case QuickInsertCaseTransformResult::Type::kLowerCase:
      return QuickInsertTransformToLowerCase(text);
    case QuickInsertCaseTransformResult::Type::kTitleCase:
      return QuickInsertTransformToTitleCase(text);
  }
  NOTREACHED();
}

void OpenLink(const GURL& url) {
  NewWindowDelegate::GetInstance()->OpenUrl(
      url, NewWindowDelegate::OpenUrlFrom::kUserInteraction,
      NewWindowDelegate::Disposition::kNewForegroundTab);
}

void OpenFile(const base::FilePath& path) {
  NewWindowDelegate::GetInstance()->OpenFile(path);
}

GURL GetUrlForNewWindow(QuickInsertNewWindowResult::Type type) {
  switch (type) {
    case QuickInsertNewWindowResult::Type::kDoc:
      return GURL("https://docs.new");
    case QuickInsertNewWindowResult::Type::kSheet:
      return GURL("https://sheets.new");
    case QuickInsertNewWindowResult::Type::kSlide:
      return GURL("https://slides.new");
    case QuickInsertNewWindowResult::Type::kChrome:
      return GURL("chrome://newtab");
  }
}

ui::EmojiPickerCategory EmojiResultTypeToCategory(
    QuickInsertEmojiResult::Type type) {
  switch (type) {
    case QuickInsertEmojiResult::Type::kEmoji:
      return ui::EmojiPickerCategory::kEmojis;
    case QuickInsertEmojiResult::Type::kSymbol:
      return ui::EmojiPickerCategory::kSymbols;
    case QuickInsertEmojiResult::Type::kEmoticon:
      return ui::EmojiPickerCategory::kEmoticons;
  }
}

QuickInsertSectionType GetSectionTypeForCategorySuggestion(
    QuickInsertCategory category) {
  switch (category) {
    case QuickInsertCategory::kUnitsMaths:
    case QuickInsertCategory::kDatesTimes:
      return QuickInsertSectionType::kExamples;
    case QuickInsertCategory::kGifs:
      return QuickInsertSectionType::kFeaturedGifs;
    default:
      return QuickInsertSectionType::kNone;
  }
}

}  // namespace

QuickInsertController::QuickInsertController()
    : caps_lock_bubble_controller_(&GetImeKeyboard()),
      asset_fetcher_(std::make_unique<QuickInsertAssetFetcherImpl>(this)),
      search_controller_(kBurnInPeriod) {}

QuickInsertController::~QuickInsertController() {
  // `widget_` depends on `this`. Destroy the widget synchronously to avoid a
  // dangling pointer.
  if (widget_) {
    widget_->CloseNow();
  }
}

void QuickInsertController::RegisterProfilePrefs(PrefRegistrySimple* registry) {
  QuickInsertFeatureTour::RegisterProfilePrefs(registry);
  QuickInsertSessionMetrics::RegisterProfilePrefs(registry);
}

void QuickInsertController::DisableFeatureTourForTesting() {
  CHECK_IS_TEST();
  g_feature_tour_enabled = false;
}

void QuickInsertController::SetClient(QuickInsertClient* client) {
  // `QuickInsertSearchController` may depend on the current client via
  // `StartSearch`. Stop the search before changing the `client`. This may send
  // a `StopSearch` call to the current `client_`.
  search_controller_.StopSearch();
  client_ = client;
}

void QuickInsertController::OnClientPrefsSet(PrefService* prefs) {
  if (client_ == nullptr) {
    return;
  }

  search_controller_.LoadEmojiLanguagesFromPrefs(prefs);
}

void QuickInsertController::ToggleWidget(
    const base::TimeTicks trigger_event_timestamp) {
  // Show the feature tour if it's the first time this feature is used.
  if (PrefService* prefs = GetPrefs();
      g_feature_tour_enabled && prefs &&
      feature_tour_.MaybeShowForFirstUse(
          prefs,
          client_->IsEligibleForEditor()
              ? QuickInsertFeatureTour::EditorStatus::kEligible
              : QuickInsertFeatureTour::EditorStatus::kNotEligible,
          base::BindRepeating(OpenLink, GURL(kSupportUrl)),
          base::BindRepeating(&QuickInsertController::ShowWidgetPostFeatureTour,
                              weak_ptr_factory_.GetWeakPtr()))) {
    return;
  }

  if (widget_) {
    CloseWidget();
  } else {
    ShowWidget(trigger_event_timestamp, WidgetTriggerSource::kDefault);
  }
}

std::vector<QuickInsertCategory>
QuickInsertController::GetAvailableCategories() {
  return session_ == nullptr ? std::vector<QuickInsertCategory>{}
                             : session_->model.GetAvailableCategories();
}

void QuickInsertController::GetZeroStateSuggestedResults(
    SuggestedResultsCallback callback) {
  CHECK(client_);
  suggestions_controller_.GetSuggestions(*client_, session_->model,
                                         std::move(callback));
}

void QuickInsertController::GetResultsForCategory(
    QuickInsertCategory category,
    SearchResultsCallback callback) {
  CHECK(client_);
  suggestions_controller_.GetSuggestionsForCategory(
      *client_, category,
      base::BindRepeating(CreateSingleSectionForCategoryResults,
                          GetSectionTypeForCategorySuggestion(category))
          .Then(std::move(callback)));
}

void QuickInsertController::StartSearch(
    std::u16string_view query,
    std::optional<QuickInsertCategory> category,
    SearchResultsCallback callback) {
  CHECK(session_);
  CHECK(client_);
  search_controller_.StartSearch(
      client_, query, std::move(category), GetAvailableCategories(),
      !session_->model.is_caps_lock_enabled(),
      session_->model.GetMode() == QuickInsertModeType::kHasSelection,
      std::move(callback));
}

void QuickInsertController::StopSearch() {
  search_controller_.StopSearch();
}

void QuickInsertController::StartEmojiSearch(
    std::u16string_view query,
    EmojiSearchResultsCallback callback) {
  search_controller_.StartEmojiSearch(GetPrefs(), query, std::move(callback));
}

void QuickInsertController::CloseWidgetThenInsertResultOnNextFocus(
    const QuickInsertSearchResult& result) {
  InsertResultOnNextFocus(result);

  client_->Announce(
      l10n_util::GetStringUTF16(IDS_PICKER_INSERTION_ANNOUNCEMENT_TEXT));

  if (Shell::Get()->accessibility_controller()->spoken_feedback().enabled()) {
    close_widget_delay_timer_.Start(
        FROM_HERE, kCloseWidgetDelay,
        base::BindOnce(&QuickInsertController::CloseWidget,
                       weak_ptr_factory_.GetWeakPtr()));
  } else {
    CloseWidget();
  }
}

void QuickInsertController::OpenResult(const QuickInsertSearchResult& result) {
  return std::visit(
      absl::Overload{
          [](const QuickInsertTextResult& data) { NOTREACHED(); },
          [](const QuickInsertEmojiResult& data) { NOTREACHED(); },
          [](const QuickInsertGifResult& data) { NOTREACHED(); },
          [](const QuickInsertClipboardResult& data) { NOTREACHED(); },
          [&](const QuickInsertBrowsingHistoryResult& data) {
            session_->session_metrics.SetOutcome(
                QuickInsertSessionMetrics::SessionOutcome::kOpenLink);
            OpenLink(data.url);
          },
          [&](const QuickInsertLocalFileResult& data) {
            session_->session_metrics.SetOutcome(
                QuickInsertSessionMetrics::SessionOutcome::kOpenFile);
            OpenFile(data.file_path);
          },
          [&](const QuickInsertDriveFileResult& data) {
            session_->session_metrics.SetOutcome(
                QuickInsertSessionMetrics::SessionOutcome::kOpenLink);
            OpenLink(data.url);
          },
          [](const QuickInsertCategoryResult& data) { NOTREACHED(); },
          [](const QuickInsertSearchRequestResult& data) { NOTREACHED(); },
          [](const QuickInsertEditorResult& data) { NOTREACHED(); },
          [](const QuickInsertLobsterResult& data) { NOTREACHED(); },
          [&](const QuickInsertNewWindowResult& data) {
            session_->session_metrics.SetOutcome(
                QuickInsertSessionMetrics::SessionOutcome::kCreate);
            OpenLink(GetUrlForNewWindow(data.type));
          },
          [&](const QuickInsertCapsLockResult& data) {
            session_->session_metrics.SetOutcome(
                QuickInsertSessionMetrics::SessionOutcome::kFormat);
            caps_lock_request_ =
                std::make_unique<QuickInsertActionOnNextFocusRequest>(
                    widget_->GetInputMethod(), kCapsLockRequestTimeout,
                    base::BindOnce(
                        [](bool enabled) {
                          GetImeKeyboard().SetCapsLockEnabled(enabled);
                        },
                        data.enabled),
                    base::BindOnce(
                        [](bool enabled) {
                          GetImeKeyboard().SetCapsLockEnabled(enabled);
                        },
                        data.enabled));
          },
          [&](const QuickInsertCaseTransformResult& data) {
            if (!session_) {
              return;
            }
            session_->session_metrics.SetOutcome(
                QuickInsertSessionMetrics::SessionOutcome::kFormat);
            std::u16string_view selected_text = session_->model.selected_text();
            InsertResultOnNextFocus(QuickInsertTextResult(
                TransformText(selected_text, data.type),
                QuickInsertTextResult::Source::kCaseTransform));
          },
      },
      result);
}

void QuickInsertController::ShowEmojiPicker(ui::EmojiPickerCategory category,
                                            std::u16string_view query) {
  ui::ShowEmojiPanelInSpecificMode(category,
                                   ui::EmojiPickerFocusBehavior::kAlwaysShow,
                                   base::UTF16ToUTF8(query));
}

void QuickInsertController::ShowEditor(
    std::optional<std::string> preset_query_id,
    std::optional<std::string> freeform_text) {
  if (!show_editor_callback_.is_null()) {
    std::move(show_editor_callback_)
        .Run(std::move(preset_query_id), std::move(freeform_text));
  }
}

// TODO: b:370885630 - Considers making selected_text as an argument of this
// method.
void QuickInsertController::ShowLobster(
    std::optional<std::string> freeform_text) {
  if (!show_lobster_callback_.is_null()) {
    std::move(show_lobster_callback_)
        .Run(session_ != nullptr && session_->model.selected_text() != u""
                 ? base::UTF16ToUTF8(session_->model.selected_text())
                 : std::move(freeform_text));
  }
}

QuickInsertAssetFetcher* QuickInsertController::GetAssetFetcher() {
  return asset_fetcher_.get();
}

QuickInsertSessionMetrics& QuickInsertController::GetSessionMetrics() {
  return session_->session_metrics;
}

QuickInsertActionType QuickInsertController::GetActionForResult(
    const QuickInsertSearchResult& result) {
  CHECK(session_);
  const QuickInsertModeType mode = session_->model.GetMode();
  return std::visit(
      absl::Overload{[mode](const QuickInsertTextResult& data) {
                       CHECK(mode == QuickInsertModeType::kNoSelection ||
                             mode == QuickInsertModeType::kHasSelection);
                       return QuickInsertActionType::kInsert;
                     },
                     [mode](const QuickInsertEmojiResult& data) {
                       CHECK(mode == QuickInsertModeType::kNoSelection ||
                             mode == QuickInsertModeType::kHasSelection);
                       return QuickInsertActionType::kInsert;
                     },
                     [mode](const QuickInsertGifResult& data) {
                       CHECK(mode == QuickInsertModeType::kNoSelection ||
                             mode == QuickInsertModeType::kHasSelection);
                       return QuickInsertActionType::kInsert;
                     },
                     [mode](const QuickInsertClipboardResult& data) {
                       CHECK(mode == QuickInsertModeType::kNoSelection ||
                             mode == QuickInsertModeType::kHasSelection);
                       return QuickInsertActionType::kInsert;
                     },
                     [mode](const QuickInsertBrowsingHistoryResult& data) {
                       return mode == QuickInsertModeType::kUnfocused
                                  ? QuickInsertActionType::kOpen
                                  : QuickInsertActionType::kInsert;
                     },
                     [mode](const QuickInsertLocalFileResult& data) {
                       return mode == QuickInsertModeType::kUnfocused
                                  ? QuickInsertActionType::kOpen
                                  : QuickInsertActionType::kInsert;
                     },
                     [mode](const QuickInsertDriveFileResult& data) {
                       return mode == QuickInsertModeType::kUnfocused
                                  ? QuickInsertActionType::kOpen
                                  : QuickInsertActionType::kInsert;
                     },
                     [](const QuickInsertCategoryResult& data) {
                       return QuickInsertActionType::kDo;
                     },
                     [](const QuickInsertSearchRequestResult& data) {
                       return QuickInsertActionType::kDo;
                     },
                     [](const QuickInsertEditorResult& data) {
                       return QuickInsertActionType::kCreate;
                     },
                     [](const QuickInsertLobsterResult& data) {
                       return QuickInsertActionType::kCreate;
                     },
                     [](const QuickInsertNewWindowResult& data) {
                       return QuickInsertActionType::kDo;
                     },
                     [](const QuickInsertCapsLockResult& data) {
                       return QuickInsertActionType::kDo;
                     },
                     [&](const QuickInsertCaseTransformResult& data) {
                       return QuickInsertActionType::kDo;
                     }},
      result);
}

std::vector<QuickInsertEmojiResult> QuickInsertController::GetSuggestedEmoji() {
  CHECK(session_);
  return session_->emoji_suggester.GetSuggestedEmoji();
}

bool QuickInsertController::IsGifsEnabled() {
  CHECK(session_);
  return session_->model.IsGifsEnabled();
}

PrefService* QuickInsertController::GetPrefs() {
  return Shell::Get()->session_controller()->GetLastActiveUserPrefService();
}

QuickInsertModeType QuickInsertController::GetMode() {
  CHECK(session_);
  return session_->model.GetMode();
}

void QuickInsertController::OnViewIsDeleting(views::View* view) {
  view_observation_.Reset();

  session_.reset();
}

scoped_refptr<network::SharedURLLoaderFactory>
QuickInsertController::GetSharedURLLoaderFactory() {
  return client_->GetSharedURLLoaderFactory();
}

void QuickInsertController::FetchFileThumbnail(
    const base::FilePath& path,
    const gfx::Size& size,
    FetchFileThumbnailCallback callback) {
  client_->FetchFileThumbnail(path, size, std::move(callback));
}

QuickInsertController::Session::Session(
    PrefService* prefs,
    ui::TextInputClient* focused_client,
    input_method::ImeKeyboard* ime_keyboard,
    QuickInsertModel::EditorStatus editor_status,
    QuickInsertModel::LobsterStatus lobster_status,
    QuickInsertEmojiSuggester::GetNameCallback get_name)
    : model(prefs, focused_client, ime_keyboard, editor_status, lobster_status),
      emoji_history_model(prefs),
      emoji_suggester(&emoji_history_model, std::move(get_name)),
      session_metrics(prefs) {
  session_metrics.OnStartSession(focused_client);
  feature_usage_metrics.StartUsage();
}

QuickInsertController::Session::~Session() {
  feature_usage_metrics.StopUsage();
}

void QuickInsertController::ShowWidget(base::TimeTicks trigger_event_timestamp,
                                       WidgetTriggerSource trigger_source) {
  ui::TextInputClient* focused_text_input_client = GetFocusedTextInputClient();
  show_editor_callback_ = client_->CacheEditorContext();
  show_lobster_callback_ =
      client_->CacheLobsterContext(focused_text_input_client);
  input_method::ImeKeyboard& keyboard = GetImeKeyboard();

  if (focused_text_input_client &&
      focused_text_input_client->GetTextInputType() ==
          ui::TEXT_INPUT_TYPE_PASSWORD) {
    bool should_enable = !keyboard.IsCapsLockEnabled();
    keyboard.SetCapsLockEnabled(should_enable);
    return;
  }

  session_ = std::make_unique<Session>(
      GetPrefs(), focused_text_input_client, &keyboard,
      show_editor_callback_.is_null()
          ? QuickInsertModel::EditorStatus::kDisabled
          : QuickInsertModel::EditorStatus::kEnabled,
      show_lobster_callback_.is_null()
          ? QuickInsertModel::LobsterStatus::kDisabled
          : QuickInsertModel::LobsterStatus::kEnabled,
      base::BindRepeating(
          [](base::WeakPtr<QuickInsertController> weak_controller,
             std::string_view emoji) -> std::string {
            if (weak_controller == nullptr) {
              return "";
            }
            return weak_controller->search_controller_.GetEmojiName(emoji);
          },
          weak_ptr_factory_.GetWeakPtr()));

  const gfx::Rect anchor_bounds = GetQuickInsertAnchorBounds(
      GetCaretBounds(), GetCursorPoint(), GetFocusedWindowBounds());
  if (trigger_source == WidgetTriggerSource::kFeatureTour &&
      session_->model.GetMode() == QuickInsertModeType::kUnfocused) {
    widget_ = QuickInsertWidget::CreateCentered(this, anchor_bounds,
                                                trigger_event_timestamp);
  } else {
    widget_ =
        QuickInsertWidget::Create(this, anchor_bounds, trigger_event_timestamp);
  }
  widget_->Show();

  view_observation_.Observe(widget_->GetContentsView());
}

void QuickInsertController::CloseWidget() {
  if (!widget_) {
    return;
  }

  session_->session_metrics.SetOutcome(
      QuickInsertSessionMetrics::SessionOutcome::kAbandoned);
  widget_->Close();
}

void QuickInsertController::ShowWidgetPostFeatureTour() {
  ShowWidget(base::TimeTicks::Now(), WidgetTriggerSource::kFeatureTour);
}

std::optional<QuickInsertWebPasteTarget>
QuickInsertController::GetWebPasteTarget() {
  return client_ ? client_->GetWebPasteTarget() : std::nullopt;
}

void QuickInsertController::InsertResultOnNextFocus(
    const QuickInsertSearchResult& result) {
  if (!widget_) {
    return;
  }

  // Update emoji history in prefs the result is an emoji/symbol/emoticon.
  CHECK(session_);
  if (auto* data = std::get_if<QuickInsertEmojiResult>(&result);
      data != nullptr && session_->model.should_do_learning()) {
    session_->emoji_history_model.UpdateRecentEmoji(
        EmojiResultTypeToCategory(data->type), base::UTF16ToUTF8(data->text));
  }

  std::visit(
      absl::Overload{
          [&](QuickInsertRichMedia media) {
            ui::InputMethod* input_method = widget_->GetInputMethod();
            if (input_method == nullptr) {
              return;
            }

            // This cancels the previous request if there was one.
            insert_media_request_ = std::make_unique<
                QuickInsertInsertMediaRequest>(
                input_method, media, kInsertMediaTimeout,
                base::BindOnce(
                    [](base::WeakPtr<QuickInsertController> weak_controller) {
                      return weak_controller
                                 ? weak_controller->GetWebPasteTarget()
                                 : std::nullopt;
                    },
                    weak_ptr_factory_.GetWeakPtr()),
                base::BindOnce(&QuickInsertController::OnInsertCompleted,
                               weak_ptr_factory_.GetWeakPtr(), media));
          },
          [&](QuickInsertClipboardResult data) {
            // This cancels the previous request if there was one.
            paste_request_ = std::make_unique<QuickInsertPasteRequest>(
                ClipboardHistoryController::Get(),
                aura::client::GetFocusClient(widget_->GetNativeView()),
                data.item_id);
          },
          [](std::monostate) { NOTREACHED(); },
      },
      GetInsertionContentForResult(result));

  session_->session_metrics.SetOutcome(
      QuickInsertSessionMetrics::SessionOutcome::kInsertedOrCopied);
}

void QuickInsertController::OnInsertCompleted(
    const QuickInsertRichMedia& media,
    QuickInsertInsertMediaRequest::Result result) {
  // Fallback to copying to the clipboard on failure.
  if (result != QuickInsertInsertMediaRequest::Result::kSuccess) {
    CopyMediaToClipboard(media);
  }
}

QuickInsertCapsLockPosition QuickInsertController::GetCapsLockPosition() {
  // Always put the caps lock entry point at the top if the user has caps lock
  // enabled, since it is they will likely want to disable it.
  if (GetImeKeyboard().IsCapsLockEnabled()) {
    return QuickInsertCapsLockPosition::kTop;
  }

  PrefService* prefs = GetPrefs();
  if (prefs == nullptr) {
    return QuickInsertCapsLockPosition::kTop;
  }

  int caps_lock_displayed_count =
      prefs->GetInteger(prefs::kQuickInsertCapsLockDisplayedCountPrefName);
  int caps_lock_selected_count =
      prefs->GetInteger(prefs::kQuickInsertLockSelectedCountPrefName);
  float caps_lock_selected_ratio =
      static_cast<float>(caps_lock_selected_count) / caps_lock_displayed_count;

  if (caps_lock_displayed_count < kCapsLockMinimumTopDisplayCount ||
      caps_lock_selected_ratio >= kCapsLockRatioThresholdForTop) {
    return QuickInsertCapsLockPosition::kTop;
  }
  if (caps_lock_selected_ratio >= kCapsLockRatioThresholdForBottom) {
    return QuickInsertCapsLockPosition::kMiddle;
  }
  return QuickInsertCapsLockPosition::kBottom;
}

}  // namespace ash
