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

#include "ui/accessibility/ax_computed_node_data.h"

#include "base/check_op.h"
#include "base/i18n/break_iterator.h"
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/accessibility/accessibility_features.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node.h"
#include "ui/accessibility/ax_node_position.h"
#include "ui/accessibility/ax_position.h"
#include "ui/accessibility/ax_range.h"
#include "ui/accessibility/ax_tree_manager.h"
#include "ui/accessibility/ax_tree_manager_map.h"

namespace ui {

AXComputedNodeData::AXComputedNodeData(const AXNode& node) : owner_(&node) {}

AXComputedNodeData::~AXComputedNodeData() = default;

int AXComputedNodeData::GetOrComputeUnignoredIndexInParent() const {
  DCHECK(!owner_->IsIgnored())
      << "Ignored nodes cannot have an `unignored index in parent`.\n"
      << *owner_;
  if (unignored_index_in_parent_)
    return *unignored_index_in_parent_;

  if (const AXNode* unignored_parent = SlowGetUnignoredParent()) {
    DCHECK_NE(unignored_parent->id(), kInvalidAXNodeID)
        << "All nodes should have a valid ID.\n"
        << *owner_;
    unignored_parent->GetComputedNodeData().ComputeUnignoredValues();
  } else {
    // This should be the root node and, by convention, we assign it an
    // index-in-parent of 0.
    unignored_index_in_parent_ = 0;
    unignored_parent_id_ = kInvalidAXNodeID;
  }
  return *unignored_index_in_parent_;
}

AXNodeID AXComputedNodeData::GetOrComputeUnignoredParentID() const {
  if (unignored_parent_id_)
    return *unignored_parent_id_;

  if (const AXNode* unignored_parent = SlowGetUnignoredParent()) {
    DCHECK_NE(unignored_parent->id(), kInvalidAXNodeID)
        << "All nodes should have a valid ID.\n"
        << *owner_;
    unignored_parent_id_ = unignored_parent->id();
  } else {
    // This should be the root node and, by convention, we assign it an
    // index-in-parent of 0.
    DCHECK(!owner_->GetParent())
        << "If `unignored_parent` is nullptr, then this should be the "
           "rootnode, since in all trees the rootnode should be unignored.\n"
        << *owner_;
    unignored_index_in_parent_ = 0;
    unignored_parent_id_ = kInvalidAXNodeID;
  }
  return *unignored_parent_id_;
}

AXNode* AXComputedNodeData::GetOrComputeUnignoredParent() const {
  DCHECK(owner_->tree())
      << "All nodes should be owned by an accessibility tree.\n"
      << *owner_;
  return owner_->tree()->GetFromId(GetOrComputeUnignoredParentID());
}

int AXComputedNodeData::GetOrComputeUnignoredChildCount() const {
  DCHECK(!owner_->IsIgnored())
      << "Ignored nodes cannot have an `unignored child count`.\n"
      << *owner_;
  if (!unignored_child_count_)
    ComputeUnignoredValues();
  return *unignored_child_count_;
}

const std::vector<AXNodeID>& AXComputedNodeData::GetOrComputeUnignoredChildIDs()
    const {
  DCHECK(!owner_->IsIgnored())
      << "Ignored nodes cannot have `unignored child IDs`.\n"
      << *owner_;
  if (!unignored_child_ids_)
    ComputeUnignoredValues();
  return *unignored_child_ids_;
}

bool AXComputedNodeData::GetOrComputeIsDescendantOfPlatformLeaf() const {
  if (!is_descendant_of_leaf_)
    ComputeIsDescendantOfPlatformLeaf();
  return *is_descendant_of_leaf_;
}

const std::string& AXComputedNodeData::ComputeAttributeUTF8(
    const ax::mojom::StringAttribute attribute) const {
  DCHECK(owner_->CanComputeStringAttribute(attribute));
  switch (attribute) {
    case ax::mojom::StringAttribute::kValue:
      return GetOrComputeTextContentWithParagraphBreaksUTF8();

    case ax::mojom::StringAttribute::kName:
      return GetOrComputeTextContentUTF8();

    default:
      NOTREACHED();
  }
}

std::u16string AXComputedNodeData::ComputeAttributeUTF16(
    const ax::mojom::StringAttribute attribute) const {
  DCHECK(owner_->CanComputeStringAttribute(attribute));
  switch (attribute) {
    case ax::mojom::StringAttribute::kValue:
      return GetOrComputeTextContentWithParagraphBreaksUTF16();

    case ax::mojom::StringAttribute::kName:
      return GetOrComputeTextContentUTF16();

    default:
      NOTREACHED();
  }
}

const std::vector<int32_t>& AXComputedNodeData::ComputeAttribute(
    const ax::mojom::IntListAttribute attribute) const {
  DCHECK(owner_->CanComputeIntListAttribute(attribute));
  switch (attribute) {
    case ax::mojom::IntListAttribute::kLineStarts:
      ComputeLineOffsetsIfNeeded();
      return *line_starts_;

    case ax::mojom::IntListAttribute::kLineEnds:
      ComputeLineOffsetsIfNeeded();
      return *line_ends_;

    case ax::mojom::IntListAttribute::kSentenceStarts:
      ComputeSentenceOffsetsIfNeeded();
      return *sentence_starts_;

    case ax::mojom::IntListAttribute::kSentenceEnds:
      ComputeSentenceOffsetsIfNeeded();
      return *sentence_ends_;

    case ax::mojom::IntListAttribute::kWordStarts:
      ComputeWordOffsetsIfNeeded();
      return *word_starts_;

    case ax::mojom::IntListAttribute::kWordEnds:
      ComputeWordOffsetsIfNeeded();
      return *word_ends_;

    default:
      NOTREACHED();
  }
}

const std::string&
AXComputedNodeData::GetOrComputeTextContentWithParagraphBreaksUTF8() const {
  if (!text_content_with_paragraph_breaks_utf8_) {
    VLOG_IF(1, text_content_with_paragraph_breaks_utf16_)
        << "Only a single encoding of text content with paragraph breaks "
           "should be cached.";
    auto range =
        AXRange<AXPosition<AXNodePosition, AXNode>>::RangeOfContents(*owner_);
    text_content_with_paragraph_breaks_utf8_ = base::UTF16ToUTF8(
        range.GetText(AXTextConcatenationBehavior::kWithParagraphBreaks,
                      AXEmbeddedObjectBehavior::kSuppressCharacter));
  }
  return *text_content_with_paragraph_breaks_utf8_;
}

const std::u16string&
AXComputedNodeData::GetOrComputeTextContentWithParagraphBreaksUTF16() const {
  if (!text_content_with_paragraph_breaks_utf16_) {
    VLOG_IF(1, text_content_with_paragraph_breaks_utf8_)
        << "Only a single encoding of text content with paragraph breaks "
           "should be cached.";
    auto range =
        AXRange<AXPosition<AXNodePosition, AXNode>>::RangeOfContents(*owner_);
    text_content_with_paragraph_breaks_utf16_ =
        range.GetText(AXTextConcatenationBehavior::kWithParagraphBreaks,
                      AXEmbeddedObjectBehavior::kSuppressCharacter);
  }
  return *text_content_with_paragraph_breaks_utf16_;
}

const std::string& AXComputedNodeData::GetOrComputeTextContentUTF8() const {
  if (!text_content_utf8_) {
    VLOG_IF(1, text_content_utf16_)
        << "Only a single encoding of text content should be cached.";
    text_content_utf8_ = ComputeTextContentUTF8();
  }
  return *text_content_utf8_;
}

const std::u16string& AXComputedNodeData::GetOrComputeTextContentUTF16() const {
  if (!text_content_utf16_) {
    VLOG_IF(1, text_content_utf8_)
        << "Only a single encoding of text content should be cached.";
    text_content_utf16_ = ComputeTextContentUTF16();
  }
  return *text_content_utf16_;
}

int AXComputedNodeData::GetOrComputeTextContentLengthUTF8() const {
  return static_cast<int>(GetOrComputeTextContentUTF8().length());
}

int AXComputedNodeData::GetOrComputeTextContentLengthUTF16() const {
  if (utf16_length_) {
    return utf16_length_.value();
  }
  if (text_content_utf16_) {
    // Used the cached UTF16 representation if we have it already.
    utf16_length_ = text_content_utf16_->length();
  } else {
    // Do not cache the text since used just to extract the length.
    utf16_length_ = ComputeTextContentUTF16().length();
  }
  return utf16_length_.value();
}

bool AXComputedNodeData::CanInferNameAttribute() const {
  // The name may be suppressed when serializing an AXInlineTextBox if it
  // can be inferred from the parent.
  return owner_->data().role == ax::mojom::Role::kInlineTextBox &&
         owner_->data().GetNameFrom() == ax::mojom::NameFrom::kContents &&
         owner_->GetParent()->data().GetNameFrom() ==
             ax::mojom::NameFrom::kContents &&
         owner_->GetParent()->data().HasStringAttribute(
             ax::mojom::StringAttribute::kName);
}

void AXComputedNodeData::ComputeUnignoredValues(
    AXNodeID unignored_parent_id,
    int starting_index_in_parent) const {
  DCHECK_GE(starting_index_in_parent, 0);
  // Reset any previously computed values.
  unignored_index_in_parent_ = std::nullopt;
  unignored_parent_id_ = std::nullopt;
  unignored_child_count_ = std::nullopt;
  unignored_child_ids_ = std::nullopt;

  AXNodeID unignored_parent_id_for_child = unignored_parent_id;
  if (!owner_->IsIgnored())
    unignored_parent_id_for_child = owner_->id();
  int unignored_child_count = 0;
  std::vector<AXNodeID> unignored_child_ids;
  for (AXNode* child : owner_->GetAllChildren()) {
    const AXComputedNodeData& computed_data = child->GetComputedNodeData();
    int new_index_in_parent = starting_index_in_parent + unignored_child_count;

    if (child->IsIgnored()) {
      // Skip the ignored node and recursively look at its children.
      computed_data.ComputeUnignoredValues(unignored_parent_id_for_child,
                                           new_index_in_parent);
      DCHECK(computed_data.unignored_child_count_);
      unignored_child_count += *computed_data.unignored_child_count_;
      DCHECK(computed_data.unignored_child_ids_);
      unignored_child_ids.insert(unignored_child_ids.end(),
                                 computed_data.unignored_child_ids_->begin(),
                                 computed_data.unignored_child_ids_->end());
    } else {
      // Setting `unignored_index_in_parent_` and `unignored_parent_id_` is the
      // responsibility of the parent node, since only the parent node can
      // calculate these values. This is in contrast to `unignored_child_count_`
      // and `unignored_child_ids_` that are only set if this method is called
      // on the node itself.
      computed_data.unignored_index_in_parent_ = new_index_in_parent;
      if (unignored_parent_id_for_child != kInvalidAXNodeID)
        computed_data.unignored_parent_id_ = unignored_parent_id_for_child;

      ++unignored_child_count;
      unignored_child_ids.push_back(child->id());
    }
  }

  if (unignored_parent_id != kInvalidAXNodeID)
    unignored_parent_id_ = unignored_parent_id;
  // Ignored nodes store unignored child information in order to propagate it to
  // their parents, but do not expose it directly. The latter is guarded via a
  // DCHECK.
  unignored_child_count_ = unignored_child_count;
  unignored_child_ids_ = unignored_child_ids;
}

AXNode* AXComputedNodeData::SlowGetUnignoredParent() const {
  AXNode* unignored_parent = owner_->GetParent();
  while (unignored_parent && unignored_parent->IsIgnored())
    unignored_parent = unignored_parent->GetParent();
  return unignored_parent;
}

void AXComputedNodeData::ComputeIsDescendantOfPlatformLeaf() const {
  is_descendant_of_leaf_ = false;
  for (const AXNode* ancestor = GetOrComputeUnignoredParent(); ancestor;
       ancestor =
           ancestor->GetComputedNodeData().GetOrComputeUnignoredParent()) {
    if (ancestor->GetComputedNodeData().is_descendant_of_leaf_.value_or(
            false) ||
        ancestor->IsLeaf()) {
      is_descendant_of_leaf_ = true;
      return;
    }
  }
}

void AXComputedNodeData::ComputeLineOffsetsIfNeeded() const {
  DCHECK_EQ(line_starts_.has_value(), line_ends_.has_value());
  if (line_starts_) {
    DCHECK_EQ(line_starts_->size(), line_ends_->size());
    return;  // Already cached.
  }

  line_starts_ = std::vector<int32_t>();
  line_ends_ = std::vector<int32_t>();
  const std::u16string& text_content = GetOrComputeTextContentUTF16();
  if (text_content.empty())
    return;

  // TODO(nektar): Using the `base::i18n::BreakIterator` class is not enough. We
  // also need to pass information from Blink as to which inline text boxes
  // start a new line and deprecate next/previous_on_line.
  base::i18n::BreakIterator iter(text_content,
                                 base::i18n::BreakIterator::BREAK_NEWLINE);
  if (!iter.Init())
    return;

  while (iter.Advance()) {
    line_starts_->push_back(base::checked_cast<int32_t>(iter.prev()));
    line_ends_->push_back(base::checked_cast<int32_t>(iter.pos()));
  }
}

void AXComputedNodeData::ComputeSentenceOffsetsIfNeeded() const {
  DCHECK_EQ(sentence_starts_.has_value(), sentence_ends_.has_value());
  if (sentence_starts_) {
    DCHECK_EQ(sentence_starts_->size(), sentence_ends_->size());
    return;  // Already cached.
  }

  sentence_starts_ = std::vector<int32_t>();
  sentence_ends_ = std::vector<int32_t>();
  if (owner_->IsLineBreak()) {
    return;
  }

  const std::u16string& text_content = GetOrComputeTextContentUTF16();
  if (text_content.empty() ||
      base::ContainsOnlyChars(text_content, base::kWhitespaceUTF16)) {
    return;
  }

  // Unlike in ICU, a sentence boundary is not valid in Blink if it falls within
  // some whitespace that is used to separate sentences. We therefore need to
  // filter the boundaries returned by ICU and return a subset of them. For
  // example we should exclude a sentence boundary that is between two space
  // characters, "Hello. | there.".
  // TODO(nektar): The above is not accomplished simply by using the
  // `base::i18n::BreakIterator` class.
  base::i18n::BreakIterator iter(text_content,
                                 base::i18n::BreakIterator::BREAK_SENTENCE);
  if (!iter.Init())
    return;

  while (iter.Advance()) {
    sentence_starts_->push_back(base::checked_cast<int32_t>(iter.prev()));
    sentence_ends_->push_back(base::checked_cast<int32_t>(iter.pos()));
  }
}

void AXComputedNodeData::ComputeWordOffsetsIfNeeded() const {
  DCHECK_EQ(word_starts_.has_value(), word_ends_.has_value());
  if (word_starts_) {
    DCHECK_EQ(word_starts_->size(), word_ends_->size());
    return;  // Already cached.
  }

  word_starts_ = std::vector<int32_t>();
  word_ends_ = std::vector<int32_t>();
  const std::u16string& text_content = GetOrComputeTextContentUTF16();
  if (text_content.empty())
    return;

  // Unlike in ICU, a word boundary is valid in Blink only if it is before, or
  // immediately preceded by, an alphanumeric character, a series of punctuation
  // marks, an underscore or a line break. We therefore need to filter the
  // boundaries returned by ICU and return a subset of them. For example we
  // should exclude a word boundary that is between two space characters, "Hello
  // | there".
  // TODO(nektar): Fix the fact that the `base::i18n::BreakIterator` class does
  // not take into account underscores as word separators.
  base::i18n::BreakIterator iter(text_content,
                                 base::i18n::BreakIterator::BREAK_WORD);
  if (!iter.Init())
    return;

  while (iter.Advance()) {
    if (iter.IsWord()) {
      word_starts_->push_back(base::checked_cast<int>(iter.prev()));
      word_ends_->push_back(base::checked_cast<int>(iter.pos()));
    }
  }
}

std::string AXComputedNodeData::ComputeTextContentUTF8() const {
  // Name is omitted from an inline text if an only child since its value is
  // the same as the parent. We can differentiate this case from a specified
  // but empty name based on the name from attribute, which is kFromContent if
  // set and kNone if the text content is to be inferred from the parent.
  if (owner_->data().role == ax::mojom::Role::kInlineTextBox &&
      !owner_->data().HasStringAttribute(ax::mojom::StringAttribute::kName)) {
    return owner_->GetParent()->data().GetStringAttribute(
        ax::mojom::StringAttribute::kName);
  }

  // If a text field has no descendants, then we compute its text content from
  // its value or its placeholder. Otherwise we prefer to look at its descendant
  // text nodes because Blink doesn't always add all trailing white space to the
  // value attribute.
  const bool is_atomic_text_field_without_descendants =
      (owner_->data().IsTextField() && !owner_->GetUnignoredChildCount());
  if (is_atomic_text_field_without_descendants) {
    std::string value =
        owner_->data().GetStringAttribute(ax::mojom::StringAttribute::kValue);
    // If the value is empty, then there might be some placeholder text in the
    // text field, or any other name that is derived from visible contents, even
    // if the text field has no children, so we treat this as any other leaf
    // node.
    if (!value.empty())
      return value;
  }

  // Ordinarily, atomic text fields are leaves, and for all leaves we directly
  // retrieve their text content using the information provided by the tree
  // source, such as Blink. However, for atomic text fields we need to exclude
  // them from the set of leaf nodes when they expose any descendants. This is
  // because we want to compute their text content from their descendant text
  // nodes as we don't always trust the "value" attribute provided by Blink.
  const bool is_atomic_text_field_with_descendants =
      (owner_->data().IsTextField() && owner_->GetUnignoredChildCount());
  if (owner_->IsLeaf() && !is_atomic_text_field_with_descendants) {
    switch (owner_->data().GetNameFrom()) {
      case ax::mojom::NameFrom::kNone:
      // The accessible name is not displayed on screen, e.g. aria-label, or is
      // not displayed directly inside the node, e.g. an associated label
      // element.
      case ax::mojom::NameFrom::kAttribute:
      // The node's accessible name is explicitly empty.
      case ax::mojom::NameFrom::kAttributeExplicitlyEmpty:
      // The accessible name does not represent the entirety of the node's text
      // content, e.g. a table's caption or a figure's figcaption.
      case ax::mojom::NameFrom::kCaption:
      // The name comes from CSS alt text.
      case ax::mojom::NameFrom::kCssAltText:
      // The object should not have an accessible name according to ARIA 1.2.
      // If kProhibited is set, that means we calculated a name in Blink and
      // are deliberately not exposing it.
      case ax::mojom::NameFrom::kProhibited:
      case ax::mojom::NameFrom::kProhibitedAndRedundant:
      case ax::mojom::NameFrom::kRelatedElement:
      // The accessible name is not displayed directly inside the node but is
      // visible via e.g. a tooltip.
      case ax::mojom::NameFrom::kTitle:
      case ax::mojom::NameFrom::kPopoverTarget:
      case ax::mojom::NameFrom::kInterestFor:
        return std::string();

      case ax::mojom::NameFrom::kContents:
      // The placeholder text is initially displayed inside the text field and
      // takes the place of its value.
      case ax::mojom::NameFrom::kPlaceholder:
      // The value attribute takes the place of the node's text content, e.g.
      // the value of a submit button is displayed inside the button itself.
      case ax::mojom::NameFrom::kValue:
        return owner_->data().GetStringAttribute(
            ax::mojom::StringAttribute::kName);
    }
  }

  std::string text_content;
  for (auto it = owner_->UnignoredChildrenCrossingTreeBoundaryBegin(),
            end = owner_->UnignoredChildrenCrossingTreeBoundaryEnd();
       it != end; ++it) {
    text_content += it->GetTextContentUTF8();
  }
  return text_content;
}

std::u16string AXComputedNodeData::ComputeTextContentUTF16() const {
  return base::UTF8ToUTF16(ComputeTextContentUTF8());
}

}  // namespace ui
