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

#include <comdef.h>
#include <comutil.h>
#include <oleacc.h>

#include <vector>

#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
#include "flutter/shell/platform/windows/flutter_platform_node_delegate_windows.h"
#include "flutter/shell/platform/windows/flutter_windows_engine.h"
#include "flutter/shell/platform/windows/flutter_windows_view.h"
#include "flutter/shell/platform/windows/testing/engine_modifier.h"
#include "flutter/shell/platform/windows/testing/mock_window_binding_handler.h"
#include "flutter/shell/platform/windows/testing/test_keyboard.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"

namespace flutter {
namespace testing {

namespace {

// A structure representing a Win32 MSAA event targeting a specified node.
struct MsaaEvent {
  std::shared_ptr<FlutterPlatformNodeDelegateWindows> node_delegate;
  DWORD event_type;
};

// Accessibility bridge delegate that captures events dispatched to the OS.
class AccessibilityBridgeWindowsSpy : public AccessibilityBridgeWindows {
 public:
  using AccessibilityBridgeWindows::OnAccessibilityEvent;

  explicit AccessibilityBridgeWindowsSpy(FlutterWindowsEngine* engine,
                                         FlutterWindowsView* view)
      : AccessibilityBridgeWindows(engine, view) {}

  void DispatchWinAccessibilityEvent(
      std::shared_ptr<FlutterPlatformNodeDelegateWindows> node_delegate,
      DWORD event_type) override {
    dispatched_events_.push_back({node_delegate, event_type});
  }

  void SetFocus(std::shared_ptr<FlutterPlatformNodeDelegateWindows>
                    node_delegate) override {
    focused_nodes_.push_back(node_delegate->GetAXNode()->id());
  }

  void ResetRecords() {
    dispatched_events_.clear();
    focused_nodes_.clear();
  }

  const std::vector<MsaaEvent>& dispatched_events() const {
    return dispatched_events_;
  }

  const std::vector<int32_t> focused_nodes() const { return focused_nodes_; }

 private:
  std::vector<MsaaEvent> dispatched_events_;
  std::vector<int32_t> focused_nodes_;
};

// A FlutterWindowsEngine whose accessibility bridge is a
// AccessibilityBridgeWindowsSpy.
class FlutterWindowsEngineSpy : public FlutterWindowsEngine {
 public:
  explicit FlutterWindowsEngineSpy(const FlutterProjectBundle& project)
      : FlutterWindowsEngine(project) {}

 protected:
  virtual std::shared_ptr<AccessibilityBridge> CreateAccessibilityBridge(
      FlutterWindowsEngine* engine,
      FlutterWindowsView* view) override {
    return std::make_shared<AccessibilityBridgeWindowsSpy>(engine, view);
  }
};

// Returns an engine instance configured with dummy project path values, and
// overridden methods for sending platform messages, so that the engine can
// respond as if the framework were connected.
std::unique_ptr<FlutterWindowsEngineSpy> GetTestEngine() {
  FlutterDesktopEngineProperties properties = {};
  properties.assets_path = L"C:\\foo\\flutter_assets";
  properties.icu_data_path = L"C:\\foo\\icudtl.dat";
  properties.aot_library_path = L"C:\\foo\\aot.so";
  FlutterProjectBundle project(properties);
  auto engine = std::make_unique<FlutterWindowsEngineSpy>(project);

  EngineModifier modifier(engine.get());
  modifier.embedder_api().UpdateSemanticsEnabled =
      [](FLUTTER_API_SYMBOL(FlutterEngine) engine, bool enabled) {
        return kSuccess;
      };

  MockEmbedderApiForKeyboard(modifier,
                             std::make_shared<MockKeyResponseController>());

  engine->Run();
  return engine;
}

// Populates the AXTree associated with the specified bridge with test data.
//
//        node0
//        /   \
//    node1    node2
//             /   \
//         node3   node4
//
// node0 and node2 are grouping nodes. node1 and node2 are static text nodes.
// node4 is a static text node with no text, and hence has the "ignored" state.
void PopulateAXTree(std::shared_ptr<AccessibilityBridge> bridge) {
  // Add node 0: root.
  FlutterSemanticsNode node0{sizeof(FlutterSemanticsNode), 0};
  std::vector<int32_t> node0_children{1, 2};
  node0.child_count = node0_children.size();
  node0.children_in_traversal_order = node0_children.data();
  node0.children_in_hit_test_order = node0_children.data();

  // Add node 1: text child of node 0.
  FlutterSemanticsNode node1{sizeof(FlutterSemanticsNode), 1};
  node1.label = "prefecture";
  node1.value = "Kyoto";

  // Add node 2: subtree child of node 0.
  FlutterSemanticsNode node2{sizeof(FlutterSemanticsNode), 2};
  std::vector<int32_t> node2_children{3, 4};
  node2.child_count = node2_children.size();
  node2.children_in_traversal_order = node2_children.data();
  node2.children_in_hit_test_order = node2_children.data();

  // Add node 3: text child of node 2.
  FlutterSemanticsNode node3{sizeof(FlutterSemanticsNode), 3};
  node3.label = "city";
  node3.value = "Uji";

  // Add node 4: text child (with no text) of node 2.
  FlutterSemanticsNode node4{sizeof(FlutterSemanticsNode), 4};

  bridge->AddFlutterSemanticsNodeUpdate(&node0);
  bridge->AddFlutterSemanticsNodeUpdate(&node1);
  bridge->AddFlutterSemanticsNodeUpdate(&node2);
  bridge->AddFlutterSemanticsNodeUpdate(&node3);
  bridge->AddFlutterSemanticsNodeUpdate(&node4);
  bridge->CommitUpdates();
}

ui::AXNode* AXNodeFromID(std::shared_ptr<AccessibilityBridge> bridge,
                         int32_t id) {
  auto node_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(id).lock();
  return node_delegate ? node_delegate->GetAXNode() : nullptr;
}

std::shared_ptr<AccessibilityBridgeWindowsSpy> GetAccessibilityBridgeSpy(
    FlutterWindowsEngine* engine) {
  FlutterWindowsEngineSpy* engine_spy =
      reinterpret_cast<FlutterWindowsEngineSpy*>(engine);
  return std::reinterpret_pointer_cast<AccessibilityBridgeWindowsSpy>(
      engine_spy->accessibility_bridge().lock());
}

void ExpectWinEventFromAXEvent(int32_t node_id,
                               ui::AXEventGenerator::Event ax_event,
                               DWORD expected_event) {
  auto window_binding_handler =
      std::make_unique<::testing::NiceMock<MockWindowBindingHandler>>();
  FlutterWindowsView view(std::move(window_binding_handler));
  view.SetEngine(GetTestEngine());
  view.OnUpdateSemanticsEnabled(true);

  auto bridge = GetAccessibilityBridgeSpy(view.GetEngine());
  PopulateAXTree(bridge);

  bridge->ResetRecords();
  bridge->OnAccessibilityEvent({AXNodeFromID(bridge, node_id),
                                {ax_event, ax::mojom::EventFrom::kNone, {}}});
  ASSERT_EQ(bridge->dispatched_events().size(), 1);
  EXPECT_EQ(bridge->dispatched_events()[0].event_type, expected_event);
}

}  // namespace

TEST(AccessibilityBridgeWindows, GetParent) {
  auto window_binding_handler =
      std::make_unique<::testing::NiceMock<MockWindowBindingHandler>>();
  FlutterWindowsView view(std::move(window_binding_handler));
  view.SetEngine(GetTestEngine());
  view.OnUpdateSemanticsEnabled(true);

  auto bridge = view.GetEngine()->accessibility_bridge().lock();
  PopulateAXTree(bridge);

  auto node0_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
  auto node1_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(1).lock();
  EXPECT_EQ(node0_delegate->GetNativeViewAccessible(),
            node1_delegate->GetParent());
}

TEST(AccessibilityBridgeWindows, GetParentOnRootRetunsNullptr) {
  auto window_binding_handler =
      std::make_unique<::testing::NiceMock<MockWindowBindingHandler>>();
  FlutterWindowsView view(std::move(window_binding_handler));
  view.SetEngine(GetTestEngine());
  view.OnUpdateSemanticsEnabled(true);

  auto bridge = view.GetEngine()->accessibility_bridge().lock();
  PopulateAXTree(bridge);

  auto node0_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
  ASSERT_TRUE(node0_delegate->GetParent() == nullptr);
}

TEST(AccessibilityBridgeWindows, DispatchAccessibilityAction) {
  auto window_binding_handler =
      std::make_unique<::testing::NiceMock<MockWindowBindingHandler>>();
  FlutterWindowsView view(std::move(window_binding_handler));
  view.SetEngine(GetTestEngine());
  view.OnUpdateSemanticsEnabled(true);

  auto bridge = view.GetEngine()->accessibility_bridge().lock();
  PopulateAXTree(bridge);

  FlutterSemanticsAction actual_action = kFlutterSemanticsActionTap;
  EngineModifier modifier(view.GetEngine());
  modifier.embedder_api().DispatchSemanticsAction = MOCK_ENGINE_PROC(
      DispatchSemanticsAction,
      ([&actual_action](FLUTTER_API_SYMBOL(FlutterEngine) engine, uint64_t id,
                        FlutterSemanticsAction action, const uint8_t* data,
                        size_t data_length) {
        actual_action = action;
        return kSuccess;
      }));

  AccessibilityBridgeWindows delegate(view.GetEngine(), &view);
  delegate.DispatchAccessibilityAction(1, kFlutterSemanticsActionCopy, {});
  EXPECT_EQ(actual_action, kFlutterSemanticsActionCopy);
}

TEST(AccessibilityBridgeWindows, OnAccessibilityEventAlert) {
  ExpectWinEventFromAXEvent(0, ui::AXEventGenerator::Event::ALERT,
                            EVENT_SYSTEM_ALERT);
}

TEST(AccessibilityBridgeWindows, OnAccessibilityEventChildrenChanged) {
  ExpectWinEventFromAXEvent(0, ui::AXEventGenerator::Event::CHILDREN_CHANGED,
                            EVENT_OBJECT_REORDER);
}

TEST(AccessibilityBridgeWindows, OnAccessibilityEventFocusChanged) {
  auto window_binding_handler =
      std::make_unique<::testing::NiceMock<MockWindowBindingHandler>>();
  FlutterWindowsView view(std::move(window_binding_handler));
  view.SetEngine(GetTestEngine());
  view.OnUpdateSemanticsEnabled(true);

  auto bridge = GetAccessibilityBridgeSpy(view.GetEngine());
  PopulateAXTree(bridge);

  bridge->ResetRecords();
  bridge->OnAccessibilityEvent({AXNodeFromID(bridge, 1),
                                {ui::AXEventGenerator::Event::FOCUS_CHANGED,
                                 ax::mojom::EventFrom::kNone,
                                 {}}});
  ASSERT_EQ(bridge->dispatched_events().size(), 1);
  EXPECT_EQ(bridge->dispatched_events()[0].event_type, EVENT_OBJECT_FOCUS);

  ASSERT_EQ(bridge->focused_nodes().size(), 1);
  EXPECT_EQ(bridge->focused_nodes()[0], 1);
}

TEST(AccessibilityBridgeWindows, OnAccessibilityEventIgnoredChanged) {
  // Static test nodes with no text, hint, or scrollability are ignored.
  ExpectWinEventFromAXEvent(4, ui::AXEventGenerator::Event::IGNORED_CHANGED,
                            EVENT_OBJECT_HIDE);
}

TEST(AccessibilityBridgeWindows, OnAccessibilityImageAnnotationChanged) {
  ExpectWinEventFromAXEvent(
      1, ui::AXEventGenerator::Event::IMAGE_ANNOTATION_CHANGED,
      EVENT_OBJECT_NAMECHANGE);
}

TEST(AccessibilityBridgeWindows, OnAccessibilityLiveRegionChanged) {
  ExpectWinEventFromAXEvent(1, ui::AXEventGenerator::Event::LIVE_REGION_CHANGED,
                            EVENT_OBJECT_LIVEREGIONCHANGED);
}

TEST(AccessibilityBridgeWindows, OnAccessibilityNameChanged) {
  ExpectWinEventFromAXEvent(1, ui::AXEventGenerator::Event::NAME_CHANGED,
                            EVENT_OBJECT_NAMECHANGE);
}

TEST(AccessibilityBridgeWindows, OnAccessibilityHScrollPosChanged) {
  ExpectWinEventFromAXEvent(
      1, ui::AXEventGenerator::Event::SCROLL_HORIZONTAL_POSITION_CHANGED,
      EVENT_SYSTEM_SCROLLINGEND);
}

TEST(AccessibilityBridgeWindows, OnAccessibilityVScrollPosChanged) {
  ExpectWinEventFromAXEvent(
      1, ui::AXEventGenerator::Event::SCROLL_VERTICAL_POSITION_CHANGED,
      EVENT_SYSTEM_SCROLLINGEND);
}

TEST(AccessibilityBridgeWindows, OnAccessibilitySelectedChanged) {
  ExpectWinEventFromAXEvent(1, ui::AXEventGenerator::Event::SELECTED_CHANGED,
                            EVENT_OBJECT_VALUECHANGE);
}

TEST(AccessibilityBridgeWindows, OnAccessibilitySelectedChildrenChanged) {
  ExpectWinEventFromAXEvent(
      2, ui::AXEventGenerator::Event::SELECTED_CHILDREN_CHANGED,
      EVENT_OBJECT_SELECTIONWITHIN);
}

TEST(AccessibilityBridgeWindows, OnAccessibilitySubtreeCreated) {
  ExpectWinEventFromAXEvent(0, ui::AXEventGenerator::Event::SUBTREE_CREATED,
                            EVENT_OBJECT_SHOW);
}

TEST(AccessibilityBridgeWindows, OnAccessibilityValueChanged) {
  ExpectWinEventFromAXEvent(1, ui::AXEventGenerator::Event::VALUE_CHANGED,
                            EVENT_OBJECT_VALUECHANGE);
}

TEST(AccessibilityBridgeWindows, OnAccessibilityStateChanged) {
  ExpectWinEventFromAXEvent(
      1, ui::AXEventGenerator::Event::WIN_IACCESSIBLE_STATE_CHANGED,
      EVENT_OBJECT_STATECHANGE);
}

}  // namespace testing
}  // namespace flutter
