// Copyright 2017 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/aom/accessible_node.h"

#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/aom/accessible_node_list.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/qualified_name.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/html/custom/element_internals.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"

namespace blink {

namespace {

QualifiedName GetCorrespondingARIAAttribute(AOMStringProperty property) {
  switch (property) {
    case AOMStringProperty::kAutocomplete:
      return html_names::kAriaAutocompleteAttr;
    case AOMStringProperty::kChecked:
      return html_names::kAriaCheckedAttr;
    case AOMStringProperty::kCurrent:
      return html_names::kAriaCurrentAttr;
    case AOMStringProperty::kDescription:
      return html_names::kAriaDescriptionAttr;
    case AOMStringProperty::kHasPopUp:
      return html_names::kAriaHaspopupAttr;
    case AOMStringProperty::kInvalid:
      return html_names::kAriaInvalidAttr;
    case AOMStringProperty::kKeyShortcuts:
      return html_names::kAriaKeyshortcutsAttr;
    case AOMStringProperty::kLabel:
      return html_names::kAriaLabelAttr;
    case AOMStringProperty::kLive:
      return html_names::kAriaLiveAttr;
    case AOMStringProperty::kOrientation:
      return html_names::kAriaOrientationAttr;
    case AOMStringProperty::kPlaceholder:
      return html_names::kAriaPlaceholderAttr;
    case AOMStringProperty::kPressed:
      return html_names::kAriaPressedAttr;
    case AOMStringProperty::kRelevant:
      return html_names::kAriaRelevantAttr;
    case AOMStringProperty::kRole:
      return html_names::kRoleAttr;
    case AOMStringProperty::kRoleDescription:
      return html_names::kAriaRoledescriptionAttr;
    case AOMStringProperty::kSort:
      return html_names::kAriaSortAttr;
    case AOMStringProperty::kValueText:
      return html_names::kAriaValuetextAttr;
    case AOMStringProperty::kVirtualContent:
      return html_names::kAriaVirtualcontentAttr;
  }

  NOTREACHED();
  return g_null_name;
}

QualifiedName GetCorrespondingARIAAttribute(AOMRelationProperty property) {
  switch (property) {
    case AOMRelationProperty::kActiveDescendant:
      return html_names::kAriaActivedescendantAttr;
    case AOMRelationProperty::kErrorMessage:
      return html_names::kAriaErrormessageAttr;
  }

  NOTREACHED();
  return g_null_name;
}

QualifiedName GetCorrespondingARIAAttribute(AOMRelationListProperty property) {
  switch (property) {
    case AOMRelationListProperty::kDescribedBy:
      return html_names::kAriaDescribedbyAttr;
    case AOMRelationListProperty::kDetails:
      return html_names::kAriaDetailsAttr;
    case AOMRelationListProperty::kControls:
      return html_names::kAriaControlsAttr;
    case AOMRelationListProperty::kFlowTo:
      return html_names::kAriaFlowtoAttr;
    case AOMRelationListProperty::kLabeledBy:
      // Note that there are two allowed spellings of this attribute.
      // Callers should check both.
      return html_names::kAriaLabelledbyAttr;
    case AOMRelationListProperty::kOwns:
      return html_names::kAriaOwnsAttr;
  }

  NOTREACHED();
  return g_null_name;
}

QualifiedName GetCorrespondingARIAAttribute(AOMBooleanProperty property) {
  switch (property) {
    case AOMBooleanProperty::kAtomic:
      return html_names::kAriaAtomicAttr;
    case AOMBooleanProperty::kBusy:
      return html_names::kAriaBusyAttr;
    case AOMBooleanProperty::kDisabled:
      return html_names::kAriaDisabledAttr;
    case AOMBooleanProperty::kExpanded:
      return html_names::kAriaExpandedAttr;
    case AOMBooleanProperty::kHidden:
      return html_names::kAriaHiddenAttr;
    case AOMBooleanProperty::kModal:
      return html_names::kAriaModalAttr;
    case AOMBooleanProperty::kMultiline:
      return html_names::kAriaMultilineAttr;
    case AOMBooleanProperty::kMultiselectable:
      return html_names::kAriaMultiselectableAttr;
    case AOMBooleanProperty::kReadOnly:
      return html_names::kAriaReadonlyAttr;
    case AOMBooleanProperty::kRequired:
      return html_names::kAriaRequiredAttr;
    case AOMBooleanProperty::kSelected:
      return html_names::kAriaSelectedAttr;
  }

  NOTREACHED();
  return g_null_name;
}

QualifiedName GetCorrespondingARIAAttribute(AOMFloatProperty property) {
  AtomicString attr_value;
  switch (property) {
    case AOMFloatProperty::kValueMax:
      return html_names::kAriaValuemaxAttr;
    case AOMFloatProperty::kValueMin:
      return html_names::kAriaValueminAttr;
    case AOMFloatProperty::kValueNow:
      return html_names::kAriaValuenowAttr;
  }

  NOTREACHED();
  return g_null_name;
}

QualifiedName GetCorrespondingARIAAttribute(AOMUIntProperty property) {
  switch (property) {
    case AOMUIntProperty::kColIndex:
      return html_names::kAriaColindexAttr;
    case AOMUIntProperty::kColSpan:
      return html_names::kAriaColspanAttr;
    case AOMUIntProperty::kLevel:
      return html_names::kAriaLevelAttr;
    case AOMUIntProperty::kPosInSet:
      return html_names::kAriaPosinsetAttr;
    case AOMUIntProperty::kRowIndex:
      return html_names::kAriaRowindexAttr;
    case AOMUIntProperty::kRowSpan:
      return html_names::kAriaRowspanAttr;
  }

  NOTREACHED();
  return g_null_name;
}

QualifiedName GetCorrespondingARIAAttribute(AOMIntProperty property) {
  switch (property) {
    case AOMIntProperty::kColCount:
      return html_names::kAriaColcountAttr;
    case AOMIntProperty::kRowCount:
      return html_names::kAriaRowcountAttr;
    case AOMIntProperty::kSetSize:
      return html_names::kAriaSetsizeAttr;
  }

  NOTREACHED();
  return g_null_name;
}

}  // namespace

AccessibleNode::AccessibleNode(Element* element)
    : element_(element), document_(nullptr) {
  DCHECK(RuntimeEnabledFeatures::AccessibilityObjectModelEnabled());
}

AccessibleNode::AccessibleNode(Document& document)
    : element_(nullptr), document_(document) {
  DCHECK(RuntimeEnabledFeatures::AccessibilityObjectModelEnabled());
}

AccessibleNode::~AccessibleNode() = default;

// static
AccessibleNode* AccessibleNode::Create(Document& document) {
  return MakeGarbageCollected<AccessibleNode>(document);
}

Document* AccessibleNode::GetDocument() const {
  if (document_)
    return document_;
  if (element_)
    return &element_->GetDocument();

  NOTREACHED();
  return nullptr;
}

const AtomicString& AccessibleNode::GetProperty(
    AOMStringProperty property) const {
  for (const auto& item : string_properties_) {
    if (item.first == property && !item.second.IsNull())
      return item.second;
  }

  return g_null_atom;
}

// static
AccessibleNode* AccessibleNode::GetProperty(Element* element,
                                            AOMRelationProperty property) {
  if (!element)
    return nullptr;

  if (AccessibleNode* accessible_node = element->ExistingAccessibleNode()) {
    for (const auto& item : accessible_node->relation_properties_) {
      if (item.first == property && item.second)
        return item.second;
    }
  }

  return nullptr;
}

// static
AccessibleNodeList* AccessibleNode::GetProperty(
    Element* element,
    AOMRelationListProperty property) {
  if (!element)
    return nullptr;

  if (AccessibleNode* accessible_node = element->ExistingAccessibleNode()) {
    for (const auto& item : accessible_node->relation_list_properties_) {
      if (item.first == property && item.second)
        return item.second;
    }
  }

  return nullptr;
}

// static
bool AccessibleNode::GetProperty(Element* element,
                                 AOMRelationListProperty property,
                                 HeapVector<Member<Element>>& targets) {
  AccessibleNodeList* node_list = GetProperty(element, property);
  if (!node_list)
    return false;

  for (wtf_size_t i = 0; i < node_list->length(); ++i) {
    AccessibleNode* accessible_node = node_list->item(i);
    if (accessible_node) {
      if (Element* target_element = accessible_node->element())
        targets.push_back(target_element);
    }
  }

  return true;
}

template <typename P, typename T>
static base::Optional<T> FindPropertyValue(
    P property,
    const Vector<std::pair<P, T>>& properties) {
  for (const auto& item : properties) {
    if (item.first == property)
      return item.second;
  }
  return base::nullopt;
}

base::Optional<bool> AccessibleNode::GetProperty(
    AOMBooleanProperty property) const {
  return FindPropertyValue(property, boolean_properties_);
}

// static
base::Optional<int32_t> AccessibleNode::GetProperty(Element* element,
                                                    AOMIntProperty property) {
  if (!element || !element->ExistingAccessibleNode())
    return base::nullopt;
  return FindPropertyValue(property,
                           element->ExistingAccessibleNode()->int_properties_);
}

// static
base::Optional<uint32_t> AccessibleNode::GetProperty(Element* element,
                                                     AOMUIntProperty property) {
  if (!element || !element->ExistingAccessibleNode())
    return base::nullopt;
  return FindPropertyValue(property,
                           element->ExistingAccessibleNode()->uint_properties_);
}

// static
base::Optional<float> AccessibleNode::GetProperty(Element* element,
                                                  AOMFloatProperty property) {
  if (!element || !element->ExistingAccessibleNode())
    return base::nullopt;
  return FindPropertyValue(
      property, element->ExistingAccessibleNode()->float_properties_);
}

bool AccessibleNode::IsUndefinedAttrValue(const AtomicString& value) {
  return value.IsEmpty() || EqualIgnoringASCIICase(value, "undefined");
}

// static
const AtomicString& AccessibleNode::GetElementOrInternalsARIAAttribute(
    Element& element,
    const QualifiedName& attribute,
    bool is_token_attr) {
  const AtomicString& attr_value = element.FastGetAttribute(attribute);
  if ((attr_value != g_null_atom) &&
      (!is_token_attr || !IsUndefinedAttrValue(attr_value))) {
    return attr_value;
  }

  if (!element.DidAttachInternals())
    return g_null_atom;

  return element.EnsureElementInternals().FastGetAttribute(attribute);
}

// static
const AtomicString& AccessibleNode::GetPropertyOrARIAAttribute(
    Element* element,
    AOMStringProperty property) {
  if (!element)
    return g_null_atom;

  const bool is_token_attr = IsStringTokenProperty(property);

  // We are currently only checking ARIA attributes, instead of AccessibleNode
  // properties. Further refactoring will be happening as the API is finalised.
  QualifiedName attribute = GetCorrespondingARIAAttribute(property);
  const AtomicString& attr_value =
      GetElementOrInternalsARIAAttribute(*element, attribute, is_token_attr);
  if (is_token_attr && IsUndefinedAttrValue(attr_value))
    return g_null_atom;  // Attribute not set or explicitly undefined.

  return attr_value;
}

// static
Element* AccessibleNode::GetPropertyOrARIAAttribute(
    Element* element,
    AOMRelationProperty property) {
  if (!element)
    return nullptr;
  QualifiedName attribute = GetCorrespondingARIAAttribute(property);
  AtomicString value = GetElementOrInternalsARIAAttribute(*element, attribute);
  return element->GetTreeScope().getElementById(value);
}

// static
bool AccessibleNode::GetPropertyOrARIAAttribute(
    Element* element,
    AOMRelationListProperty property,
    HeapVector<Member<Element>>& targets) {
  if (!element)
    return false;
  QualifiedName attribute = GetCorrespondingARIAAttribute(property);
  String value =
      GetElementOrInternalsARIAAttribute(*element, attribute).GetString();
  if (value.IsEmpty() && property == AOMRelationListProperty::kLabeledBy) {
    value = GetElementOrInternalsARIAAttribute(*element,
                                               html_names::kAriaLabeledbyAttr)
                .GetString();
  }
  if (value.IsEmpty())
    return false;

  Vector<String> ids;
  value.Split(' ', ids);
  if (ids.IsEmpty())
    return false;

  TreeScope& scope = element->GetTreeScope();
  for (const auto& id : ids) {
    if (Element* id_element = scope.getElementById(AtomicString(id)))
      targets.push_back(id_element);
  }
  return true;
}

// static
bool AccessibleNode::GetPropertyOrARIAAttribute(Element* element,
                                                AOMBooleanProperty property,
                                                bool& is_null) {
  is_null = true;
  if (!element)
    return false;

  // Fall back on the equivalent ARIA attribute.
  QualifiedName attribute = GetCorrespondingARIAAttribute(property);
  AtomicString attr_value =
      GetElementOrInternalsARIAAttribute(*element, attribute);
  is_null = IsUndefinedAttrValue(attr_value);
  return !is_null && !EqualIgnoringASCIICase(attr_value, "false");
}

// static
float AccessibleNode::GetPropertyOrARIAAttribute(Element* element,
                                                 AOMFloatProperty property,
                                                 bool& is_null) {
  is_null = true;
  if (!element)
    return 0.0;

  // Fall back on the equivalent ARIA attribute.
  QualifiedName attribute = GetCorrespondingARIAAttribute(property);
  AtomicString attr_value =
      GetElementOrInternalsARIAAttribute(*element, attribute);
  is_null = attr_value.IsNull();
  return attr_value.ToFloat();
}

// static
uint32_t AccessibleNode::GetPropertyOrARIAAttribute(Element* element,
                                                    AOMUIntProperty property,
                                                    bool& is_null) {
  is_null = true;
  if (!element)
    return 0;

  // Fall back on the equivalent ARIA attribute.
  QualifiedName attribute = GetCorrespondingARIAAttribute(property);
  AtomicString attr_value =
      GetElementOrInternalsARIAAttribute(*element, attribute);
  is_null = attr_value.IsNull();
  return attr_value.GetString().ToUInt();
}

// static
int32_t AccessibleNode::GetPropertyOrARIAAttribute(Element* element,
                                                   AOMIntProperty property,
                                                   bool& is_null) {
  is_null = true;
  if (!element)
    return 0;

  // Fall back on the equivalent ARIA attribute.
  QualifiedName attribute = GetCorrespondingARIAAttribute(property);
  AtomicString attr_value =
      GetElementOrInternalsARIAAttribute(*element, attribute);
  is_null = attr_value.IsNull();
  return attr_value.ToInt();
}

void AccessibleNode::GetAllAOMProperties(AOMPropertyClient* client) {
  for (auto& item : string_properties_) {
    client->AddStringProperty(item.first, item.second);
  }
  for (auto& item : boolean_properties_) {
    client->AddBooleanProperty(item.first, item.second);
  }
  for (auto& item : float_properties_) {
    client->AddFloatProperty(item.first, item.second);
  }
  for (auto& item : relation_properties_) {
    if (!item.second)
      continue;
    client->AddRelationProperty(item.first, *item.second);
  }
  for (auto& item : relation_list_properties_) {
    if (!item.second)
      continue;
    client->AddRelationListProperty(item.first, *item.second);
  }
}

AccessibleNode* AccessibleNode::activeDescendant() const {
  return GetProperty(element_, AOMRelationProperty::kActiveDescendant);
}

void AccessibleNode::setActiveDescendant(AccessibleNode* active_descendant) {
  SetRelationProperty(AOMRelationProperty::kActiveDescendant,
                      active_descendant);
  NotifyAttributeChanged(html_names::kAriaActivedescendantAttr);
}

base::Optional<bool> AccessibleNode::atomic() const {
  return GetProperty(AOMBooleanProperty::kAtomic);
}

void AccessibleNode::setAtomic(base::Optional<bool> value) {
  SetBooleanProperty(AOMBooleanProperty::kAtomic, value);
  NotifyAttributeChanged(html_names::kAriaAtomicAttr);
}

AtomicString AccessibleNode::autocomplete() const {
  return GetProperty(AOMStringProperty::kAutocomplete);
}

void AccessibleNode::setAutocomplete(const AtomicString& autocomplete) {
  SetStringProperty(AOMStringProperty::kAutocomplete, autocomplete);
  NotifyAttributeChanged(html_names::kAriaAutocompleteAttr);
}

base::Optional<bool> AccessibleNode::busy() const {
  return GetProperty(AOMBooleanProperty::kBusy);
}

void AccessibleNode::setBusy(base::Optional<bool> value) {
  SetBooleanProperty(AOMBooleanProperty::kBusy, value);
  NotifyAttributeChanged(html_names::kAriaBusyAttr);
}

AtomicString AccessibleNode::checked() const {
  return GetProperty(AOMStringProperty::kChecked);
}

void AccessibleNode::setChecked(const AtomicString& checked) {
  SetStringProperty(AOMStringProperty::kChecked, checked);
  NotifyAttributeChanged(html_names::kAriaCheckedAttr);
}

base::Optional<int32_t> AccessibleNode::colCount() const {
  return GetProperty(element_, AOMIntProperty::kColCount);
}

void AccessibleNode::setColCount(base::Optional<int32_t> value) {
  SetIntProperty(AOMIntProperty::kColCount, value);
  NotifyAttributeChanged(html_names::kAriaColcountAttr);
}

base::Optional<uint32_t> AccessibleNode::colIndex() const {
  return GetProperty(element_, AOMUIntProperty::kColIndex);
}

void AccessibleNode::setColIndex(base::Optional<uint32_t> value) {
  SetUIntProperty(AOMUIntProperty::kColIndex, value);
  NotifyAttributeChanged(html_names::kAriaColindexAttr);
}

base::Optional<uint32_t> AccessibleNode::colSpan() const {
  return GetProperty(element_, AOMUIntProperty::kColSpan);
}

void AccessibleNode::setColSpan(base::Optional<uint32_t> value) {
  SetUIntProperty(AOMUIntProperty::kColSpan, value);
  NotifyAttributeChanged(html_names::kAriaColspanAttr);
}

AccessibleNodeList* AccessibleNode::controls() const {
  return GetProperty(element_, AOMRelationListProperty::kControls);
}

void AccessibleNode::setControls(AccessibleNodeList* controls) {
  SetRelationListProperty(AOMRelationListProperty::kControls, controls);
  NotifyAttributeChanged(html_names::kAriaControlsAttr);
}

AtomicString AccessibleNode::current() const {
  return GetProperty(AOMStringProperty::kCurrent);
}

void AccessibleNode::setCurrent(const AtomicString& current) {
  SetStringProperty(AOMStringProperty::kCurrent, current);
  NotifyAttributeChanged(html_names::kAriaCurrentAttr);
}

AccessibleNodeList* AccessibleNode::describedBy() {
  return GetProperty(element_, AOMRelationListProperty::kDescribedBy);
}

void AccessibleNode::setDescribedBy(AccessibleNodeList* described_by) {
  SetRelationListProperty(AOMRelationListProperty::kDescribedBy, described_by);
  NotifyAttributeChanged(html_names::kAriaDescribedbyAttr);
}

AtomicString AccessibleNode::description() const {
  return GetProperty(AOMStringProperty::kDescription);
}

void AccessibleNode::setDescription(const AtomicString& description) {
  SetStringProperty(AOMStringProperty::kDescription, description);
  NotifyAttributeChanged(html_names::kAriaDescriptionAttr);
}

AccessibleNodeList* AccessibleNode::details() const {
  return GetProperty(element_, AOMRelationListProperty::kDetails);
}

void AccessibleNode::setDetails(AccessibleNodeList* details) {
  SetRelationListProperty(AOMRelationListProperty::kDetails, details);
  NotifyAttributeChanged(html_names::kAriaDetailsAttr);
}

base::Optional<bool> AccessibleNode::disabled() const {
  return GetProperty(AOMBooleanProperty::kDisabled);
}

void AccessibleNode::setDisabled(base::Optional<bool> value) {
  SetBooleanProperty(AOMBooleanProperty::kDisabled, value);
  NotifyAttributeChanged(html_names::kAriaDisabledAttr);
}

AccessibleNode* AccessibleNode::errorMessage() const {
  return GetProperty(element_, AOMRelationProperty::kErrorMessage);
}

void AccessibleNode::setErrorMessage(AccessibleNode* error_message) {
  SetRelationProperty(AOMRelationProperty::kErrorMessage, error_message);
  NotifyAttributeChanged(html_names::kAriaErrormessageAttr);
}

base::Optional<bool> AccessibleNode::expanded() const {
  return GetProperty(AOMBooleanProperty::kExpanded);
}

void AccessibleNode::setExpanded(base::Optional<bool> value) {
  SetBooleanProperty(AOMBooleanProperty::kExpanded, value);
  NotifyAttributeChanged(html_names::kAriaExpandedAttr);
}

AccessibleNodeList* AccessibleNode::flowTo() const {
  return GetProperty(element_, AOMRelationListProperty::kFlowTo);
}

void AccessibleNode::setFlowTo(AccessibleNodeList* flow_to) {
  SetRelationListProperty(AOMRelationListProperty::kFlowTo, flow_to);
  NotifyAttributeChanged(html_names::kAriaFlowtoAttr);
}

AtomicString AccessibleNode::hasPopUp() const {
  return GetProperty(AOMStringProperty::kHasPopUp);
}

void AccessibleNode::setHasPopUp(const AtomicString& has_popup) {
  SetStringProperty(AOMStringProperty::kHasPopUp, has_popup);
  NotifyAttributeChanged(html_names::kAriaHaspopupAttr);
}

base::Optional<bool> AccessibleNode::hidden() const {
  return GetProperty(AOMBooleanProperty::kHidden);
}

void AccessibleNode::setHidden(base::Optional<bool> value) {
  SetBooleanProperty(AOMBooleanProperty::kHidden, value);
  NotifyAttributeChanged(html_names::kAriaHiddenAttr);
}

AtomicString AccessibleNode::invalid() const {
  return GetProperty(AOMStringProperty::kInvalid);
}

void AccessibleNode::setInvalid(const AtomicString& invalid) {
  SetStringProperty(AOMStringProperty::kInvalid, invalid);
  NotifyAttributeChanged(html_names::kAriaInvalidAttr);
}

AtomicString AccessibleNode::keyShortcuts() const {
  return GetProperty(AOMStringProperty::kKeyShortcuts);
}

void AccessibleNode::setKeyShortcuts(const AtomicString& key_shortcuts) {
  SetStringProperty(AOMStringProperty::kKeyShortcuts, key_shortcuts);
  NotifyAttributeChanged(html_names::kAriaKeyshortcutsAttr);
}

AtomicString AccessibleNode::label() const {
  return GetProperty(AOMStringProperty::kLabel);
}

void AccessibleNode::setLabel(const AtomicString& label) {
  SetStringProperty(AOMStringProperty::kLabel, label);
  NotifyAttributeChanged(html_names::kAriaLabelAttr);
}

AccessibleNodeList* AccessibleNode::labeledBy() {
  return GetProperty(element_, AOMRelationListProperty::kLabeledBy);
}

void AccessibleNode::setLabeledBy(AccessibleNodeList* labeled_by) {
  SetRelationListProperty(AOMRelationListProperty::kLabeledBy, labeled_by);
  NotifyAttributeChanged(html_names::kAriaLabelledbyAttr);
}

base::Optional<uint32_t> AccessibleNode::level() const {
  return GetProperty(element_, AOMUIntProperty::kLevel);
}

void AccessibleNode::setLevel(base::Optional<uint32_t> value) {
  SetUIntProperty(AOMUIntProperty::kLevel, value);
  NotifyAttributeChanged(html_names::kAriaLevelAttr);
}

AtomicString AccessibleNode::live() const {
  return GetProperty(AOMStringProperty::kLive);
}

void AccessibleNode::setLive(const AtomicString& live) {
  SetStringProperty(AOMStringProperty::kLive, live);
  NotifyAttributeChanged(html_names::kAriaLiveAttr);
}

base::Optional<bool> AccessibleNode::modal() const {
  return GetProperty(AOMBooleanProperty::kModal);
}

void AccessibleNode::setModal(base::Optional<bool> value) {
  SetBooleanProperty(AOMBooleanProperty::kModal, value);
  NotifyAttributeChanged(html_names::kAriaModalAttr);
}

base::Optional<bool> AccessibleNode::multiline() const {
  return GetProperty(AOMBooleanProperty::kMultiline);
}

void AccessibleNode::setMultiline(base::Optional<bool> value) {
  SetBooleanProperty(AOMBooleanProperty::kMultiline, value);
  NotifyAttributeChanged(html_names::kAriaMultilineAttr);
}

base::Optional<bool> AccessibleNode::multiselectable() const {
  return GetProperty(AOMBooleanProperty::kMultiselectable);
}

void AccessibleNode::setMultiselectable(base::Optional<bool> value) {
  SetBooleanProperty(AOMBooleanProperty::kMultiselectable, value);
  NotifyAttributeChanged(html_names::kAriaMultiselectableAttr);
}

AtomicString AccessibleNode::orientation() const {
  return GetProperty(AOMStringProperty::kOrientation);
}

void AccessibleNode::setOrientation(const AtomicString& orientation) {
  SetStringProperty(AOMStringProperty::kOrientation, orientation);
  NotifyAttributeChanged(html_names::kAriaOrientationAttr);
}

AccessibleNodeList* AccessibleNode::owns() const {
  return GetProperty(element_, AOMRelationListProperty::kOwns);
}

void AccessibleNode::setOwns(AccessibleNodeList* owns) {
  SetRelationListProperty(AOMRelationListProperty::kOwns, owns);
  NotifyAttributeChanged(html_names::kAriaOwnsAttr);
}

AtomicString AccessibleNode::placeholder() const {
  return GetProperty(AOMStringProperty::kPlaceholder);
}

void AccessibleNode::setPlaceholder(const AtomicString& placeholder) {
  SetStringProperty(AOMStringProperty::kPlaceholder, placeholder);
  NotifyAttributeChanged(html_names::kAriaPlaceholderAttr);
}

base::Optional<uint32_t> AccessibleNode::posInSet() const {
  return GetProperty(element_, AOMUIntProperty::kPosInSet);
}

void AccessibleNode::setPosInSet(base::Optional<uint32_t> value) {
  SetUIntProperty(AOMUIntProperty::kPosInSet, value);
  NotifyAttributeChanged(html_names::kAriaPosinsetAttr);
}

AtomicString AccessibleNode::pressed() const {
  return GetProperty(AOMStringProperty::kPressed);
}

void AccessibleNode::setPressed(const AtomicString& pressed) {
  SetStringProperty(AOMStringProperty::kPressed, pressed);
  NotifyAttributeChanged(html_names::kAriaPressedAttr);
}

base::Optional<bool> AccessibleNode::readOnly() const {
  return GetProperty(AOMBooleanProperty::kReadOnly);
}

void AccessibleNode::setReadOnly(base::Optional<bool> value) {
  SetBooleanProperty(AOMBooleanProperty::kReadOnly, value);
  NotifyAttributeChanged(html_names::kAriaReadonlyAttr);
}

AtomicString AccessibleNode::relevant() const {
  return GetProperty(AOMStringProperty::kRelevant);
}

void AccessibleNode::setRelevant(const AtomicString& relevant) {
  SetStringProperty(AOMStringProperty::kRelevant, relevant);
  NotifyAttributeChanged(html_names::kAriaRelevantAttr);
}

base::Optional<bool> AccessibleNode::required() const {
  return GetProperty(AOMBooleanProperty::kRequired);
}

void AccessibleNode::setRequired(base::Optional<bool> value) {
  SetBooleanProperty(AOMBooleanProperty::kRequired, value);
  NotifyAttributeChanged(html_names::kAriaRequiredAttr);
}

AtomicString AccessibleNode::role() const {
  return GetProperty(AOMStringProperty::kRole);
}

void AccessibleNode::setRole(const AtomicString& role) {
  SetStringProperty(AOMStringProperty::kRole, role);
  NotifyAttributeChanged(html_names::kRoleAttr);
}

AtomicString AccessibleNode::roleDescription() const {
  return GetProperty(AOMStringProperty::kRoleDescription);
}

void AccessibleNode::setRoleDescription(const AtomicString& role_description) {
  SetStringProperty(AOMStringProperty::kRoleDescription, role_description);
  NotifyAttributeChanged(html_names::kAriaRoledescriptionAttr);
}

base::Optional<int32_t> AccessibleNode::rowCount() const {
  return GetProperty(element_, AOMIntProperty::kRowCount);
}

void AccessibleNode::setRowCount(base::Optional<int32_t> value) {
  SetIntProperty(AOMIntProperty::kRowCount, value);
  NotifyAttributeChanged(html_names::kAriaRowcountAttr);
}

base::Optional<uint32_t> AccessibleNode::rowIndex() const {
  return GetProperty(element_, AOMUIntProperty::kRowIndex);
}

void AccessibleNode::setRowIndex(base::Optional<uint32_t> value) {
  SetUIntProperty(AOMUIntProperty::kRowIndex, value);
  NotifyAttributeChanged(html_names::kAriaRowindexAttr);
}

base::Optional<uint32_t> AccessibleNode::rowSpan() const {
  return GetProperty(element_, AOMUIntProperty::kRowSpan);
}

void AccessibleNode::setRowSpan(base::Optional<uint32_t> value) {
  SetUIntProperty(AOMUIntProperty::kRowSpan, value);
  NotifyAttributeChanged(html_names::kAriaRowspanAttr);
}

base::Optional<bool> AccessibleNode::selected() const {
  return GetProperty(AOMBooleanProperty::kSelected);
}

void AccessibleNode::setSelected(base::Optional<bool> value) {
  SetBooleanProperty(AOMBooleanProperty::kSelected, value);
  NotifyAttributeChanged(html_names::kAriaSelectedAttr);
}

base::Optional<int32_t> AccessibleNode::setSize() const {
  return GetProperty(element_, AOMIntProperty::kSetSize);
}

void AccessibleNode::setSetSize(base::Optional<int32_t> value) {
  SetIntProperty(AOMIntProperty::kSetSize, value);
  NotifyAttributeChanged(html_names::kAriaSetsizeAttr);
}

AtomicString AccessibleNode::sort() const {
  return GetProperty(AOMStringProperty::kSort);
}

void AccessibleNode::setSort(const AtomicString& sort) {
  SetStringProperty(AOMStringProperty::kSort, sort);
  NotifyAttributeChanged(html_names::kAriaSortAttr);
}

base::Optional<float> AccessibleNode::valueMax() const {
  return GetProperty(element_, AOMFloatProperty::kValueMax);
}

void AccessibleNode::setValueMax(base::Optional<float> value) {
  SetFloatProperty(AOMFloatProperty::kValueMax, value);
  NotifyAttributeChanged(html_names::kAriaValuemaxAttr);
}

base::Optional<float> AccessibleNode::valueMin() const {
  return GetProperty(element_, AOMFloatProperty::kValueMin);
}

void AccessibleNode::setValueMin(base::Optional<float> value) {
  SetFloatProperty(AOMFloatProperty::kValueMin, value);
  NotifyAttributeChanged(html_names::kAriaValueminAttr);
}

base::Optional<float> AccessibleNode::valueNow() const {
  return GetProperty(element_, AOMFloatProperty::kValueNow);
}

void AccessibleNode::setValueNow(base::Optional<float> value) {
  SetFloatProperty(AOMFloatProperty::kValueNow, value);
  NotifyAttributeChanged(html_names::kAriaValuenowAttr);
}

AtomicString AccessibleNode::valueText() const {
  return GetProperty(AOMStringProperty::kValueText);
}

void AccessibleNode::setValueText(const AtomicString& value_text) {
  SetStringProperty(AOMStringProperty::kValueText, value_text);
  NotifyAttributeChanged(html_names::kAriaValuetextAttr);
}

AtomicString AccessibleNode::virtualContent() const {
  return GetProperty(AOMStringProperty::kVirtualContent);
}

void AccessibleNode::setVirtualContent(const AtomicString& virtual_content) {
  SetStringProperty(AOMStringProperty::kVirtualContent, virtual_content);
  NotifyAttributeChanged(html_names::kAriaVirtualcontentAttr);
}

AccessibleNodeList* AccessibleNode::childNodes() {
  return AccessibleNodeList::Create(children_);
}

void AccessibleNode::appendChild(AccessibleNode* child,
                                 ExceptionState& exception_state) {
  if (child->element()) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kInvalidAccessError,
        "An AccessibleNode associated with an Element cannot be a child.");
    return;
  }

  if (child->parent_) {
    exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
                                      "Reparenting is not supported yet.");
    return;
  }
  child->parent_ = this;

  if (!GetExecutionContext()->GetSecurityOrigin()->CanAccess(
          child->GetExecutionContext()->GetSecurityOrigin())) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kInvalidAccessError,
        "Trying to access an AccessibleNode from a different origin.");
    return;
  }

  children_.push_back(child);
  if (AXObjectCache* cache = GetAXObjectCache())
    cache->ChildrenChanged(this);
}

void AccessibleNode::removeChild(AccessibleNode* old_child,
                                 ExceptionState& exception_state) {
  if (old_child->parent_ != this) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kInvalidAccessError,
        "Node to remove is not a child of this node.");
    return;
  }
  auto* ix = std::find_if(children_.begin(), children_.end(),
                          [old_child](const Member<AccessibleNode> child) {
                            return child.Get() == old_child;
                          });
  if (ix == children_.end()) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kInvalidAccessError,
        "Node to remove is not a child of this node.");
    return;
  }
  old_child->parent_ = nullptr;
  children_.erase(ix);

  if (AXObjectCache* cache = GetAXObjectCache())
    cache->ChildrenChanged(this);
}

// These properties support a list of tokens, and "undefined"/"" is
// equivalent to not setting the attribute.
bool AccessibleNode::IsStringTokenProperty(AOMStringProperty property) {
  switch (property) {
    case AOMStringProperty::kAutocomplete:
    case AOMStringProperty::kChecked:
    case AOMStringProperty::kCurrent:
    case AOMStringProperty::kHasPopUp:
    case AOMStringProperty::kInvalid:
    case AOMStringProperty::kLive:
    case AOMStringProperty::kOrientation:
    case AOMStringProperty::kPressed:
    case AOMStringProperty::kRelevant:
    case AOMStringProperty::kSort:
      return true;
    case AOMStringProperty::kDescription:
    case AOMStringProperty::kKeyShortcuts:
    case AOMStringProperty::kLabel:
    case AOMStringProperty::kPlaceholder:
    case AOMStringProperty::kRole:  // Is token, but ""/"undefined" not
                                    // supported.
    case AOMStringProperty::kRoleDescription:
    case AOMStringProperty::kValueText:
    case AOMStringProperty::kVirtualContent:
      break;
  }
  return false;
}

const AtomicString& AccessibleNode::InterfaceName() const {
  return event_target_names::kAccessibleNode;
}

ExecutionContext* AccessibleNode::GetExecutionContext() const {
  if (element_)
    return element_->GetExecutionContext();

  if (parent_)
    return parent_->GetExecutionContext();

  return nullptr;
}

void AccessibleNode::SetStringProperty(AOMStringProperty property,
                                       const AtomicString& value) {
  for (auto& item : string_properties_) {
    if (item.first == property) {
      item.second = value;
      return;
    }
  }

  string_properties_.push_back(std::make_pair(property, value));
}

void AccessibleNode::SetRelationProperty(AOMRelationProperty property,
                                         AccessibleNode* value) {
  for (auto& item : relation_properties_) {
    if (item.first == property) {
      item.second = value;
      return;
    }
  }

  relation_properties_.push_back(std::make_pair(property, value));
}

void AccessibleNode::SetRelationListProperty(AOMRelationListProperty property,
                                             AccessibleNodeList* value) {
  for (auto& item : relation_list_properties_) {
    if (item.first == property) {
      if (item.second)
        item.second->RemoveOwner(property, this);
      if (value)
        value->AddOwner(property, this);
      item.second = value;
      return;
    }
  }

  relation_list_properties_.push_back(std::make_pair(property, value));
}

template <typename P, typename T>
static void SetProperty(P property,
                        base::Optional<T> value,
                        Vector<std::pair<P, T>>& properties) {
  for (wtf_size_t i = 0; i < properties.size(); i++) {
    auto& item = properties[i];
    if (item.first == property) {
      if (value.has_value())
        item.second = value.value();
      else
        properties.EraseAt(i);
      return;
    }
  }

  if (value.has_value())
    properties.push_back(std::make_pair(property, value.value()));
}

void AccessibleNode::SetBooleanProperty(AOMBooleanProperty property,
                                        base::Optional<bool> value) {
  SetProperty(property, value, boolean_properties_);
}

void AccessibleNode::SetIntProperty(AOMIntProperty property,
                                    base::Optional<int32_t> value) {
  SetProperty(property, value, int_properties_);
}

void AccessibleNode::SetUIntProperty(AOMUIntProperty property,
                                     base::Optional<uint32_t> value) {
  SetProperty(property, value, uint_properties_);
}

void AccessibleNode::SetFloatProperty(AOMFloatProperty property,
                                      base::Optional<float> value) {
  SetProperty(property, value, float_properties_);
}

void AccessibleNode::OnRelationListChanged(AOMRelationListProperty property) {
  NotifyAttributeChanged(GetCorrespondingARIAAttribute(property));
}

void AccessibleNode::NotifyAttributeChanged(
    const blink::QualifiedName& attribute) {
  // TODO(dmazzoni): Make a cleaner API for this rather than pretending
  // the DOM attribute changed.
  AXObjectCache* cache = GetAXObjectCache();
  if (!cache)
    return;

  if (!element_) {
    cache->HandleAttributeChanged(attribute, this);
    return;
  }

  // By definition, any attribute on an AccessibleNode is interesting to
  // AXObjectCache, so no need to check return value.
  cache->HandleAttributeChanged(attribute, element_);
}

AXObjectCache* AccessibleNode::GetAXObjectCache() {
  return GetDocument()->ExistingAXObjectCache();
}

void AccessibleNode::Trace(Visitor* visitor) const {
  visitor->Trace(element_);
  visitor->Trace(document_);
  visitor->Trace(relation_properties_);
  visitor->Trace(relation_list_properties_);
  visitor->Trace(children_);
  visitor->Trace(parent_);
  EventTargetWithInlineData::Trace(visitor);
}

}  // namespace blink
