/*
 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved.
 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "core/editing/InputMethodController.h"

#include "core/InputModeNames.h"
#include "core/InputTypeNames.h"
#include "core/dom/Document.h"
#include "core/dom/Element.h"
#include "core/dom/Text.h"
#include "core/editing/EditingUtilities.h"
#include "core/editing/Editor.h"
#include "core/editing/commands/TypingCommand.h"
#include "core/editing/markers/DocumentMarkerController.h"
#include "core/events/CompositionEvent.h"
#include "core/frame/LocalFrame.h"
#include "core/html/HTMLInputElement.h"
#include "core/html/HTMLTextAreaElement.h"
#include "core/input/EventHandler.h"
#include "core/layout/LayoutObject.h"
#include "core/layout/LayoutTheme.h"
#include "core/page/ChromeClient.h"

namespace blink {

namespace {

void dispatchCompositionUpdateEvent(LocalFrame& frame, const String& text) {
  Element* target = frame.document()->focusedElement();
  if (!target)
    return;

  CompositionEvent* event = CompositionEvent::create(
      EventTypeNames::compositionupdate, frame.domWindow(), text);
  target->dispatchEvent(event);
}

void dispatchCompositionEndEvent(LocalFrame& frame, const String& text) {
  Element* target = frame.document()->focusedElement();
  if (!target)
    return;

  CompositionEvent* event = CompositionEvent::create(
      EventTypeNames::compositionend, frame.domWindow(), text);
  target->dispatchEvent(event);
}

// Used to insert/replace text during composition update and confirm
// composition.
// Procedure:
//   1. Fire 'beforeinput' event for (TODO(chongz): deleted composed text) and
//      inserted text
//   2. Fire 'compositionupdate' event
//   3. Fire TextEvent and modify DOM
//   TODO(chongz): 4. Fire 'input' event
void insertTextDuringCompositionWithEvents(
    LocalFrame& frame,
    const String& text,
    TypingCommand::Options options,
    TypingCommand::TextCompositionType compositionType) {
  DCHECK(compositionType ==
             TypingCommand::TextCompositionType::TextCompositionUpdate ||
         compositionType ==
             TypingCommand::TextCompositionType::TextCompositionConfirm)
      << "compositionType should be TextCompositionUpdate or "
         "TextCompositionConfirm, but got "
      << static_cast<int>(compositionType);
  if (!frame.document())
    return;

  Element* target = frame.document()->focusedElement();
  if (!target)
    return;

  // TODO(chongz): Fire 'beforeinput' for the composed text being
  // replaced/deleted.

  // Only the last confirmed text is cancelable.
  InputEvent::EventCancelable beforeInputCancelable =
      (compositionType ==
       TypingCommand::TextCompositionType::TextCompositionUpdate)
          ? InputEvent::EventCancelable::NotCancelable
          : InputEvent::EventCancelable::IsCancelable;
  DispatchEventResult result = dispatchBeforeInputFromComposition(
      target, InputEvent::InputType::InsertText, text, beforeInputCancelable);

  if (beforeInputCancelable == InputEvent::EventCancelable::IsCancelable &&
      result != DispatchEventResult::NotCanceled)
    return;

  // 'beforeinput' event handler may destroy document.
  if (!frame.document())
    return;

  dispatchCompositionUpdateEvent(frame, text);
  // 'compositionupdate' event handler may destroy document.
  if (!frame.document())
    return;

  switch (compositionType) {
    case TypingCommand::TextCompositionType::TextCompositionUpdate:
      TypingCommand::insertText(*frame.document(), text, options,
                                compositionType);
      break;
    case TypingCommand::TextCompositionType::TextCompositionConfirm:
      // TODO(chongz): Use TypingCommand::insertText after TextEvent was
      // removed. (Removed from spec since 2012)
      // See TextEvent.idl.
      frame.eventHandler().handleTextInputEvent(text, 0,
                                                TextEventInputComposition);
      break;
    default:
      NOTREACHED();
  }
  // TODO(chongz): Fire 'input' event.
}

}  // anonymous namespace

InputMethodController* InputMethodController::create(LocalFrame& frame) {
  return new InputMethodController(frame);
}

InputMethodController::InputMethodController(LocalFrame& frame)
    : m_frame(&frame), m_isDirty(false), m_hasComposition(false) {}

bool InputMethodController::hasComposition() const {
  return m_hasComposition;
}

inline Editor& InputMethodController::editor() const {
  return frame().editor();
}

void InputMethodController::clear() {
  m_hasComposition = false;
  if (m_compositionRange) {
    m_compositionRange->setStart(frame().document(), 0);
    m_compositionRange->collapse(true);
  }
  frame().document()->markers().removeMarkers(DocumentMarker::Composition);
  m_isDirty = false;
}

void InputMethodController::documentDetached() {
  clear();
  m_compositionRange = nullptr;
}

void InputMethodController::selectComposition() const {
  const EphemeralRange range = compositionEphemeralRange();
  if (range.isNull())
    return;

  // The composition can start inside a composed character sequence, so we have
  // to override checks. See <http://bugs.webkit.org/show_bug.cgi?id=15781>
  VisibleSelection selection;
  selection.setWithoutValidation(range.startPosition(), range.endPosition());
  frame().selection().setSelection(selection, 0);
}

bool InputMethodController::finishComposingText(
    ConfirmCompositionBehavior confirmBehavior) {
  if (!hasComposition())
    return false;

  if (confirmBehavior == KeepSelection) {
    PlainTextRange oldOffsets = getSelectionOffsets();
    Editor::RevealSelectionScope revealSelectionScope(&editor());

    bool result = replaceComposition(composingText());

    // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
    // needs to be audited. see http://crbug.com/590369 for more details.
    frame().document()->updateStyleAndLayoutIgnorePendingStylesheets();

    setSelectionOffsets(oldOffsets);
    return result;
  }

  return replaceCompositionAndMoveCaret(composingText(), 0);
}

bool InputMethodController::commitText(const String& text,
                                       int relativeCaretPosition) {
  if (hasComposition())
    return replaceCompositionAndMoveCaret(text, relativeCaretPosition);

  // We should do nothing in this case, because:
  // 1. No need to insert text when text is empty.
  // 2. Shouldn't move caret when relativeCaretPosition == 0 to avoid
  // duplicate selection change event.
  if (!text.length() && !relativeCaretPosition)
    return false;
  return insertTextAndMoveCaret(text, relativeCaretPosition);
}

bool InputMethodController::replaceComposition(const String& text) {
  if (!hasComposition())
    return false;

  // If the composition was set from existing text and didn't change, then
  // there's nothing to do here (and we should avoid doing anything as that
  // may clobber multi-node styled text).
  if (!m_isDirty && composingText() == text) {
    clear();
    return true;
  }

  // Select the text that will be deleted or replaced.
  selectComposition();

  if (frame().selection().isNone())
    return false;

  if (!frame().document())
    return false;

  // If text is empty, then delete the old composition here. If text is
  // non-empty, InsertTextCommand::input will delete the old composition with
  // an optimized replace operation.
  if (text.isEmpty())
    TypingCommand::deleteSelection(*frame().document(), 0);

  clear();

  insertTextDuringCompositionWithEvents(
      frame(), text, 0,
      TypingCommand::TextCompositionType::TextCompositionConfirm);
  // Event handler might destroy document.
  if (!frame().document())
    return false;

  // No DOM update after 'compositionend'.
  dispatchCompositionEndEvent(frame(), text);

  return true;
}

// relativeCaretPosition is relative to the end of the text.
static int computeAbsoluteCaretPosition(size_t textStart,
                                        size_t textLength,
                                        int relativeCaretPosition) {
  return textStart + textLength + relativeCaretPosition;
}

bool InputMethodController::replaceCompositionAndMoveCaret(
    const String& text,
    int relativeCaretPosition) {
  Element* rootEditableElement = frame().selection().rootEditableElement();
  if (!rootEditableElement)
    return false;
  PlainTextRange compositionRange =
      PlainTextRange::create(*rootEditableElement, *m_compositionRange);
  if (compositionRange.isNull())
    return false;
  int textStart = compositionRange.start();

  if (!replaceComposition(text))
    return false;

  int absoluteCaretPosition = computeAbsoluteCaretPosition(
      textStart, text.length(), relativeCaretPosition);
  return moveCaret(absoluteCaretPosition);
}

bool InputMethodController::insertText(const String& text) {
  if (dispatchBeforeInputInsertText(frame().document()->focusedElement(),
                                    text) != DispatchEventResult::NotCanceled)
    return false;
  editor().insertText(text, 0);
  return true;
}

bool InputMethodController::insertTextAndMoveCaret(const String& text,
                                                   int relativeCaretPosition) {
  PlainTextRange selectionRange = getSelectionOffsets();
  if (selectionRange.isNull())
    return false;
  int textStart = selectionRange.start();

  if (text.length()) {
    if (!insertText(text))
      return false;
  }

  int absoluteCaretPosition = computeAbsoluteCaretPosition(
      textStart, text.length(), relativeCaretPosition);
  return moveCaret(absoluteCaretPosition);
}

void InputMethodController::cancelComposition() {
  if (!hasComposition())
    return;

  Editor::RevealSelectionScope revealSelectionScope(&editor());

  if (frame().selection().isNone())
    return;

  clear();

  // TODO(chongz): Figure out which InputType should we use here.
  dispatchBeforeInputFromComposition(
      frame().document()->focusedElement(),
      InputEvent::InputType::DeleteComposedCharacterBackward, nullAtom,
      InputEvent::EventCancelable::NotCancelable);
  dispatchCompositionUpdateEvent(frame(), emptyString());
  insertTextDuringCompositionWithEvents(
      frame(), emptyString(), 0,
      TypingCommand::TextCompositionType::TextCompositionConfirm);
  // Event handler might destroy document.
  if (!frame().document())
    return;

  // An open typing command that disagrees about current selection would cause
  // issues with typing later on.
  TypingCommand::closeTyping(m_frame);

  // No DOM update after 'compositionend'.
  dispatchCompositionEndEvent(frame(), emptyString());
}

void InputMethodController::cancelCompositionIfSelectionIsInvalid() {
  if (!hasComposition() || editor().preventRevealSelection())
    return;

  // Check if selection start and selection end are valid.
  FrameSelection& selection = frame().selection();
  if (!selection.isNone() && !m_compositionRange->collapsed()) {
    if (selection.start().compareTo(m_compositionRange->startPosition()) >= 0 &&
        selection.end().compareTo(m_compositionRange->endPosition()) <= 0)
      return;
  }

  cancelComposition();
  frame().chromeClient().didCancelCompositionOnSelectionChange();
}

static size_t computeCommonPrefixLength(const String& str1,
                                        const String& str2) {
  const size_t maxCommonPrefixLength = std::min(str1.length(), str2.length());
  for (size_t index = 0; index < maxCommonPrefixLength; ++index) {
    if (str1[index] != str2[index])
      return index;
  }
  return maxCommonPrefixLength;
}

static size_t computeCommonSuffixLength(const String& str1,
                                        const String& str2) {
  const size_t length1 = str1.length();
  const size_t length2 = str2.length();
  const size_t maxCommonSuffixLength = std::min(length1, length2);
  for (size_t index = 0; index < maxCommonSuffixLength; ++index) {
    if (str1[length1 - index - 1] != str2[length2 - index - 1])
      return index;
  }
  return maxCommonSuffixLength;
}

// If current position is at grapheme boundary, return 0; otherwise, return the
// distance to its nearest left grapheme boundary.
static size_t computeDistanceToLeftGraphemeBoundary(const Position& position) {
  const Position& adjustedPosition = previousPositionOf(
      nextPositionOf(position, PositionMoveType::GraphemeCluster),
      PositionMoveType::GraphemeCluster);
  DCHECK_EQ(position.anchorNode(), adjustedPosition.anchorNode());
  DCHECK_GE(position.computeOffsetInContainerNode(),
            adjustedPosition.computeOffsetInContainerNode());
  return static_cast<size_t>(position.computeOffsetInContainerNode() -
                             adjustedPosition.computeOffsetInContainerNode());
}

static size_t computeCommonGraphemeClusterPrefixLengthForSetComposition(
    const String& oldText,
    const String& newText,
    const Element* rootEditableElement) {
  const size_t commonPrefixLength = computeCommonPrefixLength(oldText, newText);

  // For grapheme cluster, we should adjust it for grapheme boundary.
  const EphemeralRange& range =
      PlainTextRange(0, commonPrefixLength).createRange(*rootEditableElement);
  if (range.isNull())
    return 0;
  const Position& position = range.endPosition();
  const size_t diff = computeDistanceToLeftGraphemeBoundary(position);
  DCHECK_GE(commonPrefixLength, diff);
  return commonPrefixLength - diff;
}

// If current position is at grapheme boundary, return 0; otherwise, return the
// distance to its nearest right grapheme boundary.
static size_t computeDistanceToRightGraphemeBoundary(const Position& position) {
  const Position& adjustedPosition = nextPositionOf(
      previousPositionOf(position, PositionMoveType::GraphemeCluster),
      PositionMoveType::GraphemeCluster);
  DCHECK_EQ(position.anchorNode(), adjustedPosition.anchorNode());
  DCHECK_GE(adjustedPosition.computeOffsetInContainerNode(),
            position.computeOffsetInContainerNode());
  return static_cast<size_t>(adjustedPosition.computeOffsetInContainerNode() -
                             position.computeOffsetInContainerNode());
}

static size_t computeCommonGraphemeClusterSuffixLengthForSetComposition(
    const String& oldText,
    const String& newText,
    const Element* rootEditableElement) {
  const size_t commonSuffixLength = computeCommonSuffixLength(oldText, newText);

  // For grapheme cluster, we should adjust it for grapheme boundary.
  const EphemeralRange& range =
      PlainTextRange(0, oldText.length() - commonSuffixLength)
          .createRange(*rootEditableElement);
  if (range.isNull())
    return 0;
  const Position& position = range.endPosition();
  const size_t diff = computeDistanceToRightGraphemeBoundary(position);
  DCHECK_GE(commonSuffixLength, diff);
  return commonSuffixLength - diff;
}

void InputMethodController::setCompositionWithIncrementalText(
    const String& text,
    const Vector<CompositionUnderline>& underlines,
    int selectionStart,
    int selectionEnd) {
  Element* editable = frame().selection().rootEditableElement();
  if (!editable)
    return;

  DCHECK_LE(selectionStart, selectionEnd);
  String composing = composingText();
  const size_t commonPrefixLength =
      computeCommonGraphemeClusterPrefixLengthForSetComposition(composing, text,
                                                                editable);

  // We should ignore common prefix when finding common suffix.
  const size_t commonSuffixLength =
      computeCommonGraphemeClusterSuffixLengthForSetComposition(
          composing.right(composing.length() - commonPrefixLength),
          text.right(text.length() - commonPrefixLength), editable);

  const bool inserting =
      text.length() > commonPrefixLength + commonSuffixLength;
  const bool deleting =
      composing.length() > commonPrefixLength + commonSuffixLength;

  if (inserting || deleting) {
    // Select the text to be deleted.
    const size_t compositionStart =
        PlainTextRange::create(*editable, compositionEphemeralRange()).start();
    const size_t deletionStart = compositionStart + commonPrefixLength;
    const size_t deletionEnd =
        compositionStart + composing.length() - commonSuffixLength;
    const EphemeralRange& deletionRange =
        PlainTextRange(deletionStart, deletionEnd).createRange(*editable);
    VisibleSelection selection;
    selection.setWithoutValidation(deletionRange.startPosition(),
                                   deletionRange.endPosition());
    Document* const currentDocument = frame().document();
    frame().selection().setSelection(selection, 0);
    clear();

    // FrameSeleciton::setSelection() can change document associate to |frame|.
    if (currentDocument != frame().document())
      return;
    if (!currentDocument->focusedElement())
      return;

    // Insert the incremental text.
    const size_t insertionLength =
        text.length() - commonPrefixLength - commonSuffixLength;
    const String& insertingText =
        text.substring(commonPrefixLength, insertionLength);
    insertTextDuringCompositionWithEvents(frame(), insertingText,
                                          TypingCommand::PreventSpellChecking,
                                          TypingCommand::TextCompositionUpdate);

    // Event handlers might destroy document.
    if (currentDocument != frame().document())
      return;

    // TODO(yosin): The use of updateStyleAndLayoutIgnorePendingStylesheets
    // needs to be audited. see http://crbug.com/590369 for more details.
    frame().document()->updateStyleAndLayoutIgnorePendingStylesheets();

    // Now recreate the composition starting at its original start, and
    // apply the specified final selection offsets.
    setCompositionFromExistingText(underlines, compositionStart,
                                   compositionStart + text.length());
  }

  selectComposition();

  // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited. see http://crbug.com/590369 for more details.
  frame().document()->updateStyleAndLayoutIgnorePendingStylesheets();

  const PlainTextRange& selectedRange = createSelectionRangeForSetComposition(
      selectionStart, selectionEnd, text.length());
  // We shouldn't close typing in the middle of setComposition.
  setEditableSelectionOffsets(selectedRange, NotUserTriggered);
  m_isDirty = true;
}

void InputMethodController::setComposition(
    const String& text,
    const Vector<CompositionUnderline>& underlines,
    int selectionStart,
    int selectionEnd) {
  Editor::RevealSelectionScope revealSelectionScope(&editor());

  // Updates styles before setting selection for composition to prevent
  // inserting the previous composition text into text nodes oddly.
  // See https://bugs.webkit.org/show_bug.cgi?id=46868
  frame().document()->updateStyleAndLayoutTree();

  // When the IME only wants to change a few characters at the end of the
  // composition, only touch those characters in order to preserve rich text
  // substructure.
  if (hasComposition() && text.length()) {
    return setCompositionWithIncrementalText(text, underlines, selectionStart,
                                             selectionEnd);
  }

  selectComposition();

  if (frame().selection().isNone())
    return;

  Element* target = frame().document()->focusedElement();
  if (!target)
    return;

  // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited. see http://crbug.com/590369 for more details.
  frame().document()->updateStyleAndLayoutIgnorePendingStylesheets();

  PlainTextRange selectedRange = createSelectionRangeForSetComposition(
      selectionStart, selectionEnd, text.length());

  // Dispatch an appropriate composition event to the focused node.
  // We check the composition status and choose an appropriate composition event
  // since this function is used for three purposes:
  // 1. Starting a new composition.
  //    Send a compositionstart and a compositionupdate event when this function
  //    creates a new composition node, i.e. !hasComposition() &&
  //    !text.isEmpty().
  //    Sending a compositionupdate event at this time ensures that at least one
  //    compositionupdate event is dispatched.
  // 2. Updating the existing composition node.
  //    Send a compositionupdate event when this function updates the existing
  //    composition node, i.e. hasComposition() && !text.isEmpty().
  // 3. Canceling the ongoing composition.
  //    Send a compositionend event when function deletes the existing
  //    composition node, i.e. !hasComposition() && test.isEmpty().
  if (text.isEmpty()) {
    if (hasComposition()) {
      Editor::RevealSelectionScope revealSelectionScope(&editor());
      replaceComposition(emptyString());
    } else {
      // It's weird to call |setComposition()| with empty text outside
      // composition, however some IME (e.g. Japanese IBus-Anthy) did this, so
      // we simply delete selection without sending extra events.
      TypingCommand::deleteSelection(*frame().document(),
                                     TypingCommand::PreventSpellChecking);
    }

    // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
    // needs to be audited. see http://crbug.com/590369 for more details.
    frame().document()->updateStyleAndLayoutIgnorePendingStylesheets();

    setEditableSelectionOffsets(selectedRange);
    return;
  }

  // We should send a 'compositionstart' event only when the given text is not
  // empty because this function doesn't create a composition node when the text
  // is empty.
  if (!hasComposition()) {
    target->dispatchEvent(
        CompositionEvent::create(EventTypeNames::compositionstart,
                                 frame().domWindow(), frame().selectedText()));
    if (!frame().document())
      return;
  }

  DCHECK(!text.isEmpty());

  clear();

  insertTextDuringCompositionWithEvents(
      frame(), text,
      TypingCommand::SelectInsertedText | TypingCommand::PreventSpellChecking,
      TypingCommand::TextCompositionUpdate);
  // Event handlers might destroy document.
  if (!frame().document())
    return;

  // TODO(yosin): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited. see http://crbug.com/590369 for more details.
  frame().document()->updateStyleAndLayoutIgnorePendingStylesheets();

  // Find out what node has the composition now.
  Position base = mostForwardCaretPosition(frame().selection().base());
  Node* baseNode = base.anchorNode();
  if (!baseNode || !baseNode->isTextNode())
    return;

  Position extent = frame().selection().extent();
  Node* extentNode = extent.anchorNode();
  if (baseNode != extentNode)
    return;

  unsigned extentOffset = extent.computeOffsetInContainerNode();
  unsigned baseOffset = base.computeOffsetInContainerNode();
  if (baseOffset + text.length() != extentOffset)
    return;

  m_isDirty = true;
  m_hasComposition = true;
  if (!m_compositionRange)
    m_compositionRange = Range::create(baseNode->document());
  m_compositionRange->setStart(baseNode, baseOffset);
  m_compositionRange->setEnd(baseNode, extentOffset);

  if (baseNode->layoutObject())
    baseNode->layoutObject()->setShouldDoFullPaintInvalidation();

  // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited. see http://crbug.com/590369 for more details.
  frame().document()->updateStyleAndLayoutIgnorePendingStylesheets();

  // We shouldn't close typing in the middle of setComposition.
  setEditableSelectionOffsets(selectedRange, NotUserTriggered);

  if (underlines.isEmpty()) {
    frame().document()->markers().addCompositionMarker(
        m_compositionRange->startPosition(), m_compositionRange->endPosition(),
        Color::black, false,
        LayoutTheme::theme().platformDefaultCompositionBackgroundColor());
    return;
  }
  for (const auto& underline : underlines) {
    unsigned underlineStart = baseOffset + underline.startOffset();
    unsigned underlineEnd = baseOffset + underline.endOffset();
    EphemeralRange ephemeralLineRange = EphemeralRange(
        Position(baseNode, underlineStart), Position(baseNode, underlineEnd));
    if (ephemeralLineRange.isNull())
      continue;
    frame().document()->markers().addCompositionMarker(
        ephemeralLineRange.startPosition(), ephemeralLineRange.endPosition(),
        underline.color(), underline.thick(), underline.backgroundColor());
  }
}

PlainTextRange InputMethodController::createSelectionRangeForSetComposition(
    int selectionStart,
    int selectionEnd,
    size_t textLength) const {
  const int selectionOffsetsStart =
      static_cast<int>(getSelectionOffsets().start());
  const int start = selectionOffsetsStart + selectionStart;
  const int end = selectionOffsetsStart + selectionEnd;
  return createRangeForSelection(start, end, textLength);
}

void InputMethodController::setCompositionFromExistingText(
    const Vector<CompositionUnderline>& underlines,
    unsigned compositionStart,
    unsigned compositionEnd) {
  Element* editable = frame().selection().rootEditableElement();
  if (!editable)
    return;

  DCHECK(!editable->document().needsLayoutTreeUpdate());

  const EphemeralRange range =
      PlainTextRange(compositionStart, compositionEnd).createRange(*editable);
  if (range.isNull())
    return;

  const Position start = range.startPosition();
  if (rootEditableElementOf(start) != editable)
    return;

  const Position end = range.endPosition();
  if (rootEditableElementOf(end) != editable)
    return;

  clear();

  for (const auto& underline : underlines) {
    unsigned underlineStart = compositionStart + underline.startOffset();
    unsigned underlineEnd = compositionStart + underline.endOffset();
    EphemeralRange ephemeralLineRange =
        PlainTextRange(underlineStart, underlineEnd).createRange(*editable);
    if (ephemeralLineRange.isNull())
      continue;
    frame().document()->markers().addCompositionMarker(
        ephemeralLineRange.startPosition(), ephemeralLineRange.endPosition(),
        underline.color(), underline.thick(), underline.backgroundColor());
  }

  m_hasComposition = true;
  if (!m_compositionRange)
    m_compositionRange = Range::create(range.document());
  m_compositionRange->setStart(range.startPosition());
  m_compositionRange->setEnd(range.endPosition());
}

EphemeralRange InputMethodController::compositionEphemeralRange() const {
  if (!hasComposition())
    return EphemeralRange();
  return EphemeralRange(m_compositionRange.get());
}

Range* InputMethodController::compositionRange() const {
  return hasComposition() ? m_compositionRange : nullptr;
}

String InputMethodController::composingText() const {
  DocumentLifecycle::DisallowTransitionScope disallowTransition(
      frame().document()->lifecycle());
  return plainText(compositionEphemeralRange(), TextIteratorEmitsOriginalText);
}

PlainTextRange InputMethodController::getSelectionOffsets() const {
  EphemeralRange range = firstEphemeralRangeOf(frame().selection().selection());
  if (range.isNull())
    return PlainTextRange();
  ContainerNode* editable =
      frame().selection().rootEditableElementOrTreeScopeRootNode();
  DCHECK(editable);
  return PlainTextRange::create(*editable, range);
}

bool InputMethodController::setSelectionOffsets(
    const PlainTextRange& selectionOffsets,
    FrameSelection::SetSelectionOptions options) {
  if (selectionOffsets.isNull())
    return false;
  Element* rootEditableElement = frame().selection().rootEditableElement();
  if (!rootEditableElement)
    return false;

  DCHECK(!rootEditableElement->document().needsLayoutTreeUpdate());

  const EphemeralRange range =
      selectionOffsets.createRange(*rootEditableElement);
  if (range.isNull())
    return false;

  return frame().selection().setSelectedRange(
      range, VP_DEFAULT_AFFINITY, SelectionDirectionalMode::NonDirectional,
      options);
}

bool InputMethodController::setEditableSelectionOffsets(
    const PlainTextRange& selectionOffsets,
    FrameSelection::SetSelectionOptions options) {
  if (!editor().canEdit())
    return false;
  return setSelectionOffsets(selectionOffsets, options);
}

PlainTextRange InputMethodController::createRangeForSelection(
    int start,
    int end,
    size_t textLength) const {
  // In case of exceeding the left boundary.
  start = std::max(start, 0);
  end = std::max(end, start);

  Element* rootEditableElement = frame().selection().rootEditableElement();
  if (!rootEditableElement)
    return PlainTextRange();
  const EphemeralRange& range =
      EphemeralRange::rangeOfContents(*rootEditableElement);
  if (range.isNull())
    return PlainTextRange();

  const TextIteratorBehaviorFlags behaviorFlags =
      TextIteratorEmitsObjectReplacementCharacter |
      TextIteratorEmitsCharactersBetweenAllVisiblePositions;
  TextIterator it(range.startPosition(), range.endPosition(), behaviorFlags);

  int rightBoundary = 0;
  for (; !it.atEnd(); it.advance())
    rightBoundary += it.length();

  if (hasComposition())
    rightBoundary -= compositionRange()->text().length();

  rightBoundary += textLength;

  // In case of exceeding the right boundary.
  start = std::min(start, rightBoundary);
  end = std::min(end, rightBoundary);

  return PlainTextRange(start, end);
}

bool InputMethodController::moveCaret(int newCaretPosition) {
  frame().document()->updateStyleAndLayoutIgnorePendingStylesheets();
  PlainTextRange selectedRange =
      createRangeForSelection(newCaretPosition, newCaretPosition, 0);
  if (selectedRange.isNull())
    return false;
  return setEditableSelectionOffsets(selectedRange);
}

void InputMethodController::extendSelectionAndDelete(int before, int after) {
  if (!editor().canEdit())
    return;
  PlainTextRange selectionOffsets(getSelectionOffsets());
  if (selectionOffsets.isNull())
    return;

  // A common call of before=1 and after=0 will fail if the last character
  // is multi-code-word UTF-16, including both multi-16bit code-points and
  // Unicode combining character sequences of multiple single-16bit code-
  // points (officially called "compositions"). Try more until success.
  // http://crbug.com/355995
  //
  // FIXME: Note that this is not an ideal solution when this function is
  // called to implement "backspace". In that case, there should be some call
  // that will not delete a full multi-code-point composition but rather
  // only the last code-point so that it's possible for a user to correct
  // a composition without starting it from the beginning.
  // http://crbug.com/37993
  do {
    if (!setSelectionOffsets(PlainTextRange(
            std::max(static_cast<int>(selectionOffsets.start()) - before, 0),
            selectionOffsets.end() + after)))
      return;
    if (before == 0)
      break;
    ++before;
  } while (frame().selection().start() == frame().selection().end() &&
           before <= static_cast<int>(selectionOffsets.start()));
  // TODO(chongz): Find a way to distinguish Forward and Backward.
  dispatchBeforeInputEditorCommand(
      m_frame->document()->focusedElement(),
      InputEvent::InputType::DeleteContentBackward,
      new RangeVector(1, m_frame->selection().firstRange()));
  TypingCommand::deleteSelection(*frame().document());
}

// TODO(yabinh): We should reduce the number of selectionchange events.
void InputMethodController::deleteSurroundingText(int before, int after) {
  if (!editor().canEdit())
    return;
  const PlainTextRange selectionOffsets(getSelectionOffsets());
  if (selectionOffsets.isNull())
    return;
  Element* const rootEditableElement =
      frame().selection().rootEditableElement();
  if (!rootEditableElement)
    return;
  int selectionStart = static_cast<int>(selectionOffsets.start());
  int selectionEnd = static_cast<int>(selectionOffsets.end());

  // Select the text to be deleted before selectionStart.
  if (before > 0 && selectionStart > 0) {
    // In case of exceeding the left boundary.
    const int start = std::max(selectionStart - before, 0);

    const EphemeralRange& range =
        PlainTextRange(0, start).createRange(*rootEditableElement);
    if (range.isNull())
      return;
    const Position& position = range.endPosition();

    // Adjust the start of selection for multi-code text(a grapheme cluster
    // contains more than one code point). TODO(yabinh): Adjustment should be
    // based on code point instead of grapheme cluster.
    const size_t diff = computeDistanceToLeftGraphemeBoundary(position);
    const int adjustedStart = start - static_cast<int>(diff);
    if (!setSelectionOffsets(PlainTextRange(adjustedStart, selectionStart)))
      return;
    TypingCommand::deleteSelection(*frame().document());

    selectionEnd = selectionEnd - (selectionStart - adjustedStart);
    selectionStart = adjustedStart;
  }

  // Select the text to be deleted after selectionEnd.
  if (after > 0) {
    // Adjust the deleted range in case of exceeding the right boundary.
    const PlainTextRange range(0, selectionEnd + after);
    if (range.isNull())
      return;
    const EphemeralRange& validRange = range.createRange(*rootEditableElement);
    if (validRange.isNull())
      return;
    const int end =
        PlainTextRange::create(*rootEditableElement, validRange).end();
    const Position& position = validRange.endPosition();

    // Adjust the end of selection for multi-code text. TODO(yabinh): Adjustment
    // should be based on code point instead of grapheme cluster.
    const size_t diff = computeDistanceToRightGraphemeBoundary(position);
    const int adjustedEnd = end + static_cast<int>(diff);
    if (!setSelectionOffsets(PlainTextRange(selectionEnd, adjustedEnd)))
      return;
    TypingCommand::deleteSelection(*frame().document());
  }

  setSelectionOffsets(PlainTextRange(selectionStart, selectionEnd));
}

WebTextInputInfo InputMethodController::textInputInfo() const {
  WebTextInputInfo info;
  if (!frame().document())
    return info;

  if (!frame().selection().isAvailable()) {
    // plugins/mouse-capture-inside-shadow.html reaches here.
    return info;
  }
  Element* element = frame().selection().rootEditableElement();
  if (!element)
    return info;

  info.inputMode = inputModeOfFocusedElement();
  info.type = textInputType();
  info.flags = textInputFlags();
  if (info.type == WebTextInputTypeNone)
    return info;

  if (!frame().editor().canEdit())
    return info;

  // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited.  see http://crbug.com/590369 for more details.
  frame().document()->updateStyleAndLayoutIgnorePendingStylesheets();

  DocumentLifecycle::DisallowTransitionScope disallowTransition(
      frame().document()->lifecycle());

  // Emits an object replacement character for each replaced element so that
  // it is exposed to IME and thus could be deleted by IME on android.
  info.value = plainText(EphemeralRange::rangeOfContents(*element),
                         TextIteratorEmitsObjectReplacementCharacter);

  if (info.value.isEmpty())
    return info;

  EphemeralRange firstRange =
      firstEphemeralRangeOf(frame().selection().selection());
  if (firstRange.isNotNull()) {
    PlainTextRange plainTextRange(PlainTextRange::create(*element, firstRange));
    if (plainTextRange.isNotNull()) {
      info.selectionStart = plainTextRange.start();
      info.selectionEnd = plainTextRange.end();
    }
  }

  EphemeralRange range = compositionEphemeralRange();
  if (range.isNotNull()) {
    PlainTextRange plainTextRange(PlainTextRange::create(*element, range));
    if (plainTextRange.isNotNull()) {
      info.compositionStart = plainTextRange.start();
      info.compositionEnd = plainTextRange.end();
    }
  }

  return info;
}

int InputMethodController::textInputFlags() const {
  Element* element = frame().document()->focusedElement();
  if (!element)
    return WebTextInputFlagNone;

  int flags = 0;

  const AtomicString& autocomplete =
      element->getAttribute(HTMLNames::autocompleteAttr);
  if (autocomplete == "on")
    flags |= WebTextInputFlagAutocompleteOn;
  else if (autocomplete == "off")
    flags |= WebTextInputFlagAutocompleteOff;

  const AtomicString& autocorrect =
      element->getAttribute(HTMLNames::autocorrectAttr);
  if (autocorrect == "on")
    flags |= WebTextInputFlagAutocorrectOn;
  else if (autocorrect == "off")
    flags |= WebTextInputFlagAutocorrectOff;

  SpellcheckAttributeState spellcheck = element->spellcheckAttributeState();
  if (spellcheck == SpellcheckAttributeTrue)
    flags |= WebTextInputFlagSpellcheckOn;
  else if (spellcheck == SpellcheckAttributeFalse)
    flags |= WebTextInputFlagSpellcheckOff;

  if (isHTMLTextFormControlElement(element)) {
    HTMLTextFormControlElement* formElement =
        static_cast<HTMLTextFormControlElement*>(element);
    if (formElement->supportsAutocapitalize()) {
      DEFINE_STATIC_LOCAL(const AtomicString, none, ("none"));
      DEFINE_STATIC_LOCAL(const AtomicString, characters, ("characters"));
      DEFINE_STATIC_LOCAL(const AtomicString, words, ("words"));
      DEFINE_STATIC_LOCAL(const AtomicString, sentences, ("sentences"));

      const AtomicString& autocapitalize = formElement->autocapitalize();
      if (autocapitalize == none)
        flags |= WebTextInputFlagAutocapitalizeNone;
      else if (autocapitalize == characters)
        flags |= WebTextInputFlagAutocapitalizeCharacters;
      else if (autocapitalize == words)
        flags |= WebTextInputFlagAutocapitalizeWords;
      else if (autocapitalize == sentences)
        flags |= WebTextInputFlagAutocapitalizeSentences;
      else
        NOTREACHED();
    }
  }

  return flags;
}

WebTextInputMode InputMethodController::inputModeOfFocusedElement() const {
  if (!RuntimeEnabledFeatures::inputModeAttributeEnabled())
    return kWebTextInputModeDefault;

  Element* element = frame().document()->focusedElement();
  if (!element)
    return kWebTextInputModeDefault;

  AtomicString mode;
  if (isHTMLInputElement(*element)) {
    const HTMLInputElement& input = toHTMLInputElement(*element);
    if (input.supportsInputModeAttribute())
      mode = input.fastGetAttribute(HTMLNames::inputmodeAttr).lower();
  }
  if (isHTMLTextAreaElement(*element)) {
    const HTMLTextAreaElement& textarea = toHTMLTextAreaElement(*element);
    mode = textarea.fastGetAttribute(HTMLNames::inputmodeAttr).lower();
  }

  if (mode.isEmpty())
    return kWebTextInputModeDefault;
  if (mode == InputModeNames::verbatim)
    return kWebTextInputModeVerbatim;
  if (mode == InputModeNames::latin)
    return kWebTextInputModeLatin;
  if (mode == InputModeNames::latin_name)
    return kWebTextInputModeLatinName;
  if (mode == InputModeNames::latin_prose)
    return kWebTextInputModeLatinProse;
  if (mode == InputModeNames::full_width_latin)
    return kWebTextInputModeFullWidthLatin;
  if (mode == InputModeNames::kana)
    return kWebTextInputModeKana;
  if (mode == InputModeNames::kana_name)
    return kWebTextInputModeKanaName;
  if (mode == InputModeNames::katakana)
    return kWebTextInputModeKataKana;
  if (mode == InputModeNames::numeric)
    return kWebTextInputModeNumeric;
  if (mode == InputModeNames::tel)
    return kWebTextInputModeTel;
  if (mode == InputModeNames::email)
    return kWebTextInputModeEmail;
  if (mode == InputModeNames::url)
    return kWebTextInputModeUrl;
  return kWebTextInputModeDefault;
}

WebTextInputType InputMethodController::textInputType() const {
  if (!frame().selection().isAvailable()) {
    // "mouse-capture-inside-shadow.html" reaches here.
    return WebTextInputTypeNone;
  }

  // It's important to preserve the equivalence of textInputInfo().type and
  // textInputType(), so perform the same rootEditableElement() existence check
  // here for consistency.
  if (!frame().selection().selection().rootEditableElement())
    return WebTextInputTypeNone;

  Document* document = frame().document();
  if (!document)
    return WebTextInputTypeNone;

  Element* element = document->focusedElement();
  if (!element)
    return WebTextInputTypeNone;

  if (isHTMLInputElement(*element)) {
    HTMLInputElement& input = toHTMLInputElement(*element);
    const AtomicString& type = input.type();

    if (input.isDisabledOrReadOnly())
      return WebTextInputTypeNone;

    if (type == InputTypeNames::password)
      return WebTextInputTypePassword;
    if (type == InputTypeNames::search)
      return WebTextInputTypeSearch;
    if (type == InputTypeNames::email)
      return WebTextInputTypeEmail;
    if (type == InputTypeNames::number)
      return WebTextInputTypeNumber;
    if (type == InputTypeNames::tel)
      return WebTextInputTypeTelephone;
    if (type == InputTypeNames::url)
      return WebTextInputTypeURL;
    if (type == InputTypeNames::text)
      return WebTextInputTypeText;

    return WebTextInputTypeNone;
  }

  if (isHTMLTextAreaElement(*element)) {
    if (toHTMLTextAreaElement(*element).isDisabledOrReadOnly())
      return WebTextInputTypeNone;
    return WebTextInputTypeTextArea;
  }

  if (element->isHTMLElement()) {
    if (toHTMLElement(element)->isDateTimeFieldElement())
      return WebTextInputTypeDateTimeField;
  }

  document->updateStyleAndLayoutTree();
  if (hasEditableStyle(*element))
    return WebTextInputTypeContentEditable;

  return WebTextInputTypeNone;
}

DEFINE_TRACE(InputMethodController) {
  visitor->trace(m_frame);
  visitor->trace(m_compositionRange);
}

}  // namespace blink
