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

#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformNodeDelegateMac.h"

#import "flutter/shell/platform/darwin/macos/framework/Headers/FlutterAppDelegate.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterTextInputSemanticsObject.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h"

#include "flutter/shell/platform/common/accessibility_bridge.h"
#include "flutter/third_party/accessibility/ax/ax_action_data.h"
#include "flutter/third_party/accessibility/ax/ax_node_position.h"
#include "flutter/third_party/accessibility/ax/platform/ax_platform_node.h"
#include "flutter/third_party/accessibility/ax/platform/ax_platform_node_base.h"
#include "flutter/third_party/accessibility/base/string_utils.h"
#include "flutter/third_party/accessibility/gfx/geometry/rect_conversions.h"
#include "flutter/third_party/accessibility/gfx/mac/coordinate_conversion.h"

namespace flutter {  // namespace

FlutterPlatformNodeDelegateMac::FlutterPlatformNodeDelegateMac(
    __weak FlutterEngine* engine,
    __weak FlutterViewController* view_controller)
    : engine_(engine), view_controller_(view_controller) {}

void FlutterPlatformNodeDelegateMac::Init(std::weak_ptr<OwnerBridge> bridge, ui::AXNode* node) {
  FlutterPlatformNodeDelegate::Init(bridge, node);
  if (GetData().IsTextField()) {
    ax_platform_node_ = new FlutterTextPlatformNode(this, view_controller_);
  } else {
    ax_platform_node_ = ui::AXPlatformNode::Create(this);
  }
  NSCAssert(ax_platform_node_, @"Failed to create platform node.");
}

FlutterPlatformNodeDelegateMac::~FlutterPlatformNodeDelegateMac() {
  // Destroy() also calls delete on itself.
  ax_platform_node_->Destroy();
}

gfx::NativeViewAccessible FlutterPlatformNodeDelegateMac::GetNativeViewAccessible() {
  NSCAssert(ax_platform_node_, @"Platform node does not exist.");
  return ax_platform_node_->GetNativeViewAccessible();
}

gfx::NativeViewAccessible FlutterPlatformNodeDelegateMac::GetParent() {
  gfx::NativeViewAccessible parent = FlutterPlatformNodeDelegate::GetParent();
  if (!parent) {
    NSCAssert(engine_, @"Flutter engine should not be deallocated");
    NSCAssert(engine_.viewController.viewLoaded, @"Flutter view must be loaded");
    return engine_.viewController.flutterView;
  }
  return parent;
}

gfx::Rect FlutterPlatformNodeDelegateMac::GetBoundsRect(
    const ui::AXCoordinateSystem coordinate_system,
    const ui::AXClippingBehavior clipping_behavior,
    ui::AXOffscreenResult* offscreen_result) const {
  gfx::Rect local_bounds = FlutterPlatformNodeDelegate::GetBoundsRect(
      coordinate_system, clipping_behavior, offscreen_result);
  gfx::RectF local_bounds_f(local_bounds);
  gfx::RectF screen_bounds = ConvertBoundsFromLocalToScreen(local_bounds_f);
  return gfx::ToEnclosingRect(ConvertBoundsFromScreenToGlobal(screen_bounds));
}

gfx::NativeViewAccessible FlutterPlatformNodeDelegateMac::GetNSWindow() {
  FlutterAppDelegate* appDelegate = (FlutterAppDelegate*)[NSApp delegate];
  return appDelegate.mainFlutterWindow;
}

std::string FlutterPlatformNodeDelegateMac::GetLiveRegionText() const {
  if (GetAXNode()->IsIgnored()) {
    return "";
  }

  std::string text = GetData().GetStringAttribute(ax::mojom::StringAttribute::kName);
  if (!text.empty()) {
    return text;
  };
  NSCAssert(engine_, @"Flutter engine should not be deallocated");
  auto bridge_ptr = engine_.accessibilityBridge.lock();
  NSCAssert(bridge_ptr, @"Accessibility bridge in flutter engine must not be null.");
  for (int32_t child : GetData().child_ids) {
    auto delegate_child = bridge_ptr->GetFlutterPlatformNodeDelegateFromID(child).lock();
    if (!delegate_child) {
      continue;
    }
    text += std::static_pointer_cast<FlutterPlatformNodeDelegateMac>(delegate_child)
                ->GetLiveRegionText();
  }
  return text;
}

gfx::RectF FlutterPlatformNodeDelegateMac::ConvertBoundsFromLocalToScreen(
    const gfx::RectF& local_bounds) const {
  // Converts to NSRect to use NSView rect conversion.
  NSRect ns_local_bounds =
      NSMakeRect(local_bounds.x(), local_bounds.y(), local_bounds.width(), local_bounds.height());
  // The macOS XY coordinates start at bottom-left and increase toward top-right,
  // which is different from the Flutter's XY coordinates that start at top-left
  // increasing to bottom-right. Therefore, this method needs to flip the y coordinate when
  // it converts the bounds from flutter coordinates to macOS coordinates.
  ns_local_bounds.origin.y = -ns_local_bounds.origin.y - ns_local_bounds.size.height;

  NSCAssert(engine_, @"Flutter engine should not be deallocated");
  NSCAssert(engine_.viewController.viewLoaded, @"Flutter view must be loaded.");
  NSRect ns_view_bounds =
      [engine_.viewController.flutterView convertRectFromBacking:ns_local_bounds];
  NSRect ns_window_bounds = [engine_.viewController.flutterView convertRect:ns_view_bounds
                                                                     toView:nil];
  NSRect ns_screen_bounds =
      [[engine_.viewController.flutterView window] convertRectToScreen:ns_window_bounds];
  gfx::RectF screen_bounds(ns_screen_bounds.origin.x, ns_screen_bounds.origin.y,
                           ns_screen_bounds.size.width, ns_screen_bounds.size.height);
  return screen_bounds;
}

gfx::RectF FlutterPlatformNodeDelegateMac::ConvertBoundsFromScreenToGlobal(
    const gfx::RectF& screen_bounds) const {
  // The VoiceOver seems to only accept bounds that are relative to primary screen.
  // Thus, this method uses [[NSScreen screens] firstObject] instead of [NSScreen mainScreen].
  NSScreen* screen = [[NSScreen screens] firstObject];
  NSRect primary_screen_bounds = [screen frame];
  // The screen is flipped against y axis.
  float flipped_y = primary_screen_bounds.size.height - screen_bounds.y() - screen_bounds.height();
  return {screen_bounds.x(), flipped_y, screen_bounds.width(), screen_bounds.height()};
}

}  // namespace flutter
