// 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 'dart:ui' as ui;

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  testWidgets('HardwareKeyboard records pressed keys and enabled locks', (WidgetTester tester) async {
    await simulateKeyDownEvent(LogicalKeyboardKey.numLock, platform: 'windows');
    expect(HardwareKeyboard.instance.physicalKeysPressed,
      equals(<PhysicalKeyboardKey>{PhysicalKeyboardKey.numLock}));
    expect(HardwareKeyboard.instance.logicalKeysPressed,
      equals(<LogicalKeyboardKey>{LogicalKeyboardKey.numLock}));
    expect(HardwareKeyboard.instance.lockModesEnabled,
      equals(<KeyboardLockMode>{KeyboardLockMode.numLock}));

    await simulateKeyDownEvent(LogicalKeyboardKey.numpad1, platform: 'windows');
    expect(HardwareKeyboard.instance.physicalKeysPressed,
      equals(<PhysicalKeyboardKey>{PhysicalKeyboardKey.numLock, PhysicalKeyboardKey.numpad1}));
    expect(HardwareKeyboard.instance.logicalKeysPressed,
      equals(<LogicalKeyboardKey>{LogicalKeyboardKey.numLock, LogicalKeyboardKey.numpad1}));
    expect(HardwareKeyboard.instance.lockModesEnabled,
      equals(<KeyboardLockMode>{KeyboardLockMode.numLock}));

    await simulateKeyRepeatEvent(LogicalKeyboardKey.numpad1, platform: 'windows');
    expect(HardwareKeyboard.instance.physicalKeysPressed,
      equals(<PhysicalKeyboardKey>{PhysicalKeyboardKey.numLock, PhysicalKeyboardKey.numpad1}));
    expect(HardwareKeyboard.instance.logicalKeysPressed,
      equals(<LogicalKeyboardKey>{LogicalKeyboardKey.numLock, LogicalKeyboardKey.numpad1}));
    expect(HardwareKeyboard.instance.lockModesEnabled,
      equals(<KeyboardLockMode>{KeyboardLockMode.numLock}));

    await simulateKeyUpEvent(LogicalKeyboardKey.numLock);
    expect(HardwareKeyboard.instance.physicalKeysPressed,
      equals(<PhysicalKeyboardKey>{PhysicalKeyboardKey.numpad1}));
    expect(HardwareKeyboard.instance.logicalKeysPressed,
      equals(<LogicalKeyboardKey>{LogicalKeyboardKey.numpad1}));
    expect(HardwareKeyboard.instance.lockModesEnabled,
      equals(<KeyboardLockMode>{KeyboardLockMode.numLock}));

    await simulateKeyDownEvent(LogicalKeyboardKey.numLock, platform: 'windows');
    expect(HardwareKeyboard.instance.physicalKeysPressed,
      equals(<PhysicalKeyboardKey>{PhysicalKeyboardKey.numLock, PhysicalKeyboardKey.numpad1}));
    expect(HardwareKeyboard.instance.logicalKeysPressed,
      equals(<LogicalKeyboardKey>{LogicalKeyboardKey.numLock, LogicalKeyboardKey.numpad1}));
    expect(HardwareKeyboard.instance.lockModesEnabled,
      equals(<KeyboardLockMode>{}));

    await simulateKeyUpEvent(LogicalKeyboardKey.numpad1, platform: 'windows');
    expect(HardwareKeyboard.instance.physicalKeysPressed,
      equals(<PhysicalKeyboardKey>{PhysicalKeyboardKey.numLock}));
    expect(HardwareKeyboard.instance.logicalKeysPressed,
      equals(<LogicalKeyboardKey>{LogicalKeyboardKey.numLock}));
    expect(HardwareKeyboard.instance.lockModesEnabled,
      equals(<KeyboardLockMode>{}));

    await simulateKeyUpEvent(LogicalKeyboardKey.numLock, platform: 'windows');
    expect(HardwareKeyboard.instance.physicalKeysPressed,
      equals(<PhysicalKeyboardKey>{}));
    expect(HardwareKeyboard.instance.logicalKeysPressed,
      equals(<LogicalKeyboardKey>{}));
    expect(HardwareKeyboard.instance.lockModesEnabled,
      equals(<KeyboardLockMode>{}));
  }, variant: KeySimulatorTransitModeVariant.keyDataThenRawKeyData());

  testWidgets('KeyEvent can tell which keys are pressed', (WidgetTester tester) async {
    await tester.pumpWidget(const Focus(autofocus: true, child: SizedBox()));
    await tester.pump();

    await simulateKeyDownEvent(LogicalKeyboardKey.numLock, platform: 'windows');

    expect(HardwareKeyboard.instance.isPhysicalKeyPressed(PhysicalKeyboardKey.numLock), isTrue);
    expect(HardwareKeyboard.instance.isLogicalKeyPressed(LogicalKeyboardKey.numLock), isTrue);

    await simulateKeyDownEvent(LogicalKeyboardKey.numpad1, platform: 'windows');
    expect(HardwareKeyboard.instance.isPhysicalKeyPressed(PhysicalKeyboardKey.numpad1), isTrue);
    expect(HardwareKeyboard.instance.isLogicalKeyPressed(LogicalKeyboardKey.numpad1), isTrue);

    await simulateKeyRepeatEvent(LogicalKeyboardKey.numpad1, platform: 'windows');
    expect(HardwareKeyboard.instance.isPhysicalKeyPressed(PhysicalKeyboardKey.numpad1), isTrue);
    expect(HardwareKeyboard.instance.isLogicalKeyPressed(LogicalKeyboardKey.numpad1), isTrue);

    await simulateKeyUpEvent(LogicalKeyboardKey.numLock);
    expect(HardwareKeyboard.instance.isPhysicalKeyPressed(PhysicalKeyboardKey.numpad1), isTrue);
    expect(HardwareKeyboard.instance.isLogicalKeyPressed(LogicalKeyboardKey.numpad1), isTrue);

    await simulateKeyDownEvent(LogicalKeyboardKey.numLock, platform: 'windows');
    expect(HardwareKeyboard.instance.isPhysicalKeyPressed(PhysicalKeyboardKey.numLock), isTrue);
    expect(HardwareKeyboard.instance.isLogicalKeyPressed(LogicalKeyboardKey.numLock), isTrue);

    await simulateKeyUpEvent(LogicalKeyboardKey.numpad1, platform: 'windows');
    expect(HardwareKeyboard.instance.isPhysicalKeyPressed(PhysicalKeyboardKey.numpad1), isFalse);
    expect(HardwareKeyboard.instance.isLogicalKeyPressed(LogicalKeyboardKey.numpad1), isFalse);

    await simulateKeyUpEvent(LogicalKeyboardKey.numLock, platform: 'windows');
    expect(HardwareKeyboard.instance.isPhysicalKeyPressed(PhysicalKeyboardKey.numLock), isFalse);
    expect(HardwareKeyboard.instance.isLogicalKeyPressed(LogicalKeyboardKey.numLock), isFalse);
  }, variant: KeySimulatorTransitModeVariant.keyDataThenRawKeyData());

  testWidgets('KeyboardManager synthesizes modifier keys in rawKeyData mode', (WidgetTester tester) async {
    final List<KeyEvent> events = <KeyEvent>[];
    HardwareKeyboard.instance.addHandler((KeyEvent event) {
      events.add(event);
      return false;
    });
    // While ShiftLeft is held (the event of which was skipped), press keyA.
    final Map<String, dynamic> rawMessage = kIsWeb ? (
      KeyEventSimulator.getKeyData(
        LogicalKeyboardKey.keyA,
        platform: 'web',
      )..['metaState'] = RawKeyEventDataWeb.modifierShift
    ) : (
      KeyEventSimulator.getKeyData(
        LogicalKeyboardKey.keyA,
        platform: 'android',
      )..['metaState'] = RawKeyEventDataAndroid.modifierLeftShift | RawKeyEventDataAndroid.modifierShift
    );
    tester.binding.keyEventManager.handleRawKeyMessage(rawMessage);
    expect(events, hasLength(2));
    expect(events[0].physicalKey, PhysicalKeyboardKey.shiftLeft);
    expect(events[0].logicalKey, LogicalKeyboardKey.shiftLeft);
    expect(events[0].synthesized, true);
    expect(events[1].physicalKey, PhysicalKeyboardKey.keyA);
    expect(events[1].logicalKey, LogicalKeyboardKey.keyA);
    expect(events[1].synthesized, false);
  });

  testWidgets('Dispatch events to all handlers', (WidgetTester tester) async {
    final FocusNode focusNode = FocusNode();
    addTearDown(focusNode.dispose);
    final List<int> logs = <int>[];

    await tester.pumpWidget(
      KeyboardListener(
        autofocus: true,
        focusNode: focusNode,
        child: Container(),
        onKeyEvent: (KeyEvent event) {
          logs.add(1);
        },
      ),
    );

    // Only the Service binding handler.

    expect(await simulateKeyDownEvent(LogicalKeyboardKey.keyA),
      false);
    expect(logs, <int>[1]);
    logs.clear();

    // Add a handler.

    bool handler2Result = false;
    bool handler2(KeyEvent event) {
      logs.add(2);
      return handler2Result;
    }
    HardwareKeyboard.instance.addHandler(handler2);

    expect(await simulateKeyUpEvent(LogicalKeyboardKey.keyA),
      false);
    expect(logs, <int>[2, 1]);
    logs.clear();

    handler2Result = true;

    expect(await simulateKeyDownEvent(LogicalKeyboardKey.keyA),
      true);
    expect(logs, <int>[2, 1]);
    logs.clear();

    // Add another handler.

    handler2Result = false;
    bool handler3Result = false;
    bool handler3(KeyEvent event) {
      logs.add(3);
      return handler3Result;
    }
    HardwareKeyboard.instance.addHandler(handler3);

    expect(await simulateKeyUpEvent(LogicalKeyboardKey.keyA),
      false);
    expect(logs, <int>[2, 3, 1]);
    logs.clear();

    handler2Result = true;

    expect(await simulateKeyDownEvent(LogicalKeyboardKey.keyA),
      true);
    expect(logs, <int>[2, 3, 1]);
    logs.clear();

    handler3Result = true;

    expect(await simulateKeyUpEvent(LogicalKeyboardKey.keyA),
      true);
    expect(logs, <int>[2, 3, 1]);
    logs.clear();

    // Add handler2 again.

    HardwareKeyboard.instance.addHandler(handler2);

    handler3Result = false;
    handler2Result = false;
    expect(await simulateKeyDownEvent(LogicalKeyboardKey.keyA),
      false);
    expect(logs, <int>[2, 3, 2, 1]);
    logs.clear();

    handler2Result = true;
    expect(await simulateKeyUpEvent(LogicalKeyboardKey.keyA),
      true);
    expect(logs, <int>[2, 3, 2, 1]);
    logs.clear();

    // Remove handler2 once.

    HardwareKeyboard.instance.removeHandler(handler2);
    expect(await simulateKeyDownEvent(LogicalKeyboardKey.keyA),
      true);
    expect(logs, <int>[3, 2, 1]);
    logs.clear();
  }, variant: KeySimulatorTransitModeVariant.all());

  // Regression test for https://github.com/flutter/flutter/issues/99196 .
  //
  // In rawKeyData mode, if a key down event is dispatched but immediately
  // synthesized to be released, the old logic would trigger a Null check
  // _CastError on _hardwareKeyboard.lookUpLayout(key). The original scenario
  // that this is triggered on Android is unknown. Here we make up a scenario
  // where a ShiftLeft key down is dispatched but the modifier bit is not set.
  testWidgets('Correctly convert down events that are synthesized released', (WidgetTester tester) async {
    final FocusNode focusNode = FocusNode();
    addTearDown(focusNode.dispose);
    final List<KeyEvent> events = <KeyEvent>[];

    await tester.pumpWidget(
      KeyboardListener(
        autofocus: true,
        focusNode: focusNode,
        child: Container(),
        onKeyEvent: (KeyEvent event) {
          events.add(event);
        },
      ),
    );

    // Dispatch an arbitrary event to bypass the pressedKeys check.
    await simulateKeyDownEvent(LogicalKeyboardKey.keyA, platform: 'web');

    // Dispatch an
    final Map<String, dynamic> data2 = KeyEventSimulator.getKeyData(
      LogicalKeyboardKey.shiftLeft,
      platform: 'web',
    )..['metaState'] = 0;
    await tester.binding.defaultBinaryMessenger.handlePlatformMessage(
      SystemChannels.keyEvent.name,
      SystemChannels.keyEvent.codec.encodeMessage(data2),
      (ByteData? data) {},
    );

    expect(events, hasLength(3));
    expect(events[1], isA<KeyDownEvent>());
    expect(events[1].logicalKey, LogicalKeyboardKey.shiftLeft);
    expect(events[1].synthesized, false);
    expect(events[2], isA<KeyUpEvent>());
    expect(events[2].logicalKey, LogicalKeyboardKey.shiftLeft);
    expect(events[2].synthesized, true);
    expect(ServicesBinding.instance.keyboard.physicalKeysPressed, equals(<PhysicalKeyboardKey>{
      PhysicalKeyboardKey.keyA,
    }));
  }, variant: const KeySimulatorTransitModeVariant(<KeyDataTransitMode>{
    KeyDataTransitMode.rawKeyData,
  }));

  testWidgets('Instantly dispatch synthesized key events when the queue is empty', (WidgetTester tester) async {
    final FocusNode focusNode = FocusNode();
    addTearDown(focusNode.dispose);
    final List<int> logs = <int>[];

    await tester.pumpWidget(
      KeyboardListener(
        autofocus: true,
        focusNode: focusNode,
        child: Container(),
        onKeyEvent: (KeyEvent event) {
          logs.add(1);
        },
      ),
    );
    ServicesBinding.instance.keyboard.addHandler((KeyEvent event) {
      logs.add(2);
      return false;
    });

    // Dispatch a solitary synthesized event.
    expect(ServicesBinding.instance.keyEventManager.handleKeyData(ui.KeyData(
      timeStamp: Duration.zero,
      type: ui.KeyEventType.down,
      logical: LogicalKeyboardKey.keyA.keyId,
      physical: PhysicalKeyboardKey.keyA.usbHidUsage,
      character: null,
      synthesized: true,
    )), false);
    expect(logs, <int>[2, 1]);
    logs.clear();
  }, variant: KeySimulatorTransitModeVariant.keyDataThenRawKeyData());

  testWidgets('Postpone synthesized key events when the queue is not empty', (WidgetTester tester) async {
    final FocusNode keyboardListenerFocusNode = FocusNode();
    addTearDown(keyboardListenerFocusNode.dispose);
    final FocusNode rawKeyboardListenerFocusNode = FocusNode();
    addTearDown(rawKeyboardListenerFocusNode.dispose);
    final List<String> logs = <String>[];

    await tester.pumpWidget(
      RawKeyboardListener(
        focusNode: rawKeyboardListenerFocusNode,
        onKey: (RawKeyEvent event) {
          logs.add('${event.runtimeType}');
        },
        child: KeyboardListener(
          autofocus: true,
          focusNode: keyboardListenerFocusNode,
          child: Container(),
          onKeyEvent: (KeyEvent event) {
            logs.add('${event.runtimeType}');
          },
        ),
      ),
    );

    // On macOS, a CapsLock tap yields a down event and a synthesized up event.
    expect(ServicesBinding.instance.keyEventManager.handleKeyData(ui.KeyData(
      timeStamp: Duration.zero,
      type: ui.KeyEventType.down,
      logical: LogicalKeyboardKey.capsLock.keyId,
      physical: PhysicalKeyboardKey.capsLock.usbHidUsage,
      character: null,
      synthesized: false,
    )), false);
    expect(ServicesBinding.instance.keyEventManager.handleKeyData(ui.KeyData(
      timeStamp: Duration.zero,
      type: ui.KeyEventType.up,
      logical: LogicalKeyboardKey.capsLock.keyId,
      physical: PhysicalKeyboardKey.capsLock.usbHidUsage,
      character: null,
      synthesized: true,
    )), false);
    expect(await ServicesBinding.instance.keyEventManager.handleRawKeyMessage(<String, dynamic>{
      'type': 'keydown',
      'keymap': 'macos',
      'keyCode': 0x00000039,
      'characters': '',
      'charactersIgnoringModifiers': '',
      'modifiers': 0x10000,
    }), equals(<String, dynamic>{'handled': false}));

    expect(logs, <String>['RawKeyDownEvent', 'KeyDownEvent', 'KeyUpEvent']);
    logs.clear();
  }, variant: KeySimulatorTransitModeVariant.keyDataThenRawKeyData());

  // The first key data received from the engine might be an empty key data.
  // In that case, the key data should not be converted to any [KeyEvent]s,
  // but is only used so that *a* key data comes before the raw key message
  // and makes [KeyEventManager] infer [KeyDataTransitMode.keyDataThenRawKeyData].
  testWidgets('Empty keyData yields no event but triggers inference', (WidgetTester tester) async {
    final List<KeyEvent> events = <KeyEvent>[];
    final List<RawKeyEvent> rawEvents = <RawKeyEvent>[];
    tester.binding.keyboard.addHandler((KeyEvent event) {
      events.add(event);
      return true;
    });
    RawKeyboard.instance.addListener((RawKeyEvent event) {
      rawEvents.add(event);
    });
    tester.binding.keyEventManager.handleKeyData(const ui.KeyData(
      type: ui.KeyEventType.down,
      timeStamp: Duration.zero,
      logical: 0,
      physical: 0,
      character: 'a',
      synthesized: false,
    ));
    tester.binding.keyEventManager.handleRawKeyMessage(<String, dynamic>{
      'type': 'keydown',
      'keymap': 'windows',
      'keyCode': 0x04,
      'scanCode': 0x04,
      'characterCodePoint': 0,
      'modifiers': 0,
    });
    expect(events.length, 0);
    expect(rawEvents.length, 1);

    // Dispatch another key data to ensure it's in
    // [KeyDataTransitMode.keyDataThenRawKeyData] mode (otherwise assertion
    // will be thrown upon a KeyData).
    tester.binding.keyEventManager.handleKeyData(const ui.KeyData(
      type: ui.KeyEventType.down,
      timeStamp: Duration.zero,
      logical: 0x22,
      physical: 0x70034,
      character: '"',
      synthesized: false,
    ));
    tester.binding.keyEventManager.handleRawKeyMessage(<String, dynamic>{
      'type': 'keydown',
      'keymap': 'windows',
      'keyCode': 0x04,
      'scanCode': 0x04,
      'characterCodePoint': 0,
      'modifiers': 0,
    });
    expect(events.length, 1);
    expect(rawEvents.length, 2);
  });

  testWidgets('Exceptions from keyMessageHandler are caught and reported', (WidgetTester tester) async {
    final KeyMessageHandler? oldKeyMessageHandler = tester.binding.keyEventManager.keyMessageHandler;
    addTearDown(() {
      tester.binding.keyEventManager.keyMessageHandler = oldKeyMessageHandler;
    });

    // When keyMessageHandler throws an error...
    tester.binding.keyEventManager.keyMessageHandler = (KeyMessage message) {
      throw 1;
    };

    // Simulate a key down event.
    FlutterErrorDetails? record;
    await _runWhileOverridingOnError(
      () => simulateKeyDownEvent(LogicalKeyboardKey.keyA),
      onError: (FlutterErrorDetails details) {
        record = details;
      }
    );

    // ... the error should be caught.
    expect(record, isNotNull);
    expect(record!.exception, 1);
    final Map<String, DiagnosticsNode> infos = _groupDiagnosticsByName(record!.informationCollector!());
    expect(infos['KeyMessage'], isA<DiagnosticsProperty<KeyMessage>>());

    // But the exception should not interrupt recording the state.
    // Now the keyMessageHandler no longer throws an error.
    tester.binding.keyEventManager.keyMessageHandler = null;
    record = null;

    // Simulate a key up event.
    await _runWhileOverridingOnError(
      () => simulateKeyUpEvent(LogicalKeyboardKey.keyA),
      onError: (FlutterErrorDetails details) {
        record = details;
      }
    );
    // If the previous state (key down) wasn't recorded, this key up event will
    // trigger assertions.
    expect(record, isNull);
  });

  testWidgets('Exceptions from HardwareKeyboard handlers are caught and reported', (WidgetTester tester) async {
    bool throwingCallback(KeyEvent event) {
      throw 1;
    }

    // When the handler throws an error...
    HardwareKeyboard.instance.addHandler(throwingCallback);

    // Simulate a key down event.
    FlutterErrorDetails? record;
    await _runWhileOverridingOnError(
      () => simulateKeyDownEvent(LogicalKeyboardKey.keyA),
      onError: (FlutterErrorDetails details) {
        record = details;
      }
    );

    // ... the error should be caught.
    expect(record, isNotNull);
    expect(record!.exception, 1);
    final Map<String, DiagnosticsNode> infos = _groupDiagnosticsByName(record!.informationCollector!());
    expect(infos['Event'], isA<DiagnosticsProperty<KeyEvent>>());

    // But the exception should not interrupt recording the state.
    // Now the key handler no longer throws an error.
    HardwareKeyboard.instance.removeHandler(throwingCallback);
    record = null;

    // Simulate a key up event.
    await _runWhileOverridingOnError(
      () => simulateKeyUpEvent(LogicalKeyboardKey.keyA),
      onError: (FlutterErrorDetails details) {
        record = details;
      }
    );
    // If the previous state (key down) wasn't recorded, this key up event will
    // trigger assertions.
    expect(record, isNull);
  }, variant: KeySimulatorTransitModeVariant.all());

  testWidgets('debugPrintKeyboardEvents causes logging of key events', (WidgetTester tester) async {
    final bool oldDebugPrintKeyboardEvents = debugPrintKeyboardEvents;
    final DebugPrintCallback oldDebugPrint = debugPrint;
    final StringBuffer messages = StringBuffer();
    debugPrint = (String? message, {int? wrapWidth}) {
      messages.writeln(message ?? '');
    };
    debugPrintKeyboardEvents = true;
    try {
      await simulateKeyDownEvent(LogicalKeyboardKey.keyA);
    } finally {
      debugPrintKeyboardEvents = oldDebugPrintKeyboardEvents;
      debugPrint = oldDebugPrint;
    }
    final String messagesStr = messages.toString();
    expect(messagesStr, contains('KEYBOARD: Key event received: '));
    expect(messagesStr, contains('KEYBOARD: Pressed state before processing the event:'));
    expect(messagesStr, contains('KEYBOARD: Pressed state after processing the event:'));
  });
}

Future<void> _runWhileOverridingOnError(AsyncCallback body, {required FlutterExceptionHandler onError}) async {
  final FlutterExceptionHandler? oldFlutterErrorOnError = FlutterError.onError;
  FlutterError.onError = onError;

  try {
    await body();
  } finally {
    FlutterError.onError = oldFlutterErrorOnError;
  }
}

Map<String, DiagnosticsNode> _groupDiagnosticsByName(Iterable<DiagnosticsNode> infos) {
  return Map<String, DiagnosticsNode>.fromIterable(
    infos,
    key: (dynamic node) => (node as DiagnosticsNode).name ?? '',
  );
}
