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

// Allow access to fml::MessageLoop::GetCurrent() in order to flush platform
// thread tasks.
#define FML_USED_ON_EMBEDDER

#include <functional>

#include "flutter/fml/macros.h"
#include "flutter/fml/message_loop.h"
#include "flutter/fml/synchronization/waitable_event.h"
#include "flutter/lib/ui/semantics/semantics_node.h"
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/embedder/tests/embedder_config_builder.h"
#include "flutter/testing/testing.h"

// CREATE_NATIVE_ENTRY is leaky by design
// NOLINTBEGIN(clang-analyzer-core.StackAddressEscape)

namespace flutter {
namespace testing {

using Embedder11yTest = testing::EmbedderTest;

TEST_F(Embedder11yTest, A11yTreeIsConsistent) {
  auto& context = GetEmbedderContext(EmbedderTestContextType::kOpenGLContext);

  fml::AutoResetWaitableEvent latch;

  // Called by the Dart text fixture on the UI thread to signal that the C++
  // unittest should resume.
  context.AddNativeCallback(
      "SignalNativeTest", CREATE_NATIVE_ENTRY(([&latch](Dart_NativeArguments) {
        latch.Signal();
      })));

  // Called by test fixture on UI thread to pass data back to this test.
  NativeEntry notify_semantics_enabled_callback;
  context.AddNativeCallback(
      "NotifySemanticsEnabled",
      CREATE_NATIVE_ENTRY(
          ([&notify_semantics_enabled_callback](Dart_NativeArguments args) {
            ASSERT_NE(notify_semantics_enabled_callback, nullptr);
            notify_semantics_enabled_callback(args);
          })));

  NativeEntry notify_accessibility_features_callback;
  context.AddNativeCallback(
      "NotifyAccessibilityFeatures",
      CREATE_NATIVE_ENTRY((
          [&notify_accessibility_features_callback](Dart_NativeArguments args) {
            ASSERT_NE(notify_accessibility_features_callback, nullptr);
            notify_accessibility_features_callback(args);
          })));

  NativeEntry notify_semantics_action_callback;
  context.AddNativeCallback(
      "NotifySemanticsAction",
      CREATE_NATIVE_ENTRY(
          ([&notify_semantics_action_callback](Dart_NativeArguments args) {
            ASSERT_NE(notify_semantics_action_callback, nullptr);
            notify_semantics_action_callback(args);
          })));

  EmbedderConfigBuilder builder(context);
  builder.SetSoftwareRendererConfig();
  builder.SetDartEntrypoint("a11y_main");

  auto engine = builder.LaunchEngine();
  ASSERT_TRUE(engine.is_valid());

  // Wait for initial NotifySemanticsEnabled(false).
  notify_semantics_enabled_callback = [&](Dart_NativeArguments args) {
    bool enabled = true;
    auto handle = Dart_GetNativeBooleanArgument(args, 0, &enabled);
    ASSERT_FALSE(Dart_IsError(handle));
    ASSERT_FALSE(enabled);
    latch.Signal();
  };
  latch.Wait();

  // Prepare to NotifyAccessibilityFeatures call
  fml::AutoResetWaitableEvent notify_features_latch;
  notify_accessibility_features_callback = [&](Dart_NativeArguments args) {
    bool enabled = true;
    auto handle = Dart_GetNativeBooleanArgument(args, 0, &enabled);
    ASSERT_FALSE(Dart_IsError(handle));
    ASSERT_FALSE(enabled);
    notify_features_latch.Signal();
  };

  // Enable semantics. Wait for NotifySemanticsEnabled(true).
  notify_semantics_enabled_callback = [&](Dart_NativeArguments args) {
    bool enabled = false;
    auto handle = Dart_GetNativeBooleanArgument(args, 0, &enabled);
    ASSERT_FALSE(Dart_IsError(handle));
    ASSERT_TRUE(enabled);
    latch.Signal();
  };
  auto result = FlutterEngineUpdateSemanticsEnabled(engine.get(), true);
  ASSERT_EQ(result, FlutterEngineResult::kSuccess);
  latch.Wait();

  // Wait for initial accessibility features (reduce_motion == false)
  notify_features_latch.Wait();

  // Set accessibility features: (reduce_motion == true)
  notify_accessibility_features_callback = [&](Dart_NativeArguments args) {
    bool enabled = false;
    auto handle = Dart_GetNativeBooleanArgument(args, 0, &enabled);
    ASSERT_FALSE(Dart_IsError(handle));
    ASSERT_TRUE(enabled);
    latch.Signal();
  };
  result = FlutterEngineUpdateAccessibilityFeatures(
      engine.get(), kFlutterAccessibilityFeatureReduceMotion);
  ASSERT_EQ(result, FlutterEngineResult::kSuccess);
  latch.Wait();

  // Wait for UpdateSemantics callback on platform (current) thread.
  int node_count = 0;
  int node_batch_end_count = 0;
  context.SetSemanticsNodeCallback(
      [&node_count, &node_batch_end_count](const FlutterSemanticsNode* node) {
        if (node->id == kFlutterSemanticsNodeIdBatchEnd) {
          ++node_batch_end_count;
        } else {
          ++node_count;
          ASSERT_EQ(1.0, node->transform.scaleX);
          ASSERT_EQ(2.0, node->transform.skewX);
          ASSERT_EQ(3.0, node->transform.transX);
          ASSERT_EQ(4.0, node->transform.skewY);
          ASSERT_EQ(5.0, node->transform.scaleY);
          ASSERT_EQ(6.0, node->transform.transY);
          ASSERT_EQ(7.0, node->transform.pers0);
          ASSERT_EQ(8.0, node->transform.pers1);
          ASSERT_EQ(9.0, node->transform.pers2);

          if (node->id == 128) {
            ASSERT_EQ(0x3f3, node->platform_view_id);
          } else {
            ASSERT_EQ(0, node->platform_view_id);
          }
        }
      });

  int action_count = 0;
  int action_batch_end_count = 0;
  context.SetSemanticsCustomActionCallback(
      [&action_count,
       &action_batch_end_count](const FlutterSemanticsCustomAction* action) {
        if (action->id == kFlutterSemanticsCustomActionIdBatchEnd) {
          ++action_batch_end_count;
        } else {
          ++action_count;
        }
      });

  latch.Wait();
  fml::MessageLoop::GetCurrent().RunExpiredTasksNow();
  ASSERT_EQ(4, node_count);
  ASSERT_EQ(1, node_batch_end_count);
  ASSERT_EQ(1, action_count);
  ASSERT_EQ(1, action_batch_end_count);

  // Dispatch a tap to semantics node 42. Wait for NotifySemanticsAction.
  notify_semantics_action_callback = [&](Dart_NativeArguments args) {
    int64_t node_id = 0;
    Dart_GetNativeIntegerArgument(args, 0, &node_id);
    ASSERT_EQ(42, node_id);

    int64_t action_id;
    auto handle = Dart_GetNativeIntegerArgument(args, 1, &action_id);
    ASSERT_FALSE(Dart_IsError(handle));
    ASSERT_EQ(static_cast<int32_t>(flutter::SemanticsAction::kTap), action_id);

    Dart_Handle semantic_args = Dart_GetNativeArgument(args, 2);
    int64_t data;
    Dart_Handle dart_int = Dart_ListGetAt(semantic_args, 0);
    Dart_IntegerToInt64(dart_int, &data);
    ASSERT_EQ(2, data);

    dart_int = Dart_ListGetAt(semantic_args, 1);
    Dart_IntegerToInt64(dart_int, &data);
    ASSERT_EQ(1, data);
    latch.Signal();
  };
  std::vector<uint8_t> bytes({2, 1});
  result = FlutterEngineDispatchSemanticsAction(
      engine.get(), 42, kFlutterSemanticsActionTap, &bytes[0], bytes.size());
  ASSERT_EQ(result, FlutterEngineResult::kSuccess);
  latch.Wait();

  // Disable semantics. Wait for NotifySemanticsEnabled(false).
  notify_semantics_enabled_callback = [&](Dart_NativeArguments args) {
    bool enabled = true;
    Dart_GetNativeBooleanArgument(args, 0, &enabled);
    ASSERT_FALSE(enabled);
    latch.Signal();
  };
  result = FlutterEngineUpdateSemanticsEnabled(engine.get(), false);
  ASSERT_EQ(result, FlutterEngineResult::kSuccess);
  latch.Wait();
}

}  // namespace testing
}  // namespace flutter

// NOLINTEND(clang-analyzer-core.StackAddressEscape)
