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

#include "third_party/blink/renderer/core/editing/ime/cached_text_input_info.h"

#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/editing/iterators/text_iterator.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"

namespace blink {

// static
TextIteratorBehavior CachedTextInputInfo::Behavior() {
  return TextIteratorBehavior::Builder()
      .SetEmitsObjectReplacementCharacter(true)
      .SetEmitsSpaceForNbsp(true)
      .Build();
}

void CachedTextInputInfo::ClearIfNeeded(const LayoutObject& layout_object) {
  if (layout_object_ != &layout_object)
    return;
  container_ = nullptr;
  layout_object_ = nullptr;
  text_ = g_empty_string;
  composition_.Clear();
  selection_.Clear();
  offset_map_.clear();
}

void CachedTextInputInfo::DidLayoutSubtree(const LayoutObject& layout_object) {
  // <div style="contain:strict; ...">abc</div> reaches here.
  if (!container_)
    return;
  Node* const node = layout_object.NonPseudoNode();
  if (!node)
    return;
  const ContainerNode* const container =
      RootEditableElementOrTreeScopeRootNodeOf(Position(node, 0));
  if (!container || !container->GetLayoutObject())
    return;
  ClearIfNeeded(*container->GetLayoutObject());
}

void CachedTextInputInfo::DidUpdateLayout(const LayoutObject& layout_object) {
  ClearIfNeeded(layout_object);
}

void CachedTextInputInfo::EnsureCached(const ContainerNode& container) const {
  if (IsValidFor(container))
    return;
  offset_map_.clear();
  container_ = &container;
  layout_object_ = container.GetLayoutObject();
  composition_.Clear();
  selection_.Clear();
  text_ = g_empty_string;

  TextIteratorAlgorithm<EditingStrategy> it(
      EphemeralRange::RangeOfContents(container), Behavior());
  if (it.AtEnd())
    return;

  const bool needs_text = HasEditableStyle(*container_);

  // The initial buffer size can be critical for performance:
  // https://bugs.webkit.org/show_bug.cgi?id=81192
  constexpr unsigned kInitialCapacity = 1 << 15;

  StringBuilder builder;
  if (needs_text) {
    unsigned capacity = kInitialCapacity;
    if (auto* block_flow =
            DynamicTo<LayoutBlockFlow>(container.GetLayoutObject())) {
      if (block_flow->HasNGInlineNodeData()) {
        if (const auto* mapping = NGInlineNode::GetOffsetMapping(block_flow))
          capacity = mapping->GetText().length();
      }
    }
    builder.ReserveCapacity(capacity);
  }

  const Node* last_text_node = nullptr;
  unsigned length = 0;
  for (; !it.AtEnd(); it.Advance()) {
    const Node* node = it.GetTextState().PositionNode();
    if (last_text_node != node && IsA<Text>(node)) {
      last_text_node = node;
      offset_map_.insert(To<Text>(node), length);
    }
    if (needs_text)
      it.GetTextState().AppendTextToStringBuilder(builder);
    length += it.GetTextState().length();
  }

  if (!builder.IsEmpty())
    text_ = builder.ToString();
}

PlainTextRange CachedTextInputInfo::GetComposition(
    const EphemeralRange& range) const {
  DCHECK(container_);
  return GetPlainTextRangeWithCache(range, &composition_);
}

PlainTextRange CachedTextInputInfo::GetPlainTextRangeWithCache(
    const EphemeralRange& range,
    CachedPlainTextRange* text_range) const {
  if (!text_range->IsValidFor(range))
    text_range->Set(range, GetPlainTextRange(range));
  return text_range->Get();
}

PlainTextRange CachedTextInputInfo::GetPlainTextRange(
    const EphemeralRange& range) const {
  if (range.IsNull())
    return PlainTextRange();
  const Position container_start = Position(*container_, 0);
  // When selection is moved to another editable during IME composition,
  // |range| may not in |container|. See http://crbug.com/1161562
  if (container_start > range.StartPosition())
    return PlainTextRange();
  const unsigned start_offset =
      RangeLength(EphemeralRange(container_start, range.StartPosition()));
  const unsigned end_offset =
      range.IsCollapsed()
          ? start_offset
          : RangeLength(EphemeralRange(container_start, range.EndPosition()));
  DCHECK_EQ(
      static_cast<unsigned>(TextIterator::RangeLength(
          EphemeralRange(container_start, range.EndPosition()), Behavior())),
      end_offset);
  return PlainTextRange(start_offset, end_offset);
}

PlainTextRange CachedTextInputInfo::GetSelection(
    const EphemeralRange& range) const {
  DCHECK(container_);
  return GetPlainTextRangeWithCache(range, &selection_);
}

String CachedTextInputInfo::GetText() const {
  DCHECK(container_);
  DCHECK(HasEditableStyle(*container_));
  return text_;
}

bool CachedTextInputInfo::IsValidFor(const ContainerNode& container) const {
  return container_ == container &&
         layout_object_ == container.GetLayoutObject();
}

void CachedTextInputInfo::LayoutObjectWillBeDestroyed(
    const LayoutObject& layout_object) {
  ClearIfNeeded(layout_object);
}

unsigned CachedTextInputInfo::RangeLength(const EphemeralRange& range) const {
  const Node* const node = range.EndPosition().AnchorNode();
  if (range.StartPosition() == Position(*container_, 0) && IsA<Text>(node)) {
    const auto it = offset_map_.find(To<Text>(node));
    if (it != offset_map_.end()) {
      const unsigned length =
          it->value +
          TextIterator::RangeLength(
              EphemeralRange(Position(node, 0), range.EndPosition()),
              Behavior());
      DCHECK_EQ(
          static_cast<unsigned>(TextIterator::RangeLength(range, Behavior())),
          length)
          << it->value << " " << range;
      return length;
    }
  }
  return TextIterator::RangeLength(range, Behavior());
}

void CachedTextInputInfo::Trace(Visitor* visitor) const {
  visitor->Trace(container_);
  visitor->Trace(composition_);
  visitor->Trace(offset_map_);
  visitor->Trace(selection_);
}

void CachedTextInputInfo::CachedPlainTextRange::Clear() {
  start_ = end_ = Position();
  start_offset_ = end_offset_ = kNotFound;
}

PlainTextRange CachedTextInputInfo::CachedPlainTextRange::Get() const {
  if (start_offset_ == kNotFound)
    return PlainTextRange();
  return PlainTextRange(start_offset_, end_offset_);
}

bool CachedTextInputInfo::CachedPlainTextRange::IsValidFor(
    const EphemeralRange& range) const {
  return range.StartPosition() == start_ && range.EndPosition() == end_;
}

void CachedTextInputInfo::CachedPlainTextRange::Set(
    const EphemeralRange& range,
    const PlainTextRange& text_range) {
  start_ = range.StartPosition();
  end_ = range.EndPosition();
  if (text_range.IsNull()) {
    start_offset_ = end_offset_ = kNotFound;
  } else {
    start_offset_ = text_range.Start();
    end_offset_ = text_range.End();
  }
}

void CachedTextInputInfo::CachedPlainTextRange::Trace(Visitor* visitor) const {
  visitor->Trace(start_);
  visitor->Trace(end_);
}

}  // namespace blink
