// Copyright 2014 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 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';

import '../widgets/semantics_tester.dart';
import 'feedback_tester.dart';

void main () {
  const Duration kWaitDuration = Duration(seconds: 1);

  late FeedbackTester feedback;

  setUp(() {
    feedback = FeedbackTester();
  });

  tearDown(() {
    feedback.dispose();
  });

  group('Feedback on Android', () {
    late List<Map<String, Object>> semanticEvents;

    setUp(() {
      semanticEvents = <Map<String, Object>>[];
      TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, (dynamic message) async {
        final Map<dynamic, dynamic> typedMessage = message as Map<dynamic, dynamic>;
        semanticEvents.add(typedMessage.cast<String, Object>());
      });
    });

    tearDown(() {
      TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, null);
    });

    testWidgets('forTap', (WidgetTester tester) async {
      final SemanticsTester semanticsTester = SemanticsTester(tester);

      await tester.pumpWidget(TestWidget(
        tapHandler: (BuildContext context) {
          return () => Feedback.forTap(context);
        },
      ));
      await tester.pumpAndSettle(kWaitDuration);
      expect(feedback.hapticCount, 0);
      expect(feedback.clickSoundCount, 0);
      expect(semanticEvents, isEmpty);

      await tester.tap(find.text('X'));
      await tester.pumpAndSettle(kWaitDuration);
      final RenderObject object = tester.firstRenderObject(find.byType(GestureDetector));

      expect(feedback.hapticCount, 0);
      expect(feedback.clickSoundCount, 1);
      expect(semanticEvents.single, <String, dynamic>{
        'type': 'tap',
        'nodeId': object.debugSemantics!.id,
        'data': <String, dynamic>{},
      });
      expect(object.debugSemantics!.getSemanticsData().hasAction(SemanticsAction.tap), true);

      semanticsTester.dispose();
    });

    testWidgets('forTap Wrapper', (WidgetTester tester) async {
      final SemanticsTester semanticsTester = SemanticsTester(tester);

      int callbackCount = 0;
      void callback() {
        callbackCount++;
      }

      await tester.pumpWidget(TestWidget(
        tapHandler: (BuildContext context) {
          return Feedback.wrapForTap(callback, context)!;
        },
      ));
      await tester.pumpAndSettle(kWaitDuration);
      expect(feedback.hapticCount, 0);
      expect(feedback.clickSoundCount, 0);
      expect(callbackCount, 0);

      await tester.tap(find.text('X'));
      await tester.pumpAndSettle(kWaitDuration);
      final RenderObject object = tester.firstRenderObject(find.byType(GestureDetector));

      expect(feedback.hapticCount, 0);
      expect(feedback.clickSoundCount, 1);
      expect(callbackCount, 1);
      expect(semanticEvents.single, <String, dynamic>{
        'type': 'tap',
        'nodeId': object.debugSemantics!.id,
        'data': <String, dynamic>{},
      });
      expect(object.debugSemantics!.getSemanticsData().hasAction(SemanticsAction.tap), true);

      semanticsTester.dispose();
    });

    testWidgets('forLongPress', (WidgetTester tester) async {
      final SemanticsTester semanticsTester = SemanticsTester(tester);

      await tester.pumpWidget(TestWidget(
        longPressHandler: (BuildContext context) {
          return () => Feedback.forLongPress(context);
        },
      ));
      await tester.pumpAndSettle(kWaitDuration);
      expect(feedback.hapticCount, 0);
      expect(feedback.clickSoundCount, 0);

      await tester.longPress(find.text('X'));
      await tester.pumpAndSettle(kWaitDuration);
      final RenderObject object = tester.firstRenderObject(find.byType(GestureDetector));

      expect(feedback.hapticCount, 1);
      expect(feedback.clickSoundCount, 0);
      expect(semanticEvents.single, <String, dynamic>{
        'type': 'longPress',
        'nodeId': object.debugSemantics!.id,
        'data': <String, dynamic>{},
      });
      expect(object.debugSemantics!.getSemanticsData().hasAction(SemanticsAction.longPress), true);

      semanticsTester.dispose();
    });

    testWidgets('forLongPress Wrapper', (WidgetTester tester) async {
      final SemanticsTester semanticsTester = SemanticsTester(tester);
      int callbackCount = 0;
      void callback() {
        callbackCount++;
      }

      await tester.pumpWidget(TestWidget(
        longPressHandler: (BuildContext context) {
          return Feedback.wrapForLongPress(callback, context)!;
        },
      ));
      await tester.pumpAndSettle(kWaitDuration);
      final RenderObject object = tester.firstRenderObject(find.byType(GestureDetector));

      expect(feedback.hapticCount, 0);
      expect(feedback.clickSoundCount, 0);
      expect(callbackCount, 0);

      await tester.longPress(find.text('X'));
      await tester.pumpAndSettle(kWaitDuration);
      expect(feedback.hapticCount, 1);
      expect(feedback.clickSoundCount, 0);
      expect(callbackCount, 1);
      expect(semanticEvents.single, <String, dynamic>{
        'type': 'longPress',
        'nodeId': object.debugSemantics!.id,
        'data': <String, dynamic>{},
      });
      expect(object.debugSemantics!.getSemanticsData().hasAction(SemanticsAction.longPress), true);

      semanticsTester.dispose();
    });

  });

  group('Feedback on iOS', () {
    testWidgets('forTap', (WidgetTester tester) async {
      await tester.pumpWidget(Theme(
        data: ThemeData(platform: TargetPlatform.iOS),
        child: TestWidget(
          tapHandler: (BuildContext context) {
            return () => Feedback.forTap(context);
          },
        ),
      ));

      await tester.tap(find.text('X'));
      await tester.pumpAndSettle(kWaitDuration);
      expect(feedback.hapticCount, 0);
      expect(feedback.clickSoundCount, 0);
    });

    testWidgets('forLongPress', (WidgetTester tester) async {
      await tester.pumpWidget(Theme(
        data: ThemeData(platform: TargetPlatform.iOS),
        child: TestWidget(
          longPressHandler: (BuildContext context) {
            return () => Feedback.forLongPress(context);
          },
        ),
      ));

      await tester.longPress(find.text('X'));
      await tester.pumpAndSettle(kWaitDuration);
      expect(feedback.hapticCount, 0);
      expect(feedback.clickSoundCount, 0);
    });
  });
}

class TestWidget extends StatelessWidget {
  const TestWidget({
    super.key,
    this.tapHandler = nullHandler,
    this.longPressHandler = nullHandler,
  });

  final HandlerCreator tapHandler;
  final HandlerCreator longPressHandler;

  static VoidCallback? nullHandler(BuildContext context) => null;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
        onTap: tapHandler(context),
        onLongPress: longPressHandler(context),
        child: const Text('X', textDirection: TextDirection.ltr),
    );
  }
}

typedef HandlerCreator = VoidCallback? Function(BuildContext context);
