// 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 "flutter/shell/platform/fuchsia/flutter/accessibility_bridge.h"

#include <lib/inspect/cpp/inspector.h>
#include <lib/zx/process.h>
#include <zircon/status.h>
#include <zircon/types.h>

#include <deque>

#include "flutter/fml/logging.h"
#include "flutter/lib/ui/semantics/semantics_node.h"
#include "runtime/dart/utils/root_inspect_node.h"

namespace flutter_runner {
namespace {

// Returns the ViewRef's koid.
zx_koid_t GetKoid(const fuchsia::ui::views::ViewRef& view_ref) {
  zx_handle_t handle = view_ref.reference.get();
  zx_info_handle_basic_t info;
  zx_status_t status = zx_object_get_info(handle, ZX_INFO_HANDLE_BASIC, &info,
                                          sizeof(info), nullptr, nullptr);
  return status == ZX_OK ? info.koid : ZX_KOID_INVALID;
}

#if !FLUTTER_RELEASE
static constexpr char kTreeDumpInspectRootName[] = "semantic_tree_root";

// Converts flutter semantic node flags to a string representation.
std::string NodeFlagsToString(const flutter::SemanticsNode& node) {
  std::string output;
  if (node.HasFlag(flutter::SemanticsFlags::kHasCheckedState)) {
    output += "kHasCheckedState|";
  }
  if (node.HasFlag(flutter::SemanticsFlags::kHasEnabledState)) {
    output += "kHasEnabledState|";
  }
  if (node.HasFlag(flutter::SemanticsFlags::kHasImplicitScrolling)) {
    output += "kHasImplicitScrolling|";
  }
  if (node.HasFlag(flutter::SemanticsFlags::kHasToggledState)) {
    output += "kHasToggledState|";
  }
  if (node.HasFlag(flutter::SemanticsFlags::kIsButton)) {
    output += "kIsButton|";
  }
  if (node.HasFlag(flutter::SemanticsFlags::kIsChecked)) {
    output += "kIsChecked|";
  }
  if (node.HasFlag(flutter::SemanticsFlags::kIsEnabled)) {
    output += "kIsEnabled|";
  }
  if (node.HasFlag(flutter::SemanticsFlags::kIsFocusable)) {
    output += "kIsFocusable|";
  }
  if (node.HasFlag(flutter::SemanticsFlags::kIsFocused)) {
    output += "kIsFocused|";
  }
  if (node.HasFlag(flutter::SemanticsFlags::kIsHeader)) {
    output += "kIsHeader|";
  }
  if (node.HasFlag(flutter::SemanticsFlags::kIsHidden)) {
    output += "kIsHidden|";
  }
  if (node.HasFlag(flutter::SemanticsFlags::kIsImage)) {
    output += "kIsImage|";
  }
  if (node.HasFlag(flutter::SemanticsFlags::kIsInMutuallyExclusiveGroup)) {
    output += "kIsInMutuallyExclusiveGroup|";
  }
  if (node.HasFlag(flutter::SemanticsFlags::kIsKeyboardKey)) {
    output += "kIsKeyboardKey|";
  }
  if (node.HasFlag(flutter::SemanticsFlags::kIsLink)) {
    output += "kIsLink|";
  }
  if (node.HasFlag(flutter::SemanticsFlags::kIsLiveRegion)) {
    output += "kIsLiveRegion|";
  }
  if (node.HasFlag(flutter::SemanticsFlags::kIsObscured)) {
    output += "kIsObscured|";
  }
  if (node.HasFlag(flutter::SemanticsFlags::kIsReadOnly)) {
    output += "kIsReadOnly|";
  }
  if (node.HasFlag(flutter::SemanticsFlags::kIsSelected)) {
    output += "kIsSelected|";
  }
  if (node.HasFlag(flutter::SemanticsFlags::kIsSlider)) {
    output += "kIsSlider|";
  }
  if (node.HasFlag(flutter::SemanticsFlags::kIsTextField)) {
    output += "kIsTextField|";
  }
  if (node.HasFlag(flutter::SemanticsFlags::kIsToggled)) {
    output += "kIsToggled|";
  }
  if (node.HasFlag(flutter::SemanticsFlags::kNamesRoute)) {
    output += "kNamesRoute|";
  }
  if (node.HasFlag(flutter::SemanticsFlags::kScopesRoute)) {
    output += "kScopesRoute|";
  }

  return output;
}

// Converts flutter semantic node actions to a string representation.
std::string NodeActionsToString(const flutter::SemanticsNode& node) {
  std::string output;

  if (node.HasAction(flutter::SemanticsAction::kCopy)) {
    output += "kCopy|";
  }
  if (node.HasAction(flutter::SemanticsAction::kCustomAction)) {
    output += "kCustomAction|";
  }
  if (node.HasAction(flutter::SemanticsAction::kCut)) {
    output += "kCut|";
  }
  if (node.HasAction(flutter::SemanticsAction::kDecrease)) {
    output += "kDecrease|";
  }
  if (node.HasAction(flutter::SemanticsAction::kDidGainAccessibilityFocus)) {
    output += "kDidGainAccessibilityFocus|";
  }
  if (node.HasAction(flutter::SemanticsAction::kDidLoseAccessibilityFocus)) {
    output += "kDidLoseAccessibilityFocus|";
  }
  if (node.HasAction(flutter::SemanticsAction::kDismiss)) {
    output += "kDismiss|";
  }
  if (node.HasAction(flutter::SemanticsAction::kIncrease)) {
    output += "kIncrease|";
  }
  if (node.HasAction(flutter::SemanticsAction::kLongPress)) {
    output += "kLongPress|";
  }
  if (node.HasAction(
          flutter::SemanticsAction::kMoveCursorBackwardByCharacter)) {
    output += "kMoveCursorBackwardByCharacter|";
  }
  if (node.HasAction(
          flutter::SemanticsAction::kMoveCursorBackwardByWordIndex)) {
    output += "kMoveCursorBackwardByWordIndex|";
  }
  if (node.HasAction(flutter::SemanticsAction::kMoveCursorForwardByCharacter)) {
    output += "kMoveCursorForwardByCharacter|";
  }
  if (node.HasAction(flutter::SemanticsAction::kMoveCursorForwardByWordIndex)) {
    output += "kMoveCursorForwardByWordIndex|";
  }
  if (node.HasAction(flutter::SemanticsAction::kPaste)) {
    output += "kPaste|";
  }
  if (node.HasAction(flutter::SemanticsAction::kScrollDown)) {
    output += "kScrollDown|";
  }
  if (node.HasAction(flutter::SemanticsAction::kScrollLeft)) {
    output += "kScrollLeft|";
  }
  if (node.HasAction(flutter::SemanticsAction::kScrollRight)) {
    output += "kScrollRight|";
  }
  if (node.HasAction(flutter::SemanticsAction::kScrollUp)) {
    output += "kScrollUp|";
  }
  if (node.HasAction(flutter::SemanticsAction::kSetSelection)) {
    output += "kSetSelection|";
  }
  if (node.HasAction(flutter::SemanticsAction::kSetText)) {
    output += "kSetText|";
  }
  if (node.HasAction(flutter::SemanticsAction::kShowOnScreen)) {
    output += "kShowOnScreen|";
  }
  if (node.HasAction(flutter::SemanticsAction::kTap)) {
    output += "kTap|";
  }

  return output;
}

// Returns a string representation of the flutter semantic node absolut
// location.
std::string NodeLocationToString(const SkRect& rect) {
  auto min_x = rect.fLeft;
  auto min_y = rect.fTop;
  auto max_x = rect.fRight;
  auto max_y = rect.fBottom;
  std::string location =
      "min(" + std::to_string(min_x) + ", " + std::to_string(min_y) + ") max(" +
      std::to_string(max_x) + ", " + std::to_string(max_y) + ")";

  return location;
}

// Returns a string representation of the node's different types of children.
std::string NodeChildrenToString(const flutter::SemanticsNode& node) {
  std::stringstream output;
  if (!node.childrenInTraversalOrder.empty()) {
    output << "children in traversal order:[";
    for (const auto child_id : node.childrenInTraversalOrder) {
      output << child_id << ", ";
    }
    output << "]\n";
  }
  if (!node.childrenInHitTestOrder.empty()) {
    output << "children in hit test order:[";
    for (const auto child_id : node.childrenInHitTestOrder) {
      output << child_id << ", ";
    }
    output << ']';
  }

  return output.str();
}
#endif  // !FLUTTER_RELEASE

}  // namespace

AccessibilityBridge::AccessibilityBridge(
    SetSemanticsEnabledCallback set_semantics_enabled_callback,
    DispatchSemanticsActionCallback dispatch_semantics_action_callback,
    const std::shared_ptr<sys::ServiceDirectory> services,
    fuchsia::ui::views::ViewRef view_ref)
    : AccessibilityBridge(std::move(set_semantics_enabled_callback),
                          std::move(dispatch_semantics_action_callback),
                          services,
                          dart_utils::RootInspectNode::CreateRootChild(
                              std::to_string(GetKoid(view_ref))),
                          std::move(view_ref)) {}

AccessibilityBridge::AccessibilityBridge(
    SetSemanticsEnabledCallback set_semantics_enabled_callback,
    DispatchSemanticsActionCallback dispatch_semantics_action_callback,
    const std::shared_ptr<sys::ServiceDirectory> services,
    inspect::Node inspect_node,
    fuchsia::ui::views::ViewRef view_ref)
    : set_semantics_enabled_callback_(
          std::move(set_semantics_enabled_callback)),
      dispatch_semantics_action_callback_(
          std::move(dispatch_semantics_action_callback)),
      binding_(this),
      inspect_node_(std::move(inspect_node)) {
  services->Connect(fuchsia::accessibility::semantics::SemanticsManager::Name_,
                    fuchsia_semantics_manager_.NewRequest().TakeChannel());
  fuchsia_semantics_manager_.set_error_handler([](zx_status_t status) {
    FML_LOG(ERROR) << "Flutter cannot connect to SemanticsManager with status: "
                   << zx_status_get_string(status) << ".";
  });
  fidl::InterfaceHandle<fuchsia::accessibility::semantics::SemanticListener>
      listener_handle;
  binding_.Bind(listener_handle.NewRequest());

#if !FLUTTER_RELEASE
  // The first argument to |CreateLazyValues| is the name of the lazy node, and
  // will only be displayed if the callback used to generate the node's content
  // fails. Therefore, we use an error message for this node name.
  inspect_node_tree_dump_ =
      inspect_node_.CreateLazyValues("dump_fail", [this]() {
        inspect::Inspector inspector;
        if (auto it = nodes_.find(kRootNodeId); it == nodes_.end()) {
          inspector.GetRoot().CreateString(
              "empty_tree", "this semantic tree is empty", &inspector);
        } else {
          FillInspectTree(
              kRootNodeId, /*current_level=*/1,
              inspector.GetRoot().CreateChild(kTreeDumpInspectRootName),
              &inspector);
        }
        return fit::make_ok_promise(std::move(inspector));
      });
#endif  // !FLUTTER_RELEASE

  fuchsia_semantics_manager_->RegisterViewForSemantics(
      std::move(view_ref), std::move(listener_handle), tree_ptr_.NewRequest());
}

bool AccessibilityBridge::GetSemanticsEnabled() const {
  return semantics_enabled_;
}

void AccessibilityBridge::SetSemanticsEnabled(bool enabled) {
  semantics_enabled_ = enabled;
  if (!enabled) {
    nodes_.clear();
  }
}

fuchsia::ui::gfx::BoundingBox AccessibilityBridge::GetNodeLocation(
    const flutter::SemanticsNode& node) const {
  fuchsia::ui::gfx::BoundingBox box;
  box.min.x = node.rect.fLeft;
  box.min.y = node.rect.fTop;
  box.min.z = static_cast<float>(node.elevation);
  box.max.x = node.rect.fRight;
  box.max.y = node.rect.fBottom;
  box.max.z = static_cast<float>(node.thickness);
  return box;
}

fuchsia::ui::gfx::mat4 AccessibilityBridge::GetNodeTransform(
    const flutter::SemanticsNode& node) const {
  return ConvertSkiaTransformToMat4(node.transform);
}

fuchsia::ui::gfx::mat4 AccessibilityBridge::ConvertSkiaTransformToMat4(
    const SkM44 transform) const {
  fuchsia::ui::gfx::mat4 value;
  float* m = value.matrix.data();
  transform.getColMajor(m);
  return value;
}

fuchsia::accessibility::semantics::Attributes
AccessibilityBridge::GetNodeAttributes(const flutter::SemanticsNode& node,
                                       size_t* added_size) const {
  fuchsia::accessibility::semantics::Attributes attributes;
  // TODO(MI4-2531): Don't truncate.
  if (node.label.size() > fuchsia::accessibility::semantics::MAX_LABEL_SIZE) {
    attributes.set_label(node.label.substr(
        0, fuchsia::accessibility::semantics::MAX_LABEL_SIZE));
    *added_size += fuchsia::accessibility::semantics::MAX_LABEL_SIZE;
  } else {
    attributes.set_label(node.label);
    *added_size += node.label.size();
  }

  if (node.HasFlag(flutter::SemanticsFlags::kIsKeyboardKey)) {
    attributes.set_is_keyboard_key(true);
  }

  return attributes;
}

fuchsia::accessibility::semantics::States AccessibilityBridge::GetNodeStates(
    const flutter::SemanticsNode& node,
    size_t* additional_size) const {
  fuchsia::accessibility::semantics::States states;
  (*additional_size) += sizeof(fuchsia::accessibility::semantics::States);

  // Set checked state.
  if (!node.HasFlag(flutter::SemanticsFlags::kHasCheckedState)) {
    states.set_checked_state(
        fuchsia::accessibility::semantics::CheckedState::NONE);
  } else {
    states.set_checked_state(
        node.HasFlag(flutter::SemanticsFlags::kIsChecked)
            ? fuchsia::accessibility::semantics::CheckedState::CHECKED
            : fuchsia::accessibility::semantics::CheckedState::UNCHECKED);
  }

  // Set selected state.
  states.set_selected(node.HasFlag(flutter::SemanticsFlags::kIsSelected));

  // Flutter's definition of a hidden node is different from Fuchsia, so it must
  // not be set here.

  // Set value.
  if (node.value.size() > fuchsia::accessibility::semantics::MAX_VALUE_SIZE) {
    states.set_value(node.value.substr(
        0, fuchsia::accessibility::semantics::MAX_VALUE_SIZE));
    (*additional_size) += fuchsia::accessibility::semantics::MAX_VALUE_SIZE;
  } else {
    states.set_value(node.value);
    (*additional_size) += node.value.size();
  }

  // Set toggled state.
  if (node.HasFlag(flutter::SemanticsFlags::kHasToggledState)) {
    states.set_toggled_state(
        node.HasFlag(flutter::SemanticsFlags::kIsToggled)
            ? fuchsia::accessibility::semantics::ToggledState::ON
            : fuchsia::accessibility::semantics::ToggledState::OFF);
  }

  return states;
}

std::vector<fuchsia::accessibility::semantics::Action>
AccessibilityBridge::GetNodeActions(const flutter::SemanticsNode& node,
                                    size_t* additional_size) const {
  std::vector<fuchsia::accessibility::semantics::Action> node_actions;

  if (node.HasAction(flutter::SemanticsAction::kTap)) {
    node_actions.push_back(fuchsia::accessibility::semantics::Action::DEFAULT);
  }
  if (node.HasAction(flutter::SemanticsAction::kLongPress)) {
    node_actions.push_back(
        fuchsia::accessibility::semantics::Action::SECONDARY);
  }
  if (node.HasAction(flutter::SemanticsAction::kShowOnScreen)) {
    node_actions.push_back(
        fuchsia::accessibility::semantics::Action::SHOW_ON_SCREEN);
  }
  if (node.HasAction(flutter::SemanticsAction::kIncrease)) {
    node_actions.push_back(
        fuchsia::accessibility::semantics::Action::INCREMENT);
  }
  if (node.HasAction(flutter::SemanticsAction::kDecrease)) {
    node_actions.push_back(
        fuchsia::accessibility::semantics::Action::DECREMENT);
  }

  *additional_size +=
      node_actions.size() * sizeof(fuchsia::accessibility::semantics::Action);
  return node_actions;
}

fuchsia::accessibility::semantics::Role AccessibilityBridge::GetNodeRole(
    const flutter::SemanticsNode& node) const {
  if (node.HasFlag(flutter::SemanticsFlags::kIsButton)) {
    return fuchsia::accessibility::semantics::Role::BUTTON;
  }

  if (node.HasFlag(flutter::SemanticsFlags::kIsTextField)) {
    return fuchsia::accessibility::semantics::Role::TEXT_FIELD;
  }

  if (node.HasFlag(flutter::SemanticsFlags::kIsLink)) {
    return fuchsia::accessibility::semantics::Role::LINK;
  }

  if (node.HasFlag(flutter::SemanticsFlags::kIsSlider)) {
    return fuchsia::accessibility::semantics::Role::SLIDER;
  }

  if (node.HasFlag(flutter::SemanticsFlags::kIsHeader)) {
    return fuchsia::accessibility::semantics::Role::HEADER;
  }
  if (node.HasFlag(flutter::SemanticsFlags::kIsImage)) {
    return fuchsia::accessibility::semantics::Role::IMAGE;
  }

  // If a flutter node supports the kIncrease or kDecrease actions, it can be
  // treated as a slider control by assistive technology. This is important
  // because users have special gestures to deal with sliders, and Fuchsia API
  // requires nodes that can receive this kind of action to be a slider control.
  if (node.HasAction(flutter::SemanticsAction::kIncrease) ||
      node.HasAction(flutter::SemanticsAction::kDecrease)) {
    return fuchsia::accessibility::semantics::Role::SLIDER;
  }

  // If a flutter node has a checked state, then we assume it is either a
  // checkbox or a radio button. We distinguish between checkboxes and
  // radio buttons based on membership in a mutually exclusive group.
  if (node.HasFlag(flutter::SemanticsFlags::kHasCheckedState)) {
    if (node.HasFlag(flutter::SemanticsFlags::kIsInMutuallyExclusiveGroup)) {
      return fuchsia::accessibility::semantics::Role::RADIO_BUTTON;
    } else {
      return fuchsia::accessibility::semantics::Role::CHECK_BOX;
    }
  }

  if (node.HasFlag(flutter::SemanticsFlags::kHasToggledState)) {
    return fuchsia::accessibility::semantics::Role::TOGGLE_SWITCH;
  }
  return fuchsia::accessibility::semantics::Role::UNKNOWN;
}

std::unordered_set<int32_t> AccessibilityBridge::GetDescendants(
    int32_t node_id) const {
  std::unordered_set<int32_t> descendents;
  std::deque<int32_t> to_process = {node_id};
  while (!to_process.empty()) {
    int32_t id = to_process.front();
    to_process.pop_front();
    descendents.emplace(id);

    auto it = nodes_.find(id);
    if (it != nodes_.end()) {
      const auto& node = it->second.data;
      for (const auto& child : node.childrenInHitTestOrder) {
        if (descendents.find(child) == descendents.end()) {
          to_process.push_back(child);
        } else {
          // This indicates either a cycle or a child with multiple parents.
          // Flutter should never let this happen, but the engine API does not
          // explicitly forbid it right now.
          // TODO(http://fxbug.dev/75905): Crash flutter accessibility bridge
          // when a cycle in the tree is found.
          FML_LOG(ERROR) << "Semantics Node " << child
                         << " has already been listed as a child of another "
                            "node, ignoring for parent "
                         << id << ".";
        }
      }
    }
  }
  return descendents;
}

// The only known usage of a negative number for a node ID is in the embedder
// API as a sentinel value, which is not expected here. No valid producer of
// nodes should give us a negative ID.
static uint32_t FlutterIdToFuchsiaId(int32_t flutter_node_id) {
  FML_DCHECK(flutter_node_id >= 0)
      << "Unexpectedly received a negative semantics node ID.";
  return static_cast<uint32_t>(flutter_node_id);
}

void AccessibilityBridge::PruneUnreachableNodes() {
  const auto& reachable_nodes = GetDescendants(kRootNodeId);
  std::vector<uint32_t> nodes_to_remove;
  auto iter = nodes_.begin();
  while (iter != nodes_.end()) {
    int32_t id = iter->first;
    if (reachable_nodes.find(id) == reachable_nodes.end()) {
      // TODO(MI4-2531): This shouldn't be strictly necessary at this level.
      if (sizeof(nodes_to_remove) + (nodes_to_remove.size() * kNodeIdSize) >=
          kMaxMessageSize) {
        tree_ptr_->DeleteSemanticNodes(std::move(nodes_to_remove));
        nodes_to_remove.clear();
      }
      nodes_to_remove.push_back(FlutterIdToFuchsiaId(id));
      iter = nodes_.erase(iter);
    } else {
      iter++;
    }
  }
  if (!nodes_to_remove.empty()) {
    tree_ptr_->DeleteSemanticNodes(std::move(nodes_to_remove));
  }
}

// TODO(FIDL-718) - remove this, handle the error instead in something like
// set_error_handler.
static void PrintNodeSizeError(uint32_t node_id) {
  FML_LOG(ERROR) << "Semantics node with ID " << node_id
                 << " exceeded the maximum FIDL message size and may not "
                    "be delivered to the accessibility manager service.";
}

void AccessibilityBridge::AddSemanticsNodeUpdate(
    const flutter::SemanticsNodeUpdates update,
    float view_pixel_ratio) {
  if (update.empty()) {
    return;
  }
  FML_DCHECK(nodes_.find(kRootNodeId) != nodes_.end() ||
             update.find(kRootNodeId) != update.end())
      << "AccessibilityBridge received an update with out ever getting a root "
         "node.";

  std::vector<fuchsia::accessibility::semantics::Node> fuchsia_nodes;
  size_t current_size = 0;
  bool has_root_node_update = false;
  // TODO(MI4-2498): Actions, Roles, hit test children, additional
  // flags/states/attr

  // TODO(MI4-1478): Support for partial updates for nodes > 64kb
  // e.g. if a node has a long label or more than 64k children.
  for (const auto& [flutter_node_id, flutter_node] : update) {
    size_t this_node_size = sizeof(fuchsia::accessibility::semantics::Node);
    // We handle root update separately in GetRootNodeUpdate.
    // TODO(chunhtai): remove this special case after we remove the inverse
    // view pixel ratio transformation in scenic view.
    // TODO(http://fxbug.dev/75908): Investigate flutter a11y bridge refactor
    // after removal of the inverse view pixel ratio transformation in scenic
    // view).
    if (flutter_node.id == kRootNodeId) {
      root_flutter_semantics_node_ = flutter_node;
      has_root_node_update = true;
      continue;
    }
    // Store the nodes for later hit testing and logging.
    nodes_[flutter_node.id].data = flutter_node;

    fuchsia::accessibility::semantics::Node fuchsia_node;
    std::vector<uint32_t> child_ids;
    // Send the nodes in traversal order, so the manager can figure out
    // traversal.
    for (int32_t flutter_child_id : flutter_node.childrenInTraversalOrder) {
      child_ids.push_back(FlutterIdToFuchsiaId(flutter_child_id));
    }
    // TODO(http://fxbug.dev/75910): check the usage of FlutterIdToFuchsiaId in
    // the flutter accessibility bridge.
    fuchsia_node.set_node_id(flutter_node.id)
        .set_role(GetNodeRole(flutter_node))
        .set_location(GetNodeLocation(flutter_node))
        .set_transform(GetNodeTransform(flutter_node))
        .set_attributes(GetNodeAttributes(flutter_node, &this_node_size))
        .set_states(GetNodeStates(flutter_node, &this_node_size))
        .set_actions(GetNodeActions(flutter_node, &this_node_size))
        .set_child_ids(child_ids);
    this_node_size +=
        kNodeIdSize * flutter_node.childrenInTraversalOrder.size();

    // TODO(MI4-2531, FIDL-718): Remove this
    // This is defensive. If, despite our best efforts, we ended up with a node
    // that is larger than the max fidl size, we send no updates.
    if (this_node_size >= kMaxMessageSize) {
      PrintNodeSizeError(flutter_node.id);
      return;
    }
    current_size += this_node_size;

    // If we would exceed the max FIDL message size by appending this node,
    // we should delete/update/commit now.
    if (current_size >= kMaxMessageSize) {
      tree_ptr_->UpdateSemanticNodes(std::move(fuchsia_nodes));
      fuchsia_nodes.clear();
      current_size = this_node_size;
    }
    fuchsia_nodes.push_back(std::move(fuchsia_node));
  }

  if (current_size > kMaxMessageSize) {
    PrintNodeSizeError(fuchsia_nodes.back().node_id());
  }

  // Handles root node update.
  if (has_root_node_update || last_seen_view_pixel_ratio_ != view_pixel_ratio) {
    last_seen_view_pixel_ratio_ = view_pixel_ratio;
    size_t root_node_size;
    fuchsia::accessibility::semantics::Node root_update =
        GetRootNodeUpdate(root_node_size);
    // TODO(MI4-2531, FIDL-718): Remove this
    // This is defensive. If, despite our best efforts, we ended up with a node
    // that is larger than the max fidl size, we send no updates.
    if (root_node_size >= kMaxMessageSize) {
      PrintNodeSizeError(kRootNodeId);
      return;
    }
    current_size += root_node_size;
    // If we would exceed the max FIDL message size by appending this node,
    // we should delete/update/commit now.
    if (current_size >= kMaxMessageSize) {
      tree_ptr_->UpdateSemanticNodes(std::move(fuchsia_nodes));
      fuchsia_nodes.clear();
    }
    fuchsia_nodes.push_back(std::move(root_update));
  }

  PruneUnreachableNodes();
  UpdateScreenRects();

  tree_ptr_->UpdateSemanticNodes(std::move(fuchsia_nodes));
  // TODO(dnfield): Implement the callback here
  // https://bugs.fuchsia.dev/p/fuchsia/issues/detail?id=35718.
  tree_ptr_->CommitUpdates([]() {});
}

fuchsia::accessibility::semantics::Node AccessibilityBridge::GetRootNodeUpdate(
    size_t& node_size) {
  fuchsia::accessibility::semantics::Node root_fuchsia_node;
  std::vector<uint32_t> child_ids;
  node_size = sizeof(fuchsia::accessibility::semantics::Node);
  for (int32_t flutter_child_id :
       root_flutter_semantics_node_.childrenInTraversalOrder) {
    child_ids.push_back(FlutterIdToFuchsiaId(flutter_child_id));
  }
  // Applies the inverse view pixel ratio transformation to the root node.
  float inverse_view_pixel_ratio = 1.f / last_seen_view_pixel_ratio_;
  SkM44 inverse_view_pixel_ratio_transform;
  inverse_view_pixel_ratio_transform.setScale(inverse_view_pixel_ratio,
                                              inverse_view_pixel_ratio, 1.f);

  SkM44 result = root_flutter_semantics_node_.transform *
                 inverse_view_pixel_ratio_transform;
  nodes_[root_flutter_semantics_node_.id].data = root_flutter_semantics_node_;

  // TODO(http://fxbug.dev/75910): check the usage of FlutterIdToFuchsiaId in
  // the flutter accessibility bridge.
  root_fuchsia_node.set_node_id(root_flutter_semantics_node_.id)
      .set_role(GetNodeRole(root_flutter_semantics_node_))
      .set_location(GetNodeLocation(root_flutter_semantics_node_))
      .set_transform(ConvertSkiaTransformToMat4(result))
      .set_attributes(
          GetNodeAttributes(root_flutter_semantics_node_, &node_size))
      .set_states(GetNodeStates(root_flutter_semantics_node_, &node_size))
      .set_actions(GetNodeActions(root_flutter_semantics_node_, &node_size))
      .set_child_ids(child_ids);
  node_size += kNodeIdSize *
               root_flutter_semantics_node_.childrenInTraversalOrder.size();
  return root_fuchsia_node;
}

void AccessibilityBridge::RequestAnnounce(const std::string message) {
  fuchsia::accessibility::semantics::SemanticEvent semantic_event;
  fuchsia::accessibility::semantics::AnnounceEvent announce_event;
  announce_event.set_message(message);
  semantic_event.set_announce(std::move(announce_event));

  tree_ptr_->SendSemanticEvent(std::move(semantic_event), []() {});
}

void AccessibilityBridge::UpdateScreenRects() {
  std::unordered_set<int32_t> visited_nodes;
  UpdateScreenRects(kRootNodeId, SkM44{}, &visited_nodes);
}

void AccessibilityBridge::UpdateScreenRects(
    int32_t node_id,
    SkM44 parent_transform,
    std::unordered_set<int32_t>* visited_nodes) {
  auto it = nodes_.find(node_id);
  if (it == nodes_.end()) {
    FML_LOG(ERROR) << "UpdateScreenRects called on unknown node";
    return;
  }
  auto& node = it->second;
  const auto& current_transform = parent_transform * node.data.transform;

  const auto& rect = node.data.rect;
  SkV4 dst[2] = {
      current_transform.map(rect.left(), rect.top(), 0, 1),
      current_transform.map(rect.right(), rect.bottom(), 0, 1),
  };
  node.screen_rect.setLTRB(dst[0].x, dst[0].y, dst[1].x, dst[1].y);
  node.screen_rect.sort();

  visited_nodes->emplace(node_id);

  for (uint32_t child_id : node.data.childrenInHitTestOrder) {
    if (visited_nodes->find(child_id) == visited_nodes->end()) {
      UpdateScreenRects(child_id, current_transform, visited_nodes);
    }
  }
}

std::optional<flutter::SemanticsAction>
AccessibilityBridge::GetFlutterSemanticsAction(
    fuchsia::accessibility::semantics::Action fuchsia_action,
    uint32_t node_id) {
  switch (fuchsia_action) {
    // The default action associated with the element.
    case fuchsia::accessibility::semantics::Action::DEFAULT:
      return flutter::SemanticsAction::kTap;
    // The secondary action associated with the element. This may correspond to
    // a long press (touchscreens) or right click (mouse).
    case fuchsia::accessibility::semantics::Action::SECONDARY:
      return flutter::SemanticsAction::kLongPress;
    // Set (input/non-accessibility) focus on this element.
    case fuchsia::accessibility::semantics::Action::SET_FOCUS:
      FML_DLOG(WARNING)
          << "Unsupported action SET_FOCUS sent for accessibility node "
          << node_id;
      return {};
    // Set the element's value.
    case fuchsia::accessibility::semantics::Action::SET_VALUE:
      FML_DLOG(WARNING)
          << "Unsupported action SET_VALUE sent for accessibility node "
          << node_id;
      return {};
    // Scroll node to make it visible.
    case fuchsia::accessibility::semantics::Action::SHOW_ON_SCREEN:
      return flutter::SemanticsAction::kShowOnScreen;
    case fuchsia::accessibility::semantics::Action::INCREMENT:
      return flutter::SemanticsAction::kIncrease;
    case fuchsia::accessibility::semantics::Action::DECREMENT:
      return flutter::SemanticsAction::kDecrease;
    default:
      FML_DLOG(WARNING) << "Unexpected action "
                        << static_cast<int32_t>(fuchsia_action)
                        << " sent for accessibility node " << node_id;
      return {};
  }
}

// |fuchsia::accessibility::semantics::SemanticListener|
void AccessibilityBridge::OnAccessibilityActionRequested(
    uint32_t node_id,
    fuchsia::accessibility::semantics::Action action,
    fuchsia::accessibility::semantics::SemanticListener::
        OnAccessibilityActionRequestedCallback callback) {
  // TODO(http://fxbug.dev/75910): check the usage of FlutterIdToFuchsiaId in
  // the flutter accessibility bridge.
  if (nodes_.find(node_id) == nodes_.end()) {
    FML_LOG(ERROR) << "Attempted to send accessibility action "
                   << static_cast<int32_t>(action)
                   << " to unknown node id: " << node_id;
    callback(false);
    return;
  }

  std::optional<flutter::SemanticsAction> flutter_action =
      GetFlutterSemanticsAction(action, node_id);
  if (!flutter_action.has_value()) {
    callback(false);
    return;
  }
  dispatch_semantics_action_callback_(static_cast<int32_t>(node_id),
                                      flutter_action.value());
  callback(true);
}

// |fuchsia::accessibility::semantics::SemanticListener|
void AccessibilityBridge::HitTest(
    fuchsia::math::PointF local_point,
    fuchsia::accessibility::semantics::SemanticListener::HitTestCallback
        callback) {
  auto hit_node_id = GetHitNode(kRootNodeId, local_point.x, local_point.y);
  FML_DCHECK(hit_node_id.has_value());
  fuchsia::accessibility::semantics::Hit hit;
  // TODO(http://fxbug.dev/75910): check the usage of FlutterIdToFuchsiaId in
  // the flutter accessibility bridge.
  hit.set_node_id(hit_node_id.value_or(kRootNodeId));
  callback(std::move(hit));
}

std::optional<int32_t> AccessibilityBridge::GetHitNode(int32_t node_id,
                                                       float x,
                                                       float y) {
  auto it = nodes_.find(node_id);
  if (it == nodes_.end()) {
    FML_LOG(ERROR) << "Attempted to hit test unknown node id: " << node_id;
    return {};
  }
  auto const& node = it->second;
  if (node.data.flags &
          static_cast<int32_t>(flutter::SemanticsFlags::kIsHidden) ||  //
      !node.screen_rect.contains(x, y)) {
    return {};
  }
  for (int32_t child_id : node.data.childrenInHitTestOrder) {
    auto candidate = GetHitNode(child_id, x, y);
    if (candidate) {
      return candidate;
    }
  }

  if (IsFocusable(node.data)) {
    return node_id;
  }

  return {};
}

bool AccessibilityBridge::IsFocusable(
    const flutter::SemanticsNode& node) const {
  if (node.HasFlag(flutter::SemanticsFlags::kScopesRoute)) {
    return false;
  }

  if (node.HasFlag(flutter::SemanticsFlags::kIsFocusable)) {
    return true;
  }

  // Always consider platform views focusable.
  if (node.IsPlatformViewNode()) {
    return true;
  }

  // Always consider actionable nodes focusable.
  if (node.actions != 0) {
    return true;
  }

  // Consider text nodes focusable.
  return !node.label.empty() || !node.value.empty() || !node.hint.empty();
}

// |fuchsia::accessibility::semantics::SemanticListener|
void AccessibilityBridge::OnSemanticsModeChanged(
    bool enabled,
    OnSemanticsModeChangedCallback callback) {
  set_semantics_enabled_callback_(enabled);
}

#if !FLUTTER_RELEASE
void AccessibilityBridge::FillInspectTree(int32_t flutter_node_id,
                                          int32_t current_level,
                                          inspect::Node inspect_node,
                                          inspect::Inspector* inspector) const {
  const auto it = nodes_.find(flutter_node_id);
  if (it == nodes_.end()) {
    inspect_node.CreateString(
        "missing_child",
        "This node has a parent in the semantic tree but has no value",
        inspector);
    inspector->emplace(std::move(inspect_node));
    return;
  }
  const auto& semantic_node = it->second;
  const auto& data = semantic_node.data;

  inspect_node.CreateInt("id", data.id, inspector);

  // Even with an empty label, we still want to create the property to
  // explicetly show that it is empty.
  inspect_node.CreateString("label", data.label, inspector);
  if (!data.hint.empty()) {
    inspect_node.CreateString("hint", data.hint, inspector);
  }
  if (!data.value.empty()) {
    inspect_node.CreateString("value", data.value, inspector);
  }
  if (!data.increasedValue.empty()) {
    inspect_node.CreateString("increased_value", data.increasedValue,
                              inspector);
  }
  if (!data.decreasedValue.empty()) {
    inspect_node.CreateString("decreased_value", data.decreasedValue,
                              inspector);
  }

  if (data.textDirection) {
    inspect_node.CreateString(
        "text_direction", data.textDirection == 1 ? "RTL" : "LTR", inspector);
  }

  if (data.flags) {
    inspect_node.CreateString("flags", NodeFlagsToString(data), inspector);
  }
  if (data.actions) {
    inspect_node.CreateString("actions", NodeActionsToString(data), inspector);
  }

  inspect_node.CreateString(
      "location", NodeLocationToString(semantic_node.screen_rect), inspector);
  if (!data.childrenInTraversalOrder.empty() ||
      !data.childrenInHitTestOrder.empty()) {
    inspect_node.CreateString("children", NodeChildrenToString(data),
                              inspector);
  }

  inspect_node.CreateInt("current_level", current_level, inspector);

  for (int32_t flutter_child_id : semantic_node.data.childrenInTraversalOrder) {
    const auto inspect_name = "node_" + std::to_string(flutter_child_id);
    FillInspectTree(flutter_child_id, current_level + 1,
                    inspect_node.CreateChild(inspect_name), inspector);
  }

  inspector->emplace(std::move(inspect_node));
}
#endif  // !FLUTTER_RELEASE

}  // namespace flutter_runner
