// 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_platform_node_delegate.h"

#include "flutter/third_party/accessibility/ax/ax_action_data.h"
#include "flutter/third_party/accessibility/gfx/geometry/rect_conversions.h"

namespace flutter {

FlutterPlatformNodeDelegate::FlutterPlatformNodeDelegate() = default;

FlutterPlatformNodeDelegate::~FlutterPlatformNodeDelegate() = default;

void FlutterPlatformNodeDelegate::Init(std::weak_ptr<OwnerBridge> bridge,
                                       ui::AXNode* node) {
  bridge_ = bridge;
  ax_node_ = node;
}

ui::AXNode* FlutterPlatformNodeDelegate::GetAXNode() const {
  return ax_node_;
}

bool FlutterPlatformNodeDelegate::AccessibilityPerformAction(
    const ui::AXActionData& data) {
  AccessibilityNodeId target = ax_node_->id();
  auto bridge_ptr = bridge_.lock();
  BASE_DCHECK(bridge_ptr);
  switch (data.action) {
    case ax::mojom::Action::kDoDefault:
      bridge_ptr->DispatchAccessibilityAction(
          target, FlutterSemanticsAction::kFlutterSemanticsActionTap, {});
      return true;
    case ax::mojom::Action::kFocus:
      bridge_ptr->SetLastFocusedId(target);
      bridge_ptr->DispatchAccessibilityAction(
          target,
          FlutterSemanticsAction::
              kFlutterSemanticsActionDidGainAccessibilityFocus,
          {});
      return true;
    case ax::mojom::Action::kScrollToMakeVisible:
      bridge_ptr->DispatchAccessibilityAction(
          target, FlutterSemanticsAction::kFlutterSemanticsActionShowOnScreen,
          {});
      return true;
    // TODO(chunhtai): support more actions.
    default:
      return false;
  }
  return false;
}

const ui::AXNodeData& FlutterPlatformNodeDelegate::GetData() const {
  return ax_node_->data();
}

gfx::NativeViewAccessible FlutterPlatformNodeDelegate::GetParent() {
  if (!ax_node_->parent()) {
    return nullptr;
  }
  auto bridge_ptr = bridge_.lock();
  BASE_DCHECK(bridge_ptr);
  return bridge_ptr->GetNativeAccessibleFromId(ax_node_->parent()->id());
}

gfx::NativeViewAccessible FlutterPlatformNodeDelegate::GetFocus() {
  auto bridge_ptr = bridge_.lock();
  BASE_DCHECK(bridge_ptr);
  AccessibilityNodeId last_focused = bridge_ptr->GetLastFocusedId();
  if (last_focused == ui::AXNode::kInvalidAXID) {
    return nullptr;
  }
  return bridge_ptr->GetNativeAccessibleFromId(last_focused);
}

int FlutterPlatformNodeDelegate::GetChildCount() const {
  return static_cast<int>(ax_node_->GetUnignoredChildCount());
}

gfx::NativeViewAccessible FlutterPlatformNodeDelegate::ChildAtIndex(int index) {
  auto bridge_ptr = bridge_.lock();
  BASE_DCHECK(bridge_ptr);
  AccessibilityNodeId child = ax_node_->GetUnignoredChildAtIndex(index)->id();
  return bridge_ptr->GetNativeAccessibleFromId(child);
}

gfx::Rect FlutterPlatformNodeDelegate::GetBoundsRect(
    const ui::AXCoordinateSystem coordinate_system,
    const ui::AXClippingBehavior clipping_behavior,
    ui::AXOffscreenResult* offscreen_result) const {
  auto bridge_ptr = bridge_.lock();
  BASE_DCHECK(bridge_ptr);
  // TODO(chunhtai): We need to apply screen dpr in here.
  // https://github.com/flutter/flutter/issues/74283
  const bool clip_bounds =
      clipping_behavior == ui::AXClippingBehavior::kClipped;
  bool offscreen = false;
  gfx::RectF bounds =
      bridge_ptr->RelativeToGlobalBounds(ax_node_, offscreen, clip_bounds);
  if (offscreen_result != nullptr) {
    *offscreen_result = offscreen ? ui::AXOffscreenResult::kOffscreen
                                  : ui::AXOffscreenResult::kOnscreen;
  }
  return gfx::ToEnclosingRect(bounds);
}

std::weak_ptr<FlutterPlatformNodeDelegate::OwnerBridge>
FlutterPlatformNodeDelegate::GetOwnerBridge() const {
  return bridge_;
}

}  // namespace flutter
