// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef FLUTTER_SHELL_PLATFORM_COMMON_TEXT_INPUT_MODEL_H_
#define FLUTTER_SHELL_PLATFORM_COMMON_TEXT_INPUT_MODEL_H_

#include <memory>
#include <string>

#include "flutter/shell/platform/common/text_range.h"

namespace flutter {

// Handles underlying text input state, using a simple ASCII model.
//
// Ignores special states like "insert mode" for now.
class TextInputModel {
 public:
  TextInputModel();
  virtual ~TextInputModel();

  // Sets the text.
  //
  // Resets the selection base and extent.
  void SetText(const std::string& text);

  // Attempts to set the text selection.
  //
  // Returns false if the selection is not within the bounds of the text.
  // While in composing mode, the selection is restricted to the composing
  // range; otherwise, it is restricted to the length of the text.
  bool SetSelection(const TextRange& range);

  // Attempts to set the composing range.
  //
  // Returns false if the range or offset are out of range for the text, or if
  // the offset is outside the composing range.
  bool SetComposingRange(const TextRange& range, size_t cursor_offset);

  // Begins IME composing mode.
  //
  // Resets the composing base and extent to the selection start. The existing
  // selection is preserved in case composing is aborted with no changes. Until
  // |EndComposing| is called, any further changes to selection base and extent
  // are restricted to the composing range.
  void BeginComposing();

  // Replaces the composing range with new UTF-16 text.
  //
  // If a selection of non-zero length exists, it is deleted if the composing
  // text is non-empty. The composing range is adjusted to the length of
  // |text| and the selection base and offset are set to the end of the
  // composing range.
  void UpdateComposingText(const std::u16string& text);

  // Replaces the composing range with new UTF-8 text.
  //
  // If a selection of non-zero length exists, it is deleted if the composing
  // text is non-empty. The composing range is adjusted to the length of
  // |text| and the selection base and offset are set to the end of the
  // composing range.
  void UpdateComposingText(const std::string& text);

  // Commits composing range to the string.
  //
  // Causes the composing base and extent to be collapsed to the end of the
  // range.
  void CommitComposing();

  // Ends IME composing mode.
  //
  // Collapses the composing base and offset to 0.
  void EndComposing();

  // Adds a Unicode code point.
  //
  // Either appends after the cursor (when selection base and extent are the
  // same), or deletes the selected text, replacing it with the given
  // code point.
  void AddCodePoint(char32_t c);

  // Adds UTF-16 text.
  //
  // Either appends after the cursor (when selection base and extent are the
  // same), or deletes the selected text, replacing it with the given text.
  void AddText(const std::u16string& text);

  // Adds UTF-8 text.
  //
  // Either appends after the cursor (when selection base and extent are the
  // same), or deletes the selected text, replacing it with the given text.
  void AddText(const std::string& text);

  // Deletes either the selection, or one character ahead of the cursor.
  //
  // Deleting one character ahead of the cursor occurs when the selection base
  // and extent are the same. When composing is active, deletions are
  // restricted to text between the composing base and extent.
  //
  // Returns true if any deletion actually occurred.
  bool Delete();

  // Deletes text near the cursor.
  //
  // A section is made starting at |offset_from_cursor| code points past the
  // cursor (negative values go before the cursor). |count| code points are
  // removed. The selection may go outside the bounds of the available text and
  // will result in only the part selection that covers the available text
  // being deleted. The existing selection is ignored and removed after this
  // operation. When composing is active, deletions are restricted to the
  // composing range.
  //
  // Returns true if any deletion actually occurred.
  bool DeleteSurrounding(int offset_from_cursor, int count);

  // Deletes either the selection, or one character behind the cursor.
  //
  // Deleting one character behind the cursor occurs when the selection base
  // and extent are the same. When composing is active, deletions are
  // restricted to the text between the composing base and extent.
  //
  // Returns true if any deletion actually occurred.
  bool Backspace();

  // Attempts to move the cursor backward.
  //
  // Returns true if the cursor could be moved. If a selection is active, moves
  // to the start of the selection. If composing is active, motion is
  // restricted to the composing range.
  bool MoveCursorBack();

  // Attempts to move the cursor forward.
  //
  // Returns true if the cursor could be moved. If a selection is active, moves
  // to the end of the selection. If composing is active, motion is restricted
  // to the composing range.
  bool MoveCursorForward();

  // Attempts to move the cursor to the beginning.
  //
  // If composing is active, the cursor is moved to the beginning of the
  // composing range; otherwise, it is moved to the beginning of the text. If
  // composing is active, motion is restricted to the composing range.
  //
  // Returns true if the cursor could be moved.
  bool MoveCursorToBeginning();

  // Attempts to move the cursor to the end.
  //
  // If composing is active, the cursor is moved to the end of the composing
  // range; otherwise, it is moved to the end of the text. If composing is
  // active, motion is restricted to the composing range.
  //
  // Returns true if the cursor could be moved.
  bool MoveCursorToEnd();

  // Attempts to select text from the cursor position to the beginning.
  //
  // If composing is active, the selection is applied to the beginning of the
  // composing range; otherwise, it is applied to the beginning of the text.
  //
  // Returns true if the selection could be applied.
  bool SelectToBeginning();

  // Attempts to select text from the cursor position to the end.
  //
  // If composing is active, the selection is applied to the end of the
  // composing range; otherwise, it is moved to the end of the text.
  //
  // Returns true if the selection could be applied.
  bool SelectToEnd();

  // Gets the current text as UTF-8.
  std::string GetText() const;

  // Gets the cursor position as a byte offset in UTF-8 string returned from
  // GetText().
  int GetCursorOffset() const;

  // Returns a range covering the entire text.
  TextRange text_range() const { return TextRange(0, text_.length()); }

  // The current selection.
  TextRange selection() const { return selection_; }

  // The composing range.
  //
  // If not in composing mode, returns a collapsed range at position 0.
  TextRange composing_range() const { return composing_range_; }

  // Whether multi-step input composing mode is active.
  bool composing() const { return composing_; }

 private:
  // Deletes the current selection, if any.
  //
  // Returns true if any text is deleted. The selection base and extent are
  // reset to the start of the selected range.
  bool DeleteSelected();

  // Returns the currently editable text range.
  //
  // In composing mode, returns the composing range; otherwise, returns a range
  // covering the entire text.
  TextRange editable_range() const {
    return composing_ ? composing_range_ : text_range();
  }

  std::u16string text_;
  TextRange selection_ = TextRange(0);
  TextRange composing_range_ = TextRange(0);
  bool composing_ = false;
};

}  // namespace flutter

#endif  // FLUTTER_SHELL_PLATFORM_COMMON_TEXT_INPUT_MODEL_H_
