/*
 * Copyright (C) 2004, 2006, 2009 Apple Inc. All rights reserved.
 *
 * 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.
 */

#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_ITERATORS_TEXT_ITERATOR_TEXT_STATE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_ITERATORS_TEXT_ITERATOR_TEXT_STATE_H_

#include "base/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/editing/iterators/text_iterator_behavior.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"

namespace blink {

class ContainerNode;
class HTMLElement;
class Node;
class Text;

class CORE_EXPORT TextIteratorTextState {
  STACK_ALLOCATED();

 public:
  explicit TextIteratorTextState(const TextIteratorBehavior&);

  // Return properties of the current text.
  unsigned length() const { return text_length_; }
  UChar CharacterAt(unsigned index) const;
  // TODO(xiaochengh): Rename to |GetText()| as it's used in production code.
  String GetTextForTesting() const;
  void AppendTextToStringBuilder(StringBuilder&,
                                 unsigned position = 0,
                                 unsigned max_length = UINT_MAX) const;

  // Emits code unit relative to |node|.
  void EmitChar16AfterNode(UChar code_unit, const Node& node);
  void EmitChar16AsNode(UChar code_unit, const Node& node);
  void EmitChar16BeforeChildren(UChar code_unit,
                                const ContainerNode& container_node);
  void EmitChar16BeforeNode(UChar code_unit, const Node& node);

  // Emits |code_unit| before |offset| in |text_node|.
  void EmitChar16Before(UChar code_unit,
                        const Text& text_node,
                        unsigned offset);
  // Emits |code_unit| as replacement of code unit at |offset| in |text_node|.
  void EmitReplacmentCodeUnit(UChar code_unit,
                              const Text& text_node,
                              unsigned offset);
  void EmitText(const Text&,
                unsigned position_start_offset,
                unsigned position_end_offset,
                const String&,
                unsigned text_start_offset,
                unsigned text_end_offset);
  void EmitAltText(const HTMLElement&);
  void UpdateForReplacedElement(const Node& node);

  // Return position of the current text.
  void UpdatePositionOffsets(const ContainerNode& container_node,
                             unsigned index) const;
  unsigned PositionStartOffset() const;
  unsigned PositionEndOffset() const;
  const Node* PositionNode() const { return position_node_; }
  const Node* PositionContainerNode() const { return position_container_node_; }
  bool IsAfterPositionNode() const {
    return position_node_type_ == PositionNodeType::kAfterNode;
  }
  bool IsBeforePositionNode() const {
    return position_node_type_ == PositionNodeType::kBeforeNode;
  }
  bool IsBeforeCharacter() const {
    return position_node_type_ == PositionNodeType::kBeforeCharacter;
  }
  bool IsBeforeChildren() const {
    return position_node_type_ == PositionNodeType::kBeforeChildren;
  }
  bool IsInTextNode() const {
    return position_node_type_ == PositionNodeType::kInText;
  }

  bool HasEmitted() const { return has_emitted_; }
  UChar LastCharacter() const { return last_character_; }
  void ResetRunInformation() {
    position_node_ = nullptr;
    text_length_ = 0;
  }

 private:
  // Location of text run relative to |position_node_|.
  enum class PositionNodeType {
    kNone,
    kAfterNode,
    kAltText,
    kAsNode,
    kBeforeCharacter,
    kBeforeChildren,
    kBeforeNode,
    kInText,
  };

  void ResetPositionContainerNode(PositionNodeType node_type, const Node& node);
  void SetTextNodePosition(const Text& text_node,
                           unsigned start_offset,
                           unsigned end_offset);
  void PopulateStringBuffer(const String& text, unsigned start, unsigned end);
  void PopulateStringBufferFromChar16(UChar code_unit);

  const TextIteratorBehavior behavior_;
  unsigned text_length_ = 0;

  // TODO(editing-dev): We should integrate single character buffer and
  // string buffer.
  // Used for whitespace characters that aren't in the DOM, so we can point at
  // them.
  // If non-zero, overrides |text_|.
  UChar single_character_buffer_ = 0;

  // The current text when |single_character_buffer_| is zero, in which case it
  // is |text_.Substring(text_start_offset_, text_length_)|.
  String text_;
  // TODO(editing-dev): We should make |text_| to hold substring instead of
  // entire string with |text_start_offset_| and |text_length_|.
  unsigned text_start_offset_ = 0;

  // Position of the current text, in the form to be returned from the iterator.
  const Node* position_node_ = nullptr;
  // |Text| node when |position_node_type_ == kInText| or |ContainerNode|.
  mutable const Node* position_container_node_ = nullptr;
  mutable base::Optional<unsigned> position_start_offset_;
  mutable base::Optional<unsigned> position_end_offset_;
  PositionNodeType position_node_type_ = PositionNodeType::kNone;

  // Used when deciding whether to emit a "positioning" (e.g. newline) before
  // any other content
  bool has_emitted_ = false;
  UChar last_character_ = 0;

  DISALLOW_COPY_AND_ASSIGN(TextIteratorTextState);
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_ITERATORS_TEXT_ITERATOR_TEXT_STATE_H_
