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

#include "components/exo/wayland/zwp_text_input_manager.h"

#include <sys/mman.h>
#include <text-input-extension-unstable-v1-server-protocol.h>
#include <text-input-unstable-v1-server-protocol.h>
#include <wayland-server-core.h>
#include <wayland-server-protocol-core.h>
#include <xkbcommon/xkbcommon.h>

#include <string_view>

#include "ash/constants/ash_features.h"
#include "base/compiler_specific.h"
#include "base/files/file_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/utf_offset_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "components/exo/display.h"
#include "components/exo/text_input.h"
#include "components/exo/wayland/serial_tracker.h"
#include "components/exo/wayland/server_util.h"
#include "components/exo/wayland/wl_seat.h"
#include "components/exo/xkb_tracker.h"
#include "net/base/data_url.h"
#include "ui/base/ime/utf_offset.h"
#include "ui/base/wayland/wayland_server_input_types.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/events/ozone/layout/xkb/xkb_modifier_converter.h"

namespace exo {
namespace wayland {

namespace {

// The list of modifiers that this supports.
// This is consistent with X.h.
constexpr const char* kModifierNames[] = {
    XKB_MOD_NAME_SHIFT, XKB_MOD_NAME_CAPS,
    XKB_MOD_NAME_CTRL,  XKB_MOD_NAME_ALT,
    XKB_MOD_NAME_NUM,   "Mod3",
    XKB_MOD_NAME_LOGO,  "Mod5",
};

////////////////////////////////////////////////////////////////////////////////
// text_input_v1 interface:

class WaylandTextInputDelegate : public TextInput::Delegate {
 public:
  WaylandTextInputDelegate(wl_resource* text_input,
                           const XkbTracker* xkb_tracker,
                           SerialTracker* serial_tracker)
      : text_input_(text_input),
        xkb_tracker_(xkb_tracker),
        serial_tracker_(serial_tracker) {}
  ~WaylandTextInputDelegate() override = default;

  void set_surface(wl_resource* surface) { surface_ = surface; }

  void set_extended_text_input(wl_resource* extended_text_input) {
    extended_text_input_ = extended_text_input;
  }

  bool has_extended_text_input() const { return extended_text_input_; }

  base::WeakPtr<WaylandTextInputDelegate> GetWeakPtr() {
    return weak_factory_.GetWeakPtr();
  }

  wl_resource* resource() { return text_input_; }

  ui::TextInputClient::FocusReason pending_focus_reason() const {
    return pending_focus_reason_;
  }

  void set_pending_focus_reason(ui::TextInputClient::FocusReason reason) {
    pending_focus_reason_ = reason;
  }

  bool pending_surrounding_text_supported() const {
    return pending_surrounding_text_supported_;
  }

  void set_pending_surrounding_text_supported(bool is_supported) {
    pending_surrounding_text_supported_ = is_supported;
  }

  void SetPendingGrammarFragment(
      const std::optional<ui::GrammarFragment>& grammar_fragment) {
    pending_grammar_fragment_ = grammar_fragment;
  }

  std::optional<ui::GrammarFragment> TakeGrammarFragment() {
    auto result = pending_grammar_fragment_;
    pending_grammar_fragment_.reset();
    return result;
  }

  void SetPendingAutocorrectInfo(const ui::AutocorrectInfo& autocorrect_info) {
    pending_autocorrect_info_ = autocorrect_info;
  }

  std::optional<ui::AutocorrectInfo> TakeAutocorrectInfo() {
    auto result = pending_autocorrect_info_;
    pending_autocorrect_info_.reset();
    return result;
  }

  void SetSurroundingTextOffsetUtf16(uint32_t offset) {
    pending_surrounding_text_offset_utf16_ = offset;
  }

  std::optional<uint32_t> TakeSurroundingTextOffsetUtf16() {
    auto result = pending_surrounding_text_offset_utf16_;
    pending_surrounding_text_offset_utf16_.reset();
    return result;
  }

 private:
  wl_client* client() { return wl_resource_get_client(text_input_); }

  // TextInput::Delegate:
  void Activated() override {
    zwp_text_input_v1_send_enter(text_input_, surface_);
    wl_client_flush(client());
  }

  void Deactivated() override {
    zwp_text_input_v1_send_leave(text_input_);
    wl_client_flush(client());
  }

  void OnVirtualKeyboardVisibilityChanged(bool is_visible) override {
    // The detailed spec of |state| is implementation dependent.
    // So, now we use the lowest bit to indicate whether keyboard is visible.
    // This behavior is consistent with ozone/wayland to support Lacros.
    zwp_text_input_v1_send_input_panel_state(text_input_,
                                             static_cast<uint32_t>(is_visible));
    wl_client_flush(client());
  }

  void OnVirtualKeyboardOccludedBoundsChanged(
      const gfx::Rect& screen_bounds) override {
    if (!extended_text_input_)
      return;

    if (wl_resource_get_version(extended_text_input_) >=
        ZCR_EXTENDED_TEXT_INPUT_V1_SET_VIRTUAL_KEYBOARD_OCCLUDED_BOUNDS_SINCE_VERSION) {
      zcr_extended_text_input_v1_send_set_virtual_keyboard_occluded_bounds(
          extended_text_input_, screen_bounds.x(), screen_bounds.y(),
          screen_bounds.width(), screen_bounds.height());
      wl_client_flush(client());
    }
  }

  bool SupportsFinalizeVirtualKeyboardChanges() override {
    return extended_text_input_ &&
           wl_resource_get_version(extended_text_input_) >=
               ZCR_EXTENDED_TEXT_INPUT_V1_FINALIZE_VIRTUAL_KEYBOARD_CHANGES_SINCE_VERSION;
  }

  void SetCompositionText(const ui::CompositionText& composition) override {
    SendPreeditStyle(composition.text, composition.ime_text_spans);

    std::vector<size_t> offsets = {composition.selection.start()};
    const std::string utf8 =
        base::UTF16ToUTF8AndAdjustOffsets(composition.text, &offsets);

    if (offsets[0] != std::string::npos)
      zwp_text_input_v1_send_preedit_cursor(text_input_, offsets[0]);

    zwp_text_input_v1_send_preedit_string(
        text_input_,
        serial_tracker_->GetNextSerial(SerialTracker::EventType::OTHER_EVENT),
        utf8.c_str(), utf8.c_str());

    wl_client_flush(client());
  }

  void Commit(std::u16string_view text) override {
    zwp_text_input_v1_send_commit_string(
        text_input_,
        serial_tracker_->GetNextSerial(SerialTracker::EventType::OTHER_EVENT),
        base::UTF16ToUTF8(text).c_str());
    wl_client_flush(client());
  }

  void SetCursor(std::u16string_view surrounding_text,
                 const gfx::Range& selection) override {
    std::vector<size_t> offsets{selection.start(), selection.end()};
    base::UTF16ToUTF8AndAdjustOffsets(surrounding_text, &offsets);
    zwp_text_input_v1_send_cursor_position(text_input_,
                                           static_cast<uint32_t>(offsets[1]),
                                           static_cast<uint32_t>(offsets[0]));
  }

  void DeleteSurroundingText(std::u16string_view surrounding_text,
                             const gfx::Range& range) override {
    std::vector<size_t> offsets{range.GetMin(), range.GetMax()};
    base::UTF16ToUTF8AndAdjustOffsets(surrounding_text, &offsets);
    // Currently, the arguments are conflicting with spec.
    // However, the only client, Lacros, also interprets wrongly in the same
    // way so just fixing here could cause visible regression.
    // TODO(crbug.com/40189286): Fix the behavior with versioning.
    zwp_text_input_v1_send_delete_surrounding_text(
        text_input_, static_cast<uint32_t>(offsets[0]),
        static_cast<uint32_t>(offsets[1] - offsets[0]));
    wl_client_flush(client());
  }

  void SendKey(const ui::KeyEvent& event) override {
    uint32_t keysym = xkb_tracker_->GetKeysym(
        ui::KeycodeConverter::DomCodeToNativeKeycode(event.code()));
    bool pressed = (event.type() == ui::EventType::kKeyPressed);
    zwp_text_input_v1_send_keysym(
        text_input_, TimeTicksToMilliseconds(event.time_stamp()),
        serial_tracker_->GetNextSerial(SerialTracker::EventType::OTHER_EVENT),
        keysym,
        pressed ? WL_KEYBOARD_KEY_STATE_PRESSED
                : WL_KEYBOARD_KEY_STATE_RELEASED,
        modifier_converter_.MaskFromUiFlags(event.flags()));
    wl_client_flush(client());
  }

  void OnTextDirectionChanged(base::i18n::TextDirection direction) override {
    uint32_t wayland_direction = ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_AUTO;
    switch (direction) {
      case base::i18n::RIGHT_TO_LEFT:
        wayland_direction = ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_LTR;
        break;
      case base::i18n::LEFT_TO_RIGHT:
        wayland_direction = ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_RTL;
        break;
      case base::i18n::UNKNOWN_DIRECTION:
        LOG(ERROR) << "Unrecognized direction: " << direction;
    }

    zwp_text_input_v1_send_text_direction(
        text_input_,
        serial_tracker_->GetNextSerial(SerialTracker::EventType::OTHER_EVENT),
        wayland_direction);
  }

  void SetCompositionFromExistingText(
      std::u16string_view surrounding_text,
      const gfx::Range& cursor,
      const gfx::Range& range,
      const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) override {
    if (!extended_text_input_)
      return;

    uint32_t begin = range.GetMin();
    uint32_t end = range.GetMax();
    SendPreeditStyle(surrounding_text.substr(begin, range.length()),
                     ui_ime_text_spans);

    std::vector<size_t> offsets = {begin, end, cursor.end()};
    base::UTF16ToUTF8AndAdjustOffsets(surrounding_text, &offsets);
    int32_t index =
        static_cast<int32_t>(offsets[0]) - static_cast<int32_t>(offsets[2]);
    uint32_t length = static_cast<uint32_t>(offsets[1] - offsets[0]);
    zcr_extended_text_input_v1_send_set_preedit_region(extended_text_input_,
                                                       index, length);
    wl_client_flush(client());
  }

  void ClearGrammarFragments(std::u16string_view surrounding_text,
                             const gfx::Range& range) override {
    if (!extended_text_input_)
      return;

    if (wl_resource_get_version(extended_text_input_) >=
        ZCR_EXTENDED_TEXT_INPUT_V1_CLEAR_GRAMMAR_FRAGMENTS_SINCE_VERSION) {
      std::vector<size_t> offsets = {range.start(), range.end()};
      base::UTF16ToUTF8AndAdjustOffsets(surrounding_text, &offsets);
      zcr_extended_text_input_v1_send_clear_grammar_fragments(
          extended_text_input_, static_cast<uint32_t>(offsets[0]),
          static_cast<uint32_t>(offsets[1]));
      wl_client_flush(client());
    }
  }

  void AddGrammarFragment(std::u16string_view surrounding_text,
                          const ui::GrammarFragment& fragment) override {
    if (!extended_text_input_)
      return;

    if (wl_resource_get_version(extended_text_input_) >=
        ZCR_EXTENDED_TEXT_INPUT_V1_ADD_GRAMMAR_FRAGMENT_SINCE_VERSION) {
      std::vector<size_t> offsets = {fragment.range.start(),
                                     fragment.range.end()};
      base::UTF16ToUTF8AndAdjustOffsets(surrounding_text, &offsets);
      zcr_extended_text_input_v1_send_add_grammar_fragment(
          extended_text_input_, static_cast<uint32_t>(offsets[0]),
          static_cast<uint32_t>(offsets[1]), fragment.suggestion.c_str());
      wl_client_flush(client());
    }
  }

  void SetAutocorrectRange(std::u16string_view surrounding_text,
                           const gfx::Range& range) override {
    if (!extended_text_input_) {
      return;
    }

    if (wl_resource_get_version(extended_text_input_) <
        ZCR_EXTENDED_TEXT_INPUT_V1_SET_AUTOCORRECT_RANGE_SINCE_VERSION) {
      return;
    }

    std::vector<size_t> offsets{range.GetMin(), range.GetMax()};
    base::UTF16ToUTF8AndAdjustOffsets(surrounding_text, &offsets);
    zcr_extended_text_input_v1_send_set_autocorrect_range(
        extended_text_input_, offsets[0], offsets[1]);
    wl_client_flush(client());
  }

  bool HasImageInsertSupport() override {
    if (!extended_text_input_) {
      return false;
    }

    return wl_resource_get_version(extended_text_input_) >=
           ZCR_EXTENDED_TEXT_INPUT_V1_INSERT_IMAGE_SINCE_VERSION;
  }

  void InsertImage(const GURL& src) override {
    if (!extended_text_input_) {
      return;
    }

    // Due to the limit of wayland protocol, we should check the size of
    // payload here.
    static constexpr size_t kSizeLimit = 4000;
    const size_t src_size = src.spec().size();
    if (src_size > kSizeLimit) {
      if (wl_resource_get_version(extended_text_input_) <
          ZCR_EXTENDED_TEXT_INPUT_V1_INSERT_IMAGE_WITH_LARGE_URL_SINCE_VERSION) {
        LOG(ERROR) << "Inserting image with large URL is not supported";
        return;
      }

      std::string mime_type, charset, raw_data;
      if (!net::DataURL::Parse(src, &mime_type, &charset, &raw_data)) {
        LOG(ERROR) << "Failed to parse data url";
        return;
      }

      base::ScopedFD memfd(memfd_create("inserting_image", MFD_CLOEXEC));
      if (!memfd.get()) {
        PLOG(ERROR) << "Failed to create memfd";
        return;
      }

      if (!base::WriteFileDescriptor(memfd.get(), raw_data)) {
        LOG(ERROR) << "Failed to write into memfd";
        return;
      }
      if (lseek(memfd.get(), 0, SEEK_SET) != 0) {
        LOG(ERROR) << "Failed to reset file descriptor";
        return;
      }
      zcr_extended_text_input_v1_send_insert_image_with_large_url(
          extended_text_input_, mime_type.c_str(), charset.c_str(), memfd.get(),
          raw_data.size());
      wl_client_flush(client());
      return;
    }

    if (wl_resource_get_version(extended_text_input_) >=
        ZCR_EXTENDED_TEXT_INPUT_V1_INSERT_IMAGE_SINCE_VERSION) {
      zcr_extended_text_input_v1_send_insert_image(extended_text_input_,
                                                   src.spec().c_str());
      wl_client_flush(client());
    }
  }

  void SendPreeditStyle(std::u16string_view text,
                        const std::vector<ui::ImeTextSpan>& spans) {
    if (spans.empty())
      return;

    // Convert all offsets from UTF16 to UTF8.
    std::vector<size_t> offsets;
    offsets.reserve(spans.size() * 2);
    for (const auto& span : spans) {
      auto minmax = std::minmax(span.start_offset, span.end_offset);
      offsets.push_back(minmax.first);
      offsets.push_back(minmax.second);
    }
    base::UTF16ToUTF8AndAdjustOffsets(text, &offsets);

    for (size_t i = 0; i < spans.size(); ++i) {
      if (offsets[i * 2] == std::string::npos ||
          offsets[i * 2 + 1] == std::string::npos) {
        // Invalid span is specified.
        continue;
      }
      const auto& span = spans[i];
      const uint32_t begin = offsets[i * 2];
      const uint32_t end = offsets[i * 2 + 1];

      uint32_t style = ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_DEFAULT;
      switch (span.type) {
        case ui::ImeTextSpan::Type::kComposition:
          if (span.thickness == ui::ImeTextSpan::Thickness::kThick) {
            style = ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_HIGHLIGHT;
          } else {
            style = ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_UNDERLINE;
          }
          break;
        case ui::ImeTextSpan::Type::kSuggestion:
          style = ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_SELECTION;
          break;
        case ui::ImeTextSpan::Type::kMisspellingSuggestion:
        case ui::ImeTextSpan::Type::kAutocorrect:
        case ui::ImeTextSpan::Type::kGrammarSuggestion:
          style = ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_INCORRECT;
          break;
      }
      zwp_text_input_v1_send_preedit_styling(text_input_, begin, end - begin,
                                             style);
    }
  }

  bool ConfirmComposition(bool keep_selection) override {
    if (!extended_text_input_) {
      return false;
    }

    if (wl_resource_get_version(extended_text_input_) <
        ZCR_EXTENDED_TEXT_INPUT_V1_CONFIRM_PREEDIT_SINCE_VERSION) {
      return false;
    }

    zcr_extended_text_input_v1_send_confirm_preedit(
        extended_text_input_,
        keep_selection
            ? ZCR_EXTENDED_TEXT_INPUT_V1_CONFIRM_PREEDIT_SELECTION_BEHAVIOR_UNCHANGED
            : ZCR_EXTENDED_TEXT_INPUT_V1_CONFIRM_PREEDIT_SELECTION_BEHAVIOR_AFTER_PREEDIT);
    wl_client_flush(client());
    return true;
  }

  bool SupportsConfirmPreedit() override {
    // Note: until this is supported by crostini, crostini won't be able to add
    // the new extension api.
    return extended_text_input_ &&
           wl_resource_get_version(extended_text_input_) >=
               ZCR_EXTENDED_TEXT_INPUT_V1_CONFIRM_PREEDIT_SINCE_VERSION;
  }

  raw_ptr<wl_resource, DanglingUntriaged> text_input_;
  raw_ptr<wl_resource, DanglingUntriaged> extended_text_input_ = nullptr;
  raw_ptr<wl_resource, DanglingUntriaged> surface_ = nullptr;

  // Owned by Seat, which is updated before calling the callbacks of this
  // class.
  const raw_ptr<const XkbTracker> xkb_tracker_;

  // Owned by Server, which always outlives this delegate.
  const raw_ptr<SerialTracker> serial_tracker_;
  ui::XkbModifierConverter modifier_converter_{
      std::vector<std::string>(std::begin(kModifierNames),
                               std::end(kModifierNames))};

  // Pending focus reason.
  ui::TextInputClient::FocusReason pending_focus_reason_ =
      ui::TextInputClient::FOCUS_REASON_OTHER;

  // Pending surrounding text supported flag.
  bool pending_surrounding_text_supported_ = true;
  std::optional<ui::GrammarFragment> pending_grammar_fragment_;
  std::optional<ui::AutocorrectInfo> pending_autocorrect_info_;
  std::optional<std::uint32_t> pending_surrounding_text_offset_utf16_;

  base::WeakPtrFactory<WaylandTextInputDelegate> weak_factory_{this};
};

// Holds WeakPtr to WaylandTextInputDelegate, and the lifetime of this class's
// instance is tied to zcr_extended_text_input connection.
// If text_input connection is destroyed earlier than extended_text_input,
// then delegate_ will return nullptr automatically.
class WaylandExtendedTextInput {
 public:
  explicit WaylandExtendedTextInput(
      base::WeakPtr<WaylandTextInputDelegate> delegate)
      : delegate_(delegate) {}
  WaylandExtendedTextInput(const WaylandExtendedTextInput&) = delete;
  WaylandExtendedTextInput& operator=(const WaylandExtendedTextInput&) = delete;
  ~WaylandExtendedTextInput() {
    if (delegate_)
      delegate_->set_extended_text_input(nullptr);
  }

  WaylandTextInputDelegate* delegate() { return delegate_.get(); }

 private:
  base::WeakPtr<WaylandTextInputDelegate> delegate_;
};

void SetSurroundingTextImpl(TextInput* text_input,
                            WaylandTextInputDelegate* delegate,
                            std::string_view text,
                            uint32_t cursor,
                            uint32_t anchor) {
  uint32_t offset_utf16 =
      delegate->TakeSurroundingTextOffsetUtf16().value_or(0u);
  auto grammar_fragment = delegate->TakeGrammarFragment();
  auto autocorrect_info = delegate->TakeAutocorrectInfo();

  // TODO(crbug.com/40189286): Selection range should keep cursor/anchor
  // relationship.
  auto minmax = std::minmax(cursor, anchor);
  std::vector<size_t> offsets{minmax.first, minmax.second};
  if (grammar_fragment.has_value()) {
    offsets.push_back(grammar_fragment->range.start());
    offsets.push_back(grammar_fragment->range.end());
  }
  if (autocorrect_info.has_value()) {
    offsets.push_back(autocorrect_info->range.start());
    offsets.push_back(autocorrect_info->range.end());
  }

  std::u16string u16_text = base::UTF8ToUTF16AndAdjustOffsets(text, &offsets);
  if (offsets[0] == std::u16string::npos ||
      offsets[1] == std::u16string::npos) {
    return;
  }

  if (grammar_fragment.has_value()) {
    grammar_fragment->range =
        gfx::Range(offsets[2] + offset_utf16, offsets[3] + offset_utf16);
  }

  // Original implementation did not convert the range. Guard this by the
  // feature flag to be reverted to old behavior just in case for transition
  // period.
  if (autocorrect_info.has_value()) {
    size_t index = grammar_fragment.has_value() ? 4u : 2u;
    autocorrect_info->range = gfx::Range(offsets[index] + offset_utf16,
                                         offsets[index + 1] + offset_utf16);
  }

  text_input->SetSurroundingText(
      u16_text, offset_utf16,
      gfx::Range(offsets[0] + offset_utf16, offsets[1] + offset_utf16),
      grammar_fragment, autocorrect_info);
}

void text_input_activate(wl_client* client,
                         wl_resource* resource,
                         wl_resource* seat_resource,
                         wl_resource* surface_resource) {
  TextInput* text_input = GetUserDataAs<TextInput>(resource);
  Surface* surface = GetUserDataAs<Surface>(surface_resource);
  Seat* seat = GetUserDataAs<WaylandSeat>(seat_resource)->seat;
  auto* delegate =
      static_cast<WaylandTextInputDelegate*>(text_input->delegate());
  delegate->set_surface(surface_resource);
  auto focus_reason = delegate->pending_focus_reason();
  delegate->set_pending_focus_reason(ui::TextInputClient::FOCUS_REASON_OTHER);
  text_input->Activate(seat, surface, focus_reason);

  // Sending modifiers.
  wl_array modifiers;
  wl_array_init(&modifiers);
  for (const char* modifier : kModifierNames) {
    char* p =
        static_cast<char*>(wl_array_add(&modifiers, ::strlen(modifier) + 1));
    UNSAFE_TODO(::strcpy(p, modifier));
  }
  zwp_text_input_v1_send_modifiers_map(resource, &modifiers);
  wl_array_release(&modifiers);
}

void text_input_deactivate(wl_client* client,
                           wl_resource* resource,
                           wl_resource* seat) {
  TextInput* text_input = GetUserDataAs<TextInput>(resource);
  auto* delegate =
      static_cast<WaylandTextInputDelegate*>(text_input->delegate());
  delegate->set_pending_focus_reason(ui::TextInputClient::FOCUS_REASON_OTHER);
  text_input->Deactivate();
}

void text_input_show_input_panel(wl_client* client, wl_resource* resource) {
  GetUserDataAs<TextInput>(resource)->ShowVirtualKeyboardIfEnabled();
}

void text_input_hide_input_panel(wl_client* client, wl_resource* resource) {
  GetUserDataAs<TextInput>(resource)->HideVirtualKeyboard();
}

void text_input_reset(wl_client* client, wl_resource* resource) {
  GetUserDataAs<TextInput>(resource)->Reset();
}

void text_input_set_surrounding_text(wl_client* client,
                                     wl_resource* resource,
                                     const char* text,
                                     uint32_t cursor,
                                     uint32_t anchor) {
  TextInput* text_input = GetUserDataAs<TextInput>(resource);
  auto* delegate =
      static_cast<WaylandTextInputDelegate*>(text_input->delegate());
  SetSurroundingTextImpl(text_input, delegate, text, cursor, anchor);
}

void text_input_set_content_type(wl_client* client,
                                 wl_resource* resource,
                                 uint32_t hint,
                                 uint32_t purpose) {
  TextInput* text_input = GetUserDataAs<TextInput>(resource);
  ui::TextInputType type = ui::TEXT_INPUT_TYPE_TEXT;
  ui::TextInputMode mode = ui::TEXT_INPUT_MODE_DEFAULT;
  int flags = ui::TEXT_INPUT_FLAG_NONE;
  bool should_do_learning = true;
  if (hint & ZWP_TEXT_INPUT_V1_CONTENT_HINT_AUTO_COMPLETION)
    flags |= ui::TEXT_INPUT_FLAG_AUTOCOMPLETE_ON;
  if (hint & ZWP_TEXT_INPUT_V1_CONTENT_HINT_AUTO_CORRECTION)
    flags |= ui::TEXT_INPUT_FLAG_AUTOCORRECT_ON;
  if (hint & ZWP_TEXT_INPUT_V1_CONTENT_HINT_AUTO_CAPITALIZATION)
    flags |= ui::TEXT_INPUT_FLAG_AUTOCAPITALIZE_SENTENCES;
  if (hint & ZWP_TEXT_INPUT_V1_CONTENT_HINT_LOWERCASE)
    flags |= ui::TEXT_INPUT_FLAG_AUTOCAPITALIZE_NONE;
  if (hint & ZWP_TEXT_INPUT_V1_CONTENT_HINT_UPPERCASE)
    flags |= ui::TEXT_INPUT_FLAG_AUTOCAPITALIZE_CHARACTERS;
  if (hint & ZWP_TEXT_INPUT_V1_CONTENT_HINT_TITLECASE)
    flags |= ui::TEXT_INPUT_FLAG_AUTOCAPITALIZE_WORDS;
  if (hint & ZWP_TEXT_INPUT_V1_CONTENT_HINT_HIDDEN_TEXT) {
    flags |= ui::TEXT_INPUT_FLAG_AUTOCOMPLETE_OFF |
             ui::TEXT_INPUT_FLAG_AUTOCORRECT_OFF;
  }
  if (hint & ZWP_TEXT_INPUT_V1_CONTENT_HINT_SENSITIVE_DATA)
    should_do_learning = false;
  // Unused hints: LATIN, MULTILINE.

  switch (purpose) {
    case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_DIGITS:
      mode = ui::TEXT_INPUT_MODE_DECIMAL;
      type = ui::TEXT_INPUT_TYPE_NUMBER;
      break;
    case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_NUMBER:
      mode = ui::TEXT_INPUT_MODE_NUMERIC;
      type = ui::TEXT_INPUT_TYPE_NUMBER;
      break;
    case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_PHONE:
      mode = ui::TEXT_INPUT_MODE_TEL;
      type = ui::TEXT_INPUT_TYPE_TELEPHONE;
      break;
    case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_URL:
      mode = ui::TEXT_INPUT_MODE_URL;
      type = ui::TEXT_INPUT_TYPE_URL;
      break;
    case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_EMAIL:
      mode = ui::TEXT_INPUT_MODE_EMAIL;
      type = ui::TEXT_INPUT_TYPE_EMAIL;
      break;
    case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_PASSWORD:
      should_do_learning = false;
      type = ui::TEXT_INPUT_TYPE_PASSWORD;
      break;
    case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_DATE:
      type = ui::TEXT_INPUT_TYPE_DATE;
      break;
    case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_TIME:
      type = ui::TEXT_INPUT_TYPE_TIME;
      break;
    case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_DATETIME:
      type = ui::TEXT_INPUT_TYPE_DATE_TIME;
      break;
    case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_NORMAL:
    case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_ALPHA:
    case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_NAME:
    case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_TERMINAL:
      // No special type / mode are set.
      break;
  }

  auto* delegate =
      static_cast<WaylandTextInputDelegate*>(text_input->delegate());
  bool surrounding_text_supported =
    delegate->pending_surrounding_text_supported();
  delegate->set_pending_surrounding_text_supported(/*is_supported = */ true);

  text_input->SetTypeModeFlags(type, mode, flags, should_do_learning,
                               /* can_compose_inline = */ true,
                               surrounding_text_supported);
}

void text_input_set_cursor_rectangle(wl_client* client,
                                     wl_resource* resource,
                                     int32_t x,
                                     int32_t y,
                                     int32_t width,
                                     int32_t height) {
  GetUserDataAs<TextInput>(resource)->SetCaretBounds(
      gfx::Rect(x, y, width, height));
}

void text_input_set_preferred_language(wl_client* client,
                                       wl_resource* resource,
                                       const char* language) {
  // Nothing needs to be done.
}

void text_input_commit_state(wl_client* client,
                             wl_resource* resource,
                             uint32_t serial) {
  // Nothing needs to be done.
}

void text_input_invoke_action(wl_client* client,
                              wl_resource* resource,
                              uint32_t button,
                              uint32_t index) {
  GetUserDataAs<TextInput>(resource)->Resync();
}

constexpr struct zwp_text_input_v1_interface text_input_v1_implementation = {
    text_input_activate,
    text_input_deactivate,
    text_input_show_input_panel,
    text_input_hide_input_panel,
    text_input_reset,
    text_input_set_surrounding_text,
    text_input_set_content_type,
    text_input_set_cursor_rectangle,
    text_input_set_preferred_language,
    text_input_commit_state,
    text_input_invoke_action,
};

////////////////////////////////////////////////////////////////////////////////
// text_input_manager_v1 interface:

void text_input_manager_create_text_input(wl_client* client,
                                          wl_resource* resource,
                                          uint32_t id) {
  auto* data = GetUserDataAs<WaylandTextInputManager>(resource);

  wl_resource* text_input_resource =
      wl_resource_create(client, &zwp_text_input_v1_interface, 1, id);

  SetImplementation(
      text_input_resource, &text_input_v1_implementation,
      std::make_unique<TextInput>(std::make_unique<WaylandTextInputDelegate>(
          text_input_resource, data->xkb_tracker, data->serial_tracker)));
}

constexpr struct zwp_text_input_manager_v1_interface
    text_input_manager_implementation = {
        text_input_manager_create_text_input,
};

////////////////////////////////////////////////////////////////////////////////
// extended_text_input_v1 interface:

void extended_text_input_destroy(wl_client* client, wl_resource* resource) {
  wl_resource_destroy(resource);
}

void extended_text_input_set_input_type(wl_client* client,
                                        wl_resource* resource,
                                        uint32_t input_type,
                                        uint32_t input_mode,
                                        uint32_t input_flags,
                                        uint32_t learning_mode,
                                        uint32_t inline_composition_support) {
  auto* delegate =
      GetUserDataAs<WaylandExtendedTextInput>(resource)->delegate();
  if (!delegate)
    return;

  // If unknown value is passed, fall back to the default one.
  auto ui_type =
      ui::wayland::ConvertToTextInputType(
          static_cast<zcr_extended_text_input_v1_input_type>(input_type))
          .value_or(ui::TEXT_INPUT_TYPE_TEXT);
  auto ui_mode =
      ui::wayland::ConvertToTextInputMode(
          static_cast<zcr_extended_text_input_v1_input_mode>(input_mode))
          .value_or(ui::TEXT_INPUT_MODE_DEFAULT);
  // Ignore unknown flags.
  auto ui_flags = ui::wayland::ConvertToTextInputFlags(input_flags).first;
  bool should_do_learning =
      learning_mode == ZCR_EXTENDED_TEXT_INPUT_V1_LEARNING_MODE_ENABLED;
  bool can_compose_inline =
      inline_composition_support ==
      ZCR_EXTENDED_TEXT_INPUT_V1_INLINE_COMPOSITION_SUPPORT_SUPPORTED;

  bool surrounding_text_supported =
    delegate->pending_surrounding_text_supported();
  delegate->set_pending_surrounding_text_supported(/*is_supported = */ true);

  auto* text_input = GetUserDataAs<TextInput>(delegate->resource());
  text_input->SetTypeModeFlags(ui_type, ui_mode, ui_flags, should_do_learning,
                               can_compose_inline, surrounding_text_supported);
}

void extended_text_input_deprecated_set_input_type(wl_client* client,
                                                   wl_resource* resource,
                                                   uint32_t input_type,
                                                   uint32_t input_mode,
                                                   uint32_t input_flags,
                                                   uint32_t learning_mode) {
  // TODO(crbug.com/40258785) This deprecated method signature is preserved to
  // maintain backwards compatibility with older client versions. Once both Exo
  // and Lacros have stabilized on the new API, delete this implementation or
  // otherwise make it impossible to call.
  extended_text_input_set_input_type(client, resource, input_type, input_mode,
                                     input_flags, learning_mode,
                                     /*inline_composition_support=*/true);
}

void extended_text_input_set_grammar_fragment_at_cursor(
    wl_client* client,
    wl_resource* resource,
    uint32_t start,
    uint32_t end,
    const char* suggestion) {
  auto* delegate =
      GetUserDataAs<WaylandExtendedTextInput>(resource)->delegate();
  if (!delegate) {
    return;
  }

  delegate->SetPendingGrammarFragment(
      start == end ? std::nullopt
                   : std::make_optional(ui::GrammarFragment(
                         gfx::Range(start, end), suggestion)));
}

void extended_text_input_set_autocorrect_info(wl_client* client,
                                              wl_resource* resource,
                                              uint32_t start,
                                              uint32_t end,
                                              uint32_t x,
                                              uint32_t y,
                                              uint32_t width,
                                              uint32_t height) {
  auto* delegate =
      GetUserDataAs<WaylandExtendedTextInput>(resource)->delegate();
  if (!delegate) {
    return;
  }

  delegate->SetPendingAutocorrectInfo(ui::AutocorrectInfo{
      gfx::Range(start, end),
      gfx::Rect(x, y, width, height),
  });
}

void extended_text_input_finalize_virtual_keyboard_changes(
    wl_client* client,
    wl_resource* resource) {
  auto* delegate =
      GetUserDataAs<WaylandExtendedTextInput>(resource)->delegate();
  if (!delegate)
    return;

  auto* text_input = GetUserDataAs<TextInput>(delegate->resource());
  text_input->FinalizeVirtualKeyboardChanges();
}

void extended_text_input_set_focus_reason(wl_client* client,
                                          wl_resource* resource,
                                          uint32_t reason) {
  ui::TextInputClient::FocusReason focus_reason;
  switch (reason) {
    case ZCR_EXTENDED_TEXT_INPUT_V1_FOCUS_REASON_TYPE_NONE:
      focus_reason = ui::TextInputClient::FOCUS_REASON_NONE;
      break;
    case ZCR_EXTENDED_TEXT_INPUT_V1_FOCUS_REASON_TYPE_MOUSE:
      focus_reason = ui::TextInputClient::FOCUS_REASON_MOUSE;
      break;
    case ZCR_EXTENDED_TEXT_INPUT_V1_FOCUS_REASON_TYPE_TOUCH:
      focus_reason = ui::TextInputClient::FOCUS_REASON_TOUCH;
      break;
    case ZCR_EXTENDED_TEXT_INPUT_V1_FOCUS_REASON_TYPE_PEN:
      focus_reason = ui::TextInputClient::FOCUS_REASON_PEN;
      break;
    case ZCR_EXTENDED_TEXT_INPUT_V1_FOCUS_REASON_TYPE_OTHER:
      focus_reason = ui::TextInputClient::FOCUS_REASON_OTHER;
      break;
    default:
      LOG(ERROR) << "Unknown focus reason: " << reason;
      return;
  }

  // Keep tracking in WaylandExtendedTextInput. This will be passed to
  // TextInput::Activate.
  auto* delegate =
      GetUserDataAs<WaylandExtendedTextInput>(resource)->delegate();
  if (!delegate) {
    return;
  }
  delegate->set_pending_focus_reason(focus_reason);
}

void extended_text_input_set_surrounding_text_support(wl_client* client,
                                                      wl_resource* resource,
                                                      uint32_t support) {
  auto* delegate =
      GetUserDataAs<WaylandExtendedTextInput>(resource)->delegate();
  if (!delegate) {
    return;
  }

  switch (support) {
    case ZCR_EXTENDED_TEXT_INPUT_V1_SURROUNDING_TEXT_SUPPORT_SUPPORTED:
      delegate->set_pending_surrounding_text_supported(/*is_supported=*/true);
      return;
    case ZCR_EXTENDED_TEXT_INPUT_V1_SURROUNDING_TEXT_SUPPORT_UNSUPPORTED:
      delegate->set_pending_surrounding_text_supported(/*is_supported=*/false);
      return;
    default:
      LOG(ERROR) << "Unknown surrounding_text_support: " << support;
      return;
  }
}

void extended_text_input_set_surrounding_text_offset_utf16(
    wl_client* client,
    wl_resource* resource,
    uint32_t offset_utf16) {
  auto* delegate =
      GetUserDataAs<WaylandExtendedTextInput>(resource)->delegate();
  if (!delegate) {
    return;
  }

  delegate->SetSurroundingTextOffsetUtf16(offset_utf16);
}

void extended_text_input_set_large_surrounding_text(wl_client* client,
                                                    wl_resource* resource,
                                                    int32_t raw_fd,
                                                    uint32_t size,
                                                    uint32_t cursor,
                                                    uint32_t anchor) {
  std::string text;
  {
    text.resize(size);
    base::ScopedFD fd(raw_fd);
    if (!base::ReadFromFD(fd.get(), text)) {
      PLOG(ERROR) << "Failed to read file descriptor for surrounding text";
      return;
    }
  }

  auto* delegate =
      GetUserDataAs<WaylandExtendedTextInput>(resource)->delegate();
  if (!delegate) {
    return;
  }
  auto* text_input = GetUserDataAs<TextInput>(delegate->resource());
  if (!text_input) {
    return;
  }
  SetSurroundingTextImpl(text_input, delegate, text, cursor, anchor);
}

constexpr struct zcr_extended_text_input_v1_interface
    extended_text_input_implementation = {
        extended_text_input_destroy,
        extended_text_input_deprecated_set_input_type,
        extended_text_input_set_grammar_fragment_at_cursor,
        extended_text_input_set_autocorrect_info,
        extended_text_input_finalize_virtual_keyboard_changes,
        extended_text_input_set_focus_reason,
        extended_text_input_set_input_type,
        extended_text_input_set_surrounding_text_support,
        extended_text_input_set_surrounding_text_offset_utf16,
        extended_text_input_set_large_surrounding_text,
};

////////////////////////////////////////////////////////////////////////////////
// text_input_extension_v1 interface:

void text_input_extension_get_extended_text_input(
    wl_client* client,
    wl_resource* resource,
    uint32_t id,
    wl_resource* text_input_resource) {
  TextInput* text_input = GetUserDataAs<TextInput>(text_input_resource);
  auto* delegate =
      static_cast<WaylandTextInputDelegate*>(text_input->delegate());
  if (delegate->has_extended_text_input()) {
    wl_resource_post_error(
        resource, ZCR_TEXT_INPUT_EXTENSION_V1_ERROR_EXTENDED_TEXT_INPUT_EXISTS,
        "text_input has already been associated with a extended_text_input "
        "object");
    return;
  }

  uint32_t version = wl_resource_get_version(resource);
  wl_resource* extended_text_input_resource = wl_resource_create(
      client, &zcr_extended_text_input_v1_interface, version, id);

  delegate->set_extended_text_input(extended_text_input_resource);

  SetImplementation(
      extended_text_input_resource, &extended_text_input_implementation,
      std::make_unique<WaylandExtendedTextInput>(delegate->GetWeakPtr()));
}

constexpr struct zcr_text_input_extension_v1_interface
    text_input_extension_implementation = {
        text_input_extension_get_extended_text_input};

}  // namespace

void bind_text_input_manager(wl_client* client,
                             void* data,
                             uint32_t version,
                             uint32_t id) {
  wl_resource* resource =
      wl_resource_create(client, &zwp_text_input_manager_v1_interface, 1, id);
  wl_resource_set_implementation(resource, &text_input_manager_implementation,
                                 data, nullptr);
}

void bind_text_input_extension(wl_client* client,
                               void* data,
                               uint32_t version,
                               uint32_t id) {
  wl_resource* resource = wl_resource_create(
      client, &zcr_text_input_extension_v1_interface, version, id);
  wl_resource_set_implementation(resource, &text_input_extension_implementation,
                                 data, nullptr);
}

}  // namespace wayland
}  // namespace exo
