// 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.

#include "accessibility_bridge.h"

#include <functional>
#include <utility>

#include "flutter/third_party/accessibility/ax/ax_tree_manager_map.h"
#include "flutter/third_party/accessibility/ax/ax_tree_update.h"
#include "flutter/third_party/accessibility/base/logging.h"

namespace flutter {  // namespace

constexpr int kHasScrollingAction =
    FlutterSemanticsAction::kFlutterSemanticsActionScrollLeft |
    FlutterSemanticsAction::kFlutterSemanticsActionScrollRight |
    FlutterSemanticsAction::kFlutterSemanticsActionScrollUp |
    FlutterSemanticsAction::kFlutterSemanticsActionScrollDown;

// AccessibilityBridge
AccessibilityBridge::AccessibilityBridge()
    : tree_(std::make_unique<ui::AXTree>()) {
  event_generator_.SetTree(tree_.get());
  tree_->AddObserver(static_cast<ui::AXTreeObserver*>(this));
  ui::AXTreeData data = tree_->data();
  data.tree_id = ui::AXTreeID::CreateNewAXTreeID();
  tree_->UpdateData(data);
  ui::AXTreeManagerMap::GetInstance().AddTreeManager(tree_->GetAXTreeID(),
                                                     this);
}

AccessibilityBridge::~AccessibilityBridge() {
  event_generator_.ReleaseTree();
  tree_->RemoveObserver(static_cast<ui::AXTreeObserver*>(this));
}

void AccessibilityBridge::AddFlutterSemanticsNodeUpdate(
    const FlutterSemanticsNode2& node) {
  pending_semantics_node_updates_[node.id] = FromFlutterSemanticsNode(node);
}

void AccessibilityBridge::AddFlutterSemanticsCustomActionUpdate(
    const FlutterSemanticsCustomAction2& action) {
  pending_semantics_custom_action_updates_[action.id] =
      FromFlutterSemanticsCustomAction(action);
}

void AccessibilityBridge::CommitUpdates() {
  // AXTree cannot move a node in a single update.
  // This must be split across two updates:
  //
  // * Update 1: remove nodes from their old parents.
  // * Update 2: re-add nodes (including their children) to their new parents.
  //
  // First, start by removing nodes if necessary.
  std::optional<ui::AXTreeUpdate> remove_reparented =
      CreateRemoveReparentedNodesUpdate();
  if (remove_reparented.has_value()) {
    tree_->Unserialize(remove_reparented.value());

    std::string error = tree_->error();
    if (!error.empty()) {
      FML_LOG(ERROR) << "Failed to update ui::AXTree, error: " << error;
      assert(false);
      return;
    }
  }

  // Second, apply the pending node updates. This also moves reparented nodes to
  // their new parents if needed.
  ui::AXTreeUpdate update{.tree_data = tree_->data()};

  // Figure out update order, ui::AXTree only accepts update in tree order,
  // where parent node must come before the child node in
  // ui::AXTreeUpdate.nodes. We start with picking a random node and turn the
  // entire subtree into a list. We pick another node from the remaining update,
  // and keep doing so until the update map is empty. We then concatenate the
  // lists in the reversed order, this guarantees parent updates always come
  // before child updates. If the root is in the update, it is guaranteed to
  // be the first node of the last list.
  std::vector<std::vector<SemanticsNode>> results;
  while (!pending_semantics_node_updates_.empty()) {
    auto begin = pending_semantics_node_updates_.begin();
    SemanticsNode target = begin->second;
    std::vector<SemanticsNode> sub_tree_list;
    GetSubTreeList(target, sub_tree_list);
    results.push_back(sub_tree_list);
    pending_semantics_node_updates_.erase(begin);
  }

  for (size_t i = results.size(); i > 0; i--) {
    for (SemanticsNode node : results[i - 1]) {
      ConvertFlutterUpdate(node, update);
    }
  }

  // The first update must set the tree's root, which is guaranteed to be the
  // last list's first node. A tree's root node never changes, though it can be
  // modified.
  if (!results.empty() && GetRootAsAXNode()->id() == ui::AXNode::kInvalidAXID) {
    FML_DCHECK(!results.back().empty());

    update.root_id = results.back().front().id;
  }

  tree_->Unserialize(update);
  pending_semantics_node_updates_.clear();
  pending_semantics_custom_action_updates_.clear();

  std::string error = tree_->error();
  if (!error.empty()) {
    FML_LOG(ERROR) << "Failed to update ui::AXTree, error: " << error;
    return;
  }
  // Handles accessibility events as the result of the semantics update.
  for (const auto& targeted_event : event_generator_) {
    auto event_target =
        GetFlutterPlatformNodeDelegateFromID(targeted_event.node->id());
    if (event_target.expired()) {
      continue;
    }

    OnAccessibilityEvent(targeted_event);
  }
  event_generator_.ClearEvents();
}

std::weak_ptr<FlutterPlatformNodeDelegate>
AccessibilityBridge::GetFlutterPlatformNodeDelegateFromID(
    AccessibilityNodeId id) const {
  const auto iter = id_wrapper_map_.find(id);
  if (iter != id_wrapper_map_.end()) {
    return iter->second;
  }

  return std::weak_ptr<FlutterPlatformNodeDelegate>();
}

const ui::AXTreeData& AccessibilityBridge::GetAXTreeData() const {
  return tree_->data();
}

const std::vector<ui::AXEventGenerator::TargetedEvent>
AccessibilityBridge::GetPendingEvents() const {
  std::vector<ui::AXEventGenerator::TargetedEvent> result(
      event_generator_.begin(), event_generator_.end());
  return result;
}

void AccessibilityBridge::OnNodeWillBeDeleted(ui::AXTree* tree,
                                              ui::AXNode* node) {}

void AccessibilityBridge::OnSubtreeWillBeDeleted(ui::AXTree* tree,
                                                 ui::AXNode* node) {}

void AccessibilityBridge::OnNodeReparented(ui::AXTree* tree, ui::AXNode* node) {
}

void AccessibilityBridge::OnRoleChanged(ui::AXTree* tree,
                                        ui::AXNode* node,
                                        ax::mojom::Role old_role,
                                        ax::mojom::Role new_role) {}

void AccessibilityBridge::OnNodeCreated(ui::AXTree* tree, ui::AXNode* node) {
  BASE_DCHECK(node);
  id_wrapper_map_[node->id()] = CreateFlutterPlatformNodeDelegate();
  id_wrapper_map_[node->id()]->Init(
      std::static_pointer_cast<FlutterPlatformNodeDelegate::OwnerBridge>(
          shared_from_this()),
      node);
}

void AccessibilityBridge::OnNodeDeleted(ui::AXTree* tree,
                                        AccessibilityNodeId node_id) {
  BASE_DCHECK(node_id != ui::AXNode::kInvalidAXID);
  if (id_wrapper_map_.find(node_id) != id_wrapper_map_.end()) {
    id_wrapper_map_.erase(node_id);
  }
}

void AccessibilityBridge::OnAtomicUpdateFinished(
    ui::AXTree* tree,
    bool root_changed,
    const std::vector<ui::AXTreeObserver::Change>& changes) {
  // The Flutter semantics update does not include child->parent relationship
  // We have to update the relative bound offset container id here in order
  // to calculate the screen bound correctly.
  for (const auto& change : changes) {
    ui::AXNode* node = change.node;
    const ui::AXNodeData& data = node->data();
    AccessibilityNodeId offset_container_id = -1;
    if (node->parent()) {
      offset_container_id = node->parent()->id();
    }
    node->SetLocation(offset_container_id, data.relative_bounds.bounds,
                      data.relative_bounds.transform.get());
  }
}

std::optional<ui::AXTreeUpdate>
AccessibilityBridge::CreateRemoveReparentedNodesUpdate() {
  std::unordered_map<int32_t, ui::AXNodeData> updates;

  for (auto node_update : pending_semantics_node_updates_) {
    for (int32_t child_id : node_update.second.children_in_traversal_order) {
      // Skip nodes that don't exist or have a parent in the current tree.
      ui::AXNode* child = tree_->GetFromId(child_id);
      if (!child) {
        continue;
      }

      // Flutter's root node should never be reparented.
      assert(child->parent());

      // Skip nodes whose parents are unchanged.
      if (child->parent()->id() == node_update.second.id) {
        continue;
      }

      // This pending update moves the current child node.
      // That new child must have a corresponding pending update.
      assert(pending_semantics_node_updates_.find(child_id) !=
             pending_semantics_node_updates_.end());

      // Create an update to remove the child from its previous parent.
      int32_t parent_id = child->parent()->id();
      if (updates.find(parent_id) == updates.end()) {
        updates[parent_id] = tree_->GetFromId(parent_id)->data();
      }

      ui::AXNodeData* parent = &updates[parent_id];
      auto iter = std::find(parent->child_ids.begin(), parent->child_ids.end(),
                            child_id);

      assert(iter != parent->child_ids.end());
      parent->child_ids.erase(iter);
    }
  }

  if (updates.empty()) {
    return std::nullopt;
  }

  ui::AXTreeUpdate update{
      .tree_data = tree_->data(),
      .nodes = std::vector<ui::AXNodeData>(),
  };

  for (std::pair<int32_t, ui::AXNodeData> data : updates) {
    update.nodes.push_back(std::move(data.second));
  }

  return update;
}

// Private method.
void AccessibilityBridge::GetSubTreeList(const SemanticsNode& target,
                                         std::vector<SemanticsNode>& result) {
  result.push_back(target);
  for (int32_t child : target.children_in_traversal_order) {
    auto iter = pending_semantics_node_updates_.find(child);
    if (iter != pending_semantics_node_updates_.end()) {
      SemanticsNode node = iter->second;
      GetSubTreeList(node, result);
      pending_semantics_node_updates_.erase(iter);
    }
  }
}

void AccessibilityBridge::ConvertFlutterUpdate(const SemanticsNode& node,
                                               ui::AXTreeUpdate& tree_update) {
  ui::AXNodeData node_data;
  node_data.id = node.id;
  SetRoleFromFlutterUpdate(node_data, node);
  SetStateFromFlutterUpdate(node_data, node);
  SetActionsFromFlutterUpdate(node_data, node);
  SetBooleanAttributesFromFlutterUpdate(node_data, node);
  SetIntAttributesFromFlutterUpdate(node_data, node);
  SetIntListAttributesFromFlutterUpdate(node_data, node);
  SetStringListAttributesFromFlutterUpdate(node_data, node);
  SetNameFromFlutterUpdate(node_data, node);
  SetValueFromFlutterUpdate(node_data, node);
  SetTooltipFromFlutterUpdate(node_data, node);
  node_data.relative_bounds.bounds.SetRect(node.rect.left, node.rect.top,
                                           node.rect.right - node.rect.left,
                                           node.rect.bottom - node.rect.top);
  node_data.relative_bounds.transform = std::make_unique<gfx::Transform>(
      node.transform.scaleX, node.transform.skewX, node.transform.transX, 0,
      node.transform.skewY, node.transform.scaleY, node.transform.transY, 0,
      node.transform.pers0, node.transform.pers1, node.transform.pers2, 0, 0, 0,
      0, 0);
  for (auto child : node.children_in_traversal_order) {
    node_data.child_ids.push_back(child);
  }
  SetTreeData(node, tree_update);
  tree_update.nodes.push_back(node_data);
}

void AccessibilityBridge::SetRoleFromFlutterUpdate(ui::AXNodeData& node_data,
                                                   const SemanticsNode& node) {
  FlutterSemanticsFlag flags = node.flags;
  if (flags & FlutterSemanticsFlag::kFlutterSemanticsFlagIsButton) {
    node_data.role = ax::mojom::Role::kButton;
    return;
  }
  if (flags & FlutterSemanticsFlag::kFlutterSemanticsFlagIsTextField &&
      !(flags & FlutterSemanticsFlag::kFlutterSemanticsFlagIsReadOnly)) {
    node_data.role = ax::mojom::Role::kTextField;
    return;
  }
  if (flags & FlutterSemanticsFlag::kFlutterSemanticsFlagIsHeader) {
    node_data.role = ax::mojom::Role::kHeader;
    return;
  }
  if (flags & FlutterSemanticsFlag::kFlutterSemanticsFlagIsImage) {
    node_data.role = ax::mojom::Role::kImage;
    return;
  }
  if (flags & FlutterSemanticsFlag::kFlutterSemanticsFlagIsLink) {
    node_data.role = ax::mojom::Role::kLink;
    return;
  }

  if (flags & kFlutterSemanticsFlagIsInMutuallyExclusiveGroup &&
      flags & kFlutterSemanticsFlagHasCheckedState) {
    node_data.role = ax::mojom::Role::kRadioButton;
    return;
  }
  if (flags & kFlutterSemanticsFlagHasCheckedState) {
    node_data.role = ax::mojom::Role::kCheckBox;
    return;
  }
  if (flags & kFlutterSemanticsFlagHasToggledState) {
    node_data.role = ax::mojom::Role::kToggleButton;
    return;
  }
  if (flags & kFlutterSemanticsFlagIsSlider) {
    node_data.role = ax::mojom::Role::kSlider;
    return;
  }
  // If the state cannot be derived from the flutter flags, we fallback to group
  // or static text.
  if (node.children_in_traversal_order.empty()) {
    node_data.role = ax::mojom::Role::kStaticText;
  } else {
    node_data.role = ax::mojom::Role::kGroup;
  }
}

void AccessibilityBridge::SetStateFromFlutterUpdate(ui::AXNodeData& node_data,
                                                    const SemanticsNode& node) {
  FlutterSemanticsFlag flags = node.flags;
  FlutterSemanticsAction actions = node.actions;
  if (flags & FlutterSemanticsFlag::kFlutterSemanticsFlagHasExpandedState &&
      flags & FlutterSemanticsFlag::kFlutterSemanticsFlagIsExpanded) {
    node_data.AddState(ax::mojom::State::kExpanded);
  } else if (flags &
             FlutterSemanticsFlag::kFlutterSemanticsFlagHasExpandedState) {
    node_data.AddState(ax::mojom::State::kCollapsed);
  }
  if (flags & FlutterSemanticsFlag::kFlutterSemanticsFlagIsTextField &&
      (flags & FlutterSemanticsFlag::kFlutterSemanticsFlagIsReadOnly) == 0) {
    node_data.AddState(ax::mojom::State::kEditable);
  }
  if (node_data.role == ax::mojom::Role::kStaticText &&
      (actions & kHasScrollingAction) == 0 && node.value.empty() &&
      node.label.empty() && node.hint.empty()) {
    node_data.AddState(ax::mojom::State::kIgnored);
  } else {
    // kFlutterSemanticsFlagIsFocusable means a keyboard focusable, it is
    // different from semantics focusable.
    // TODO(chunhtai): figure out whether something is not semantics focusable.
    node_data.AddState(ax::mojom::State::kFocusable);
  }
}

void AccessibilityBridge::SetActionsFromFlutterUpdate(
    ui::AXNodeData& node_data,
    const SemanticsNode& node) {
  FlutterSemanticsAction actions = node.actions;
  if (actions & FlutterSemanticsAction::kFlutterSemanticsActionTap) {
    node_data.AddAction(ax::mojom::Action::kDoDefault);
  }
  if (actions & FlutterSemanticsAction::kFlutterSemanticsActionScrollLeft) {
    node_data.AddAction(ax::mojom::Action::kScrollLeft);
  }
  if (actions & FlutterSemanticsAction::kFlutterSemanticsActionScrollRight) {
    node_data.AddAction(ax::mojom::Action::kScrollRight);
  }
  if (actions & FlutterSemanticsAction::kFlutterSemanticsActionScrollUp) {
    node_data.AddAction(ax::mojom::Action::kScrollUp);
  }
  if (actions & FlutterSemanticsAction::kFlutterSemanticsActionScrollDown) {
    node_data.AddAction(ax::mojom::Action::kScrollDown);
  }
  if (actions & FlutterSemanticsAction::kFlutterSemanticsActionIncrease) {
    node_data.AddAction(ax::mojom::Action::kIncrement);
  }
  if (actions & FlutterSemanticsAction::kFlutterSemanticsActionDecrease) {
    node_data.AddAction(ax::mojom::Action::kDecrement);
  }
  // Every node has show on screen action.
  node_data.AddAction(ax::mojom::Action::kScrollToMakeVisible);

  if (actions & FlutterSemanticsAction::kFlutterSemanticsActionSetSelection) {
    node_data.AddAction(ax::mojom::Action::kSetSelection);
  }
  if (actions & FlutterSemanticsAction::
                    kFlutterSemanticsActionDidGainAccessibilityFocus) {
    node_data.AddAction(ax::mojom::Action::kSetAccessibilityFocus);
  }
  if (actions & FlutterSemanticsAction::
                    kFlutterSemanticsActionDidLoseAccessibilityFocus) {
    node_data.AddAction(ax::mojom::Action::kClearAccessibilityFocus);
  }
  if (actions & FlutterSemanticsAction::kFlutterSemanticsActionCustomAction) {
    node_data.AddAction(ax::mojom::Action::kCustomAction);
  }
}

void AccessibilityBridge::SetBooleanAttributesFromFlutterUpdate(
    ui::AXNodeData& node_data,
    const SemanticsNode& node) {
  FlutterSemanticsAction actions = node.actions;
  FlutterSemanticsFlag flags = node.flags;
  node_data.AddBoolAttribute(ax::mojom::BoolAttribute::kScrollable,
                             actions & kHasScrollingAction);
  node_data.AddBoolAttribute(
      ax::mojom::BoolAttribute::kClickable,
      actions & FlutterSemanticsAction::kFlutterSemanticsActionTap);
  // TODO(chunhtai): figure out if there is a node that does not clip overflow.
  node_data.AddBoolAttribute(ax::mojom::BoolAttribute::kClipsChildren,
                             !node.children_in_traversal_order.empty());
  node_data.AddBoolAttribute(
      ax::mojom::BoolAttribute::kSelected,
      flags & FlutterSemanticsFlag::kFlutterSemanticsFlagIsSelected);
  node_data.AddBoolAttribute(
      ax::mojom::BoolAttribute::kEditableRoot,
      flags & FlutterSemanticsFlag::kFlutterSemanticsFlagIsTextField &&
          (flags & FlutterSemanticsFlag::kFlutterSemanticsFlagIsReadOnly) == 0);
  // Mark nodes as line breaking so that screen readers don't
  // merge all consecutive objects into one.
  // TODO(schectman): When should a node have this attribute set?
  // https://github.com/flutter/flutter/issues/118184
  node_data.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
                             true);
}

void AccessibilityBridge::SetIntAttributesFromFlutterUpdate(
    ui::AXNodeData& node_data,
    const SemanticsNode& node) {
  FlutterSemanticsFlag flags = node.flags;
  node_data.AddIntAttribute(ax::mojom::IntAttribute::kTextDirection,
                            node.text_direction);

  int sel_start = node.text_selection_base;
  int sel_end = node.text_selection_extent;
  if (flags & FlutterSemanticsFlag::kFlutterSemanticsFlagIsTextField &&
      (flags & FlutterSemanticsFlag::kFlutterSemanticsFlagIsReadOnly) == 0 &&
      !node.value.empty()) {
    // By default the text field selection should be at the end.
    sel_start = sel_start == -1 ? node.value.length() : sel_start;
    sel_end = sel_end == -1 ? node.value.length() : sel_end;
  }
  node_data.AddIntAttribute(ax::mojom::IntAttribute::kTextSelStart, sel_start);
  node_data.AddIntAttribute(ax::mojom::IntAttribute::kTextSelEnd, sel_end);

  if (node_data.role == ax::mojom::Role::kRadioButton ||
      node_data.role == ax::mojom::Role::kCheckBox) {
    node_data.AddIntAttribute(
        ax::mojom::IntAttribute::kCheckedState,
        static_cast<int32_t>(
            flags & FlutterSemanticsFlag::kFlutterSemanticsFlagIsCheckStateMixed
                ? ax::mojom::CheckedState::kMixed
            : flags & FlutterSemanticsFlag::kFlutterSemanticsFlagIsChecked
                ? ax::mojom::CheckedState::kTrue
                : ax::mojom::CheckedState::kFalse));
  } else if (node_data.role == ax::mojom::Role::kToggleButton) {
    node_data.AddIntAttribute(
        ax::mojom::IntAttribute::kCheckedState,
        static_cast<int32_t>(
            flags & FlutterSemanticsFlag::kFlutterSemanticsFlagIsToggled
                ? ax::mojom::CheckedState::kTrue
                : ax::mojom::CheckedState::kFalse));
  }
}

void AccessibilityBridge::SetIntListAttributesFromFlutterUpdate(
    ui::AXNodeData& node_data,
    const SemanticsNode& node) {
  FlutterSemanticsAction actions = node.actions;
  if (actions & FlutterSemanticsAction::kFlutterSemanticsActionCustomAction) {
    std::vector<int32_t> custom_action_ids;
    for (size_t i = 0; i < node.custom_accessibility_actions.size(); i++) {
      custom_action_ids.push_back(node.custom_accessibility_actions[i]);
    }
    node_data.AddIntListAttribute(ax::mojom::IntListAttribute::kCustomActionIds,
                                  custom_action_ids);
  }
}

void AccessibilityBridge::SetStringListAttributesFromFlutterUpdate(
    ui::AXNodeData& node_data,
    const SemanticsNode& node) {
  FlutterSemanticsAction actions = node.actions;
  if (actions & FlutterSemanticsAction::kFlutterSemanticsActionCustomAction) {
    std::vector<std::string> custom_action_description;
    for (size_t i = 0; i < node.custom_accessibility_actions.size(); i++) {
      auto iter = pending_semantics_custom_action_updates_.find(
          node.custom_accessibility_actions[i]);
      BASE_DCHECK(iter != pending_semantics_custom_action_updates_.end());
      custom_action_description.push_back(iter->second.label);
    }
    node_data.AddStringListAttribute(
        ax::mojom::StringListAttribute::kCustomActionDescriptions,
        custom_action_description);
  }
}

void AccessibilityBridge::SetNameFromFlutterUpdate(ui::AXNodeData& node_data,
                                                   const SemanticsNode& node) {
  node_data.SetName(node.label);
}

void AccessibilityBridge::SetValueFromFlutterUpdate(ui::AXNodeData& node_data,
                                                    const SemanticsNode& node) {
  node_data.SetValue(node.value);
}

void AccessibilityBridge::SetTooltipFromFlutterUpdate(
    ui::AXNodeData& node_data,
    const SemanticsNode& node) {
  node_data.SetTooltip(node.tooltip);
}

void AccessibilityBridge::SetTreeData(const SemanticsNode& node,
                                      ui::AXTreeUpdate& tree_update) {
  FlutterSemanticsFlag flags = node.flags;
  // Set selection of the focused node if:
  // 1. this text field has a valid selection
  // 2. this text field doesn't have a valid selection but had selection stored
  //    in the tree.
  if (flags & FlutterSemanticsFlag::kFlutterSemanticsFlagIsTextField &&
      flags & FlutterSemanticsFlag::kFlutterSemanticsFlagIsFocused) {
    if (node.text_selection_base != -1) {
      tree_update.tree_data.sel_anchor_object_id = node.id;
      tree_update.tree_data.sel_anchor_offset = node.text_selection_base;
      tree_update.tree_data.sel_focus_object_id = node.id;
      tree_update.tree_data.sel_focus_offset = node.text_selection_extent;
      tree_update.has_tree_data = true;
    } else if (tree_update.tree_data.sel_anchor_object_id == node.id) {
      tree_update.tree_data.sel_anchor_object_id = ui::AXNode::kInvalidAXID;
      tree_update.tree_data.sel_anchor_offset = -1;
      tree_update.tree_data.sel_focus_object_id = ui::AXNode::kInvalidAXID;
      tree_update.tree_data.sel_focus_offset = -1;
      tree_update.has_tree_data = true;
    }
  }

  if (flags & FlutterSemanticsFlag::kFlutterSemanticsFlagIsFocused &&
      tree_update.tree_data.focus_id != node.id) {
    tree_update.tree_data.focus_id = node.id;
    tree_update.has_tree_data = true;
  } else if ((flags & FlutterSemanticsFlag::kFlutterSemanticsFlagIsFocused) ==
                 0 &&
             tree_update.tree_data.focus_id == node.id) {
    tree_update.tree_data.focus_id = ui::AXNode::kInvalidAXID;
    tree_update.has_tree_data = true;
  }
}

AccessibilityBridge::SemanticsNode
AccessibilityBridge::FromFlutterSemanticsNode(
    const FlutterSemanticsNode2& flutter_node) {
  SemanticsNode result;
  result.id = flutter_node.id;
  result.flags = flutter_node.flags;
  result.actions = flutter_node.actions;
  result.text_selection_base = flutter_node.text_selection_base;
  result.text_selection_extent = flutter_node.text_selection_extent;
  result.scroll_child_count = flutter_node.scroll_child_count;
  result.scroll_index = flutter_node.scroll_index;
  result.scroll_position = flutter_node.scroll_position;
  result.scroll_extent_max = flutter_node.scroll_extent_max;
  result.scroll_extent_min = flutter_node.scroll_extent_min;
  result.elevation = flutter_node.elevation;
  result.thickness = flutter_node.thickness;
  if (flutter_node.label) {
    result.label = std::string(flutter_node.label);
  }
  if (flutter_node.hint) {
    result.hint = std::string(flutter_node.hint);
  }
  if (flutter_node.value) {
    result.value = std::string(flutter_node.value);
  }
  if (flutter_node.increased_value) {
    result.increased_value = std::string(flutter_node.increased_value);
  }
  if (flutter_node.decreased_value) {
    result.decreased_value = std::string(flutter_node.decreased_value);
  }
  if (flutter_node.tooltip) {
    result.tooltip = std::string(flutter_node.tooltip);
  }
  result.text_direction = flutter_node.text_direction;
  result.rect = flutter_node.rect;
  result.transform = flutter_node.transform;
  if (flutter_node.child_count > 0) {
    result.children_in_traversal_order = std::vector<int32_t>(
        flutter_node.children_in_traversal_order,
        flutter_node.children_in_traversal_order + flutter_node.child_count);
  }
  if (flutter_node.custom_accessibility_actions_count > 0) {
    result.custom_accessibility_actions = std::vector<int32_t>(
        flutter_node.custom_accessibility_actions,
        flutter_node.custom_accessibility_actions +
            flutter_node.custom_accessibility_actions_count);
  }
  return result;
}

AccessibilityBridge::SemanticsCustomAction
AccessibilityBridge::FromFlutterSemanticsCustomAction(
    const FlutterSemanticsCustomAction2& flutter_custom_action) {
  SemanticsCustomAction result;
  result.id = flutter_custom_action.id;
  result.override_action = flutter_custom_action.override_action;
  if (flutter_custom_action.label) {
    result.label = std::string(flutter_custom_action.label);
  }
  if (flutter_custom_action.hint) {
    result.hint = std::string(flutter_custom_action.hint);
  }
  return result;
}

void AccessibilityBridge::SetLastFocusedId(AccessibilityNodeId node_id) {
  if (last_focused_id_ != node_id) {
    auto last_focused_child =
        GetFlutterPlatformNodeDelegateFromID(last_focused_id_);
    if (!last_focused_child.expired()) {
      DispatchAccessibilityAction(
          last_focused_id_,
          FlutterSemanticsAction::
              kFlutterSemanticsActionDidLoseAccessibilityFocus,
          {});
    }
    last_focused_id_ = node_id;
  }
}

AccessibilityNodeId AccessibilityBridge::GetLastFocusedId() {
  return last_focused_id_;
}

gfx::NativeViewAccessible AccessibilityBridge::GetNativeAccessibleFromId(
    AccessibilityNodeId id) {
  auto platform_node_delegate = GetFlutterPlatformNodeDelegateFromID(id).lock();
  if (!platform_node_delegate) {
    return nullptr;
  }
  return platform_node_delegate->GetNativeViewAccessible();
}

gfx::RectF AccessibilityBridge::RelativeToGlobalBounds(const ui::AXNode* node,
                                                       bool& offscreen,
                                                       bool clip_bounds) {
  return tree_->RelativeToTreeBounds(node, gfx::RectF(), &offscreen,
                                     clip_bounds);
}

ui::AXNode* AccessibilityBridge::GetNodeFromTree(
    ui::AXTreeID tree_id,
    ui::AXNode::AXID node_id) const {
  return GetNodeFromTree(node_id);
}

ui::AXNode* AccessibilityBridge::GetNodeFromTree(
    ui::AXNode::AXID node_id) const {
  return tree_->GetFromId(node_id);
}

ui::AXTreeID AccessibilityBridge::GetTreeID() const {
  return tree_->GetAXTreeID();
}

ui::AXTreeID AccessibilityBridge::GetParentTreeID() const {
  return ui::AXTreeIDUnknown();
}

ui::AXNode* AccessibilityBridge::GetRootAsAXNode() const {
  return tree_->root();
}

ui::AXNode* AccessibilityBridge::GetParentNodeFromParentTreeAsAXNode() const {
  return nullptr;
}

ui::AXTree* AccessibilityBridge::GetTree() const {
  return tree_.get();
}

ui::AXPlatformNode* AccessibilityBridge::GetPlatformNodeFromTree(
    const ui::AXNode::AXID node_id) const {
  auto platform_delegate_weak = GetFlutterPlatformNodeDelegateFromID(node_id);
  auto platform_delegate = platform_delegate_weak.lock();
  if (!platform_delegate) {
    return nullptr;
  }
  return platform_delegate->GetPlatformNode();
}

ui::AXPlatformNode* AccessibilityBridge::GetPlatformNodeFromTree(
    const ui::AXNode& node) const {
  return GetPlatformNodeFromTree(node.id());
}

ui::AXPlatformNodeDelegate* AccessibilityBridge::RootDelegate() const {
  return GetFlutterPlatformNodeDelegateFromID(GetRootAsAXNode()->id())
      .lock()
      .get();
}

}  // namespace flutter
