// 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/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';

const List<String> platforms = <String>['linux', 'macos', 'android', 'fuchsia'];

void _verifyKeyEvent<T extends KeyEvent>(KeyEvent event, PhysicalKeyboardKey physical, LogicalKeyboardKey logical, String? character) {
  expect(event, isA<T>());
  expect(event.physicalKey, physical);
  expect(event.logicalKey, logical);
  expect(event.character, character);
  expect(event.synthesized, false);
}

void _verifyRawKeyEvent<T extends RawKeyEvent>(RawKeyEvent event, PhysicalKeyboardKey physical, LogicalKeyboardKey logical, String? character) {
  expect(event, isA<T>());
  expect(event.physicalKey, physical);
  expect(event.logicalKey, logical);
  expect(event.character, character);
}

Future<void> _shouldThrow<T extends Error>(AsyncValueGetter<void> func) async {
  bool hasError = false;
  try {
    await func();
  } catch (e) {
    expect(e, isA<T>());
    hasError = true;
  } finally {
    expect(hasError, true);
  }
}

void main() {
  testWidgets('simulates keyboard events (RawEvent)', (WidgetTester tester) async {
    debugKeyEventSimulatorTransitModeOverride = KeyDataTransitMode.rawKeyData;

    final List<RawKeyEvent> events = <RawKeyEvent>[];

    final FocusNode focusNode = FocusNode();

    await tester.pumpWidget(
      RawKeyboardListener(
        focusNode: focusNode,
        onKey: events.add,
        child: Container(),
      ),
    );

    focusNode.requestFocus();
    await tester.idle();

    for (final String platform in platforms) {
      await tester.sendKeyEvent(LogicalKeyboardKey.shiftLeft, platform: platform);
      await tester.sendKeyEvent(LogicalKeyboardKey.shift, platform: platform);
      await tester.sendKeyDownEvent(LogicalKeyboardKey.keyA, platform: platform);
      await tester.sendKeyUpEvent(LogicalKeyboardKey.keyA, platform: platform);
      await tester.sendKeyDownEvent(LogicalKeyboardKey.numpad1, platform: platform);
      await tester.sendKeyUpEvent(LogicalKeyboardKey.numpad1, platform: platform);
      await tester.idle();

      expect(events.length, 8);
      for (int i = 0; i < events.length; ++i) {
        final bool isEven = i.isEven;
        if (isEven) {
          expect(events[i].runtimeType, equals(RawKeyDownEvent));
        } else {
          expect(events[i].runtimeType, equals(RawKeyUpEvent));
        }
        if (i < 4) {
          expect(events[i].data.isModifierPressed(ModifierKey.shiftModifier, side: KeyboardSide.left), equals(isEven));
        }
      }
      events.clear();
    }

    await tester.pumpWidget(Container());
    focusNode.dispose();

    debugKeyEventSimulatorTransitModeOverride = null;
  });

  testWidgets('simulates keyboard events (KeyData then RawKeyEvent)', (WidgetTester tester) async {
    debugKeyEventSimulatorTransitModeOverride = KeyDataTransitMode.keyDataThenRawKeyData;

    final List<KeyEvent> events = <KeyEvent>[];

    final FocusNode focusNode = FocusNode();

    await tester.pumpWidget(
      KeyboardListener(
        focusNode: focusNode,
        onKeyEvent: events.add,
        child: Container(),
      ),
    );

    focusNode.requestFocus();
    await tester.idle();

    // Key press shiftLeft
    await tester.sendKeyDownEvent(LogicalKeyboardKey.shiftLeft);
    expect(events.length, 1);
    _verifyKeyEvent<KeyDownEvent>(events[0], PhysicalKeyboardKey.shiftLeft, LogicalKeyboardKey.shiftLeft, null);
    expect(HardwareKeyboard.instance.physicalKeysPressed, equals(<PhysicalKeyboardKey>{PhysicalKeyboardKey.shiftLeft}));
    expect(HardwareKeyboard.instance.logicalKeysPressed, equals(<LogicalKeyboardKey>{LogicalKeyboardKey.shiftLeft}));
    expect(HardwareKeyboard.instance.lockModesEnabled, isEmpty);
    events.clear();

    await tester.sendKeyRepeatEvent(LogicalKeyboardKey.shiftLeft);
    expect(events.length, 1);
    _verifyKeyEvent<KeyRepeatEvent>(events[0], PhysicalKeyboardKey.shiftLeft, LogicalKeyboardKey.shiftLeft, null);
    expect(HardwareKeyboard.instance.physicalKeysPressed, equals(<PhysicalKeyboardKey>{PhysicalKeyboardKey.shiftLeft}));
    expect(HardwareKeyboard.instance.logicalKeysPressed, equals(<LogicalKeyboardKey>{LogicalKeyboardKey.shiftLeft}));
    expect(HardwareKeyboard.instance.lockModesEnabled, isEmpty);
    events.clear();

    await tester.sendKeyUpEvent(LogicalKeyboardKey.shiftLeft);
    expect(events.length, 1);
    _verifyKeyEvent<KeyUpEvent>(events[0], PhysicalKeyboardKey.shiftLeft, LogicalKeyboardKey.shiftLeft, null);
    expect(HardwareKeyboard.instance.physicalKeysPressed, isEmpty);
    expect(HardwareKeyboard.instance.logicalKeysPressed, isEmpty);
    expect(HardwareKeyboard.instance.lockModesEnabled, isEmpty);
    events.clear();

    // Key press keyA
    await tester.sendKeyDownEvent(LogicalKeyboardKey.keyA);
    expect(events.length, 1);
    _verifyKeyEvent<KeyDownEvent>(events[0], PhysicalKeyboardKey.keyA, LogicalKeyboardKey.keyA, 'a');
    expect(HardwareKeyboard.instance.physicalKeysPressed, equals(<PhysicalKeyboardKey>{PhysicalKeyboardKey.keyA}));
    expect(HardwareKeyboard.instance.logicalKeysPressed, equals(<LogicalKeyboardKey>{LogicalKeyboardKey.keyA}));
    expect(HardwareKeyboard.instance.lockModesEnabled, isEmpty);
    events.clear();

    await tester.sendKeyRepeatEvent(LogicalKeyboardKey.keyA);
    _verifyKeyEvent<KeyRepeatEvent>(events[0], PhysicalKeyboardKey.keyA, LogicalKeyboardKey.keyA, 'a');
    expect(HardwareKeyboard.instance.physicalKeysPressed, equals(<PhysicalKeyboardKey>{PhysicalKeyboardKey.keyA}));
    expect(HardwareKeyboard.instance.logicalKeysPressed, equals(<LogicalKeyboardKey>{LogicalKeyboardKey.keyA}));
    expect(HardwareKeyboard.instance.lockModesEnabled, isEmpty);
    events.clear();

    await tester.sendKeyUpEvent(LogicalKeyboardKey.keyA);
    _verifyKeyEvent<KeyUpEvent>(events[0], PhysicalKeyboardKey.keyA, LogicalKeyboardKey.keyA, null);
    expect(HardwareKeyboard.instance.physicalKeysPressed, isEmpty);
    expect(HardwareKeyboard.instance.logicalKeysPressed, isEmpty);
    expect(HardwareKeyboard.instance.lockModesEnabled, isEmpty);
    events.clear();

    // Key press numpad1
    await tester.sendKeyDownEvent(LogicalKeyboardKey.numpad1);
    _verifyKeyEvent<KeyDownEvent>(events[0], PhysicalKeyboardKey.numpad1, LogicalKeyboardKey.numpad1, null);
    expect(HardwareKeyboard.instance.physicalKeysPressed, equals(<PhysicalKeyboardKey>{PhysicalKeyboardKey.numpad1}));
    expect(HardwareKeyboard.instance.logicalKeysPressed, equals(<LogicalKeyboardKey>{LogicalKeyboardKey.numpad1}));
    expect(HardwareKeyboard.instance.lockModesEnabled, isEmpty);
    events.clear();

    await tester.sendKeyRepeatEvent(LogicalKeyboardKey.numpad1);
    _verifyKeyEvent<KeyRepeatEvent>(events[0], PhysicalKeyboardKey.numpad1, LogicalKeyboardKey.numpad1, null);
    expect(HardwareKeyboard.instance.physicalKeysPressed, equals(<PhysicalKeyboardKey>{PhysicalKeyboardKey.numpad1}));
    expect(HardwareKeyboard.instance.logicalKeysPressed, equals(<LogicalKeyboardKey>{LogicalKeyboardKey.numpad1}));
    expect(HardwareKeyboard.instance.lockModesEnabled, isEmpty);
    events.clear();

    await tester.sendKeyUpEvent(LogicalKeyboardKey.numpad1);
    _verifyKeyEvent<KeyUpEvent>(events[0], PhysicalKeyboardKey.numpad1, LogicalKeyboardKey.numpad1, null);
    expect(HardwareKeyboard.instance.physicalKeysPressed, isEmpty);
    expect(HardwareKeyboard.instance.logicalKeysPressed, isEmpty);
    expect(HardwareKeyboard.instance.lockModesEnabled, isEmpty);
    events.clear();

    // Key press numLock (1st time)
    await tester.sendKeyDownEvent(LogicalKeyboardKey.numLock);
    _verifyKeyEvent<KeyDownEvent>(events[0], PhysicalKeyboardKey.numLock, LogicalKeyboardKey.numLock, null);
    expect(HardwareKeyboard.instance.physicalKeysPressed, equals(<PhysicalKeyboardKey>{PhysicalKeyboardKey.numLock}));
    expect(HardwareKeyboard.instance.logicalKeysPressed, equals(<LogicalKeyboardKey>{LogicalKeyboardKey.numLock}));
    expect(HardwareKeyboard.instance.lockModesEnabled, equals(<KeyboardLockMode>{KeyboardLockMode.numLock}));
    events.clear();

    await tester.sendKeyRepeatEvent(LogicalKeyboardKey.numLock);
    _verifyKeyEvent<KeyRepeatEvent>(events[0], PhysicalKeyboardKey.numLock, LogicalKeyboardKey.numLock, null);
    expect(HardwareKeyboard.instance.physicalKeysPressed, equals(<PhysicalKeyboardKey>{PhysicalKeyboardKey.numLock}));
    expect(HardwareKeyboard.instance.logicalKeysPressed, equals(<LogicalKeyboardKey>{LogicalKeyboardKey.numLock}));
    expect(HardwareKeyboard.instance.lockModesEnabled, equals(<KeyboardLockMode>{KeyboardLockMode.numLock}));
    events.clear();

    await tester.sendKeyUpEvent(LogicalKeyboardKey.numLock);
    _verifyKeyEvent<KeyUpEvent>(events[0], PhysicalKeyboardKey.numLock, LogicalKeyboardKey.numLock, null);
    expect(HardwareKeyboard.instance.physicalKeysPressed, isEmpty);
    expect(HardwareKeyboard.instance.logicalKeysPressed, isEmpty);
    expect(HardwareKeyboard.instance.lockModesEnabled, equals(<KeyboardLockMode>{KeyboardLockMode.numLock}));
    events.clear();

    // Key press numLock (2nd time)
    await tester.sendKeyDownEvent(LogicalKeyboardKey.numLock);
    _verifyKeyEvent<KeyDownEvent>(events[0], PhysicalKeyboardKey.numLock, LogicalKeyboardKey.numLock, null);
    expect(HardwareKeyboard.instance.physicalKeysPressed, equals(<PhysicalKeyboardKey>{PhysicalKeyboardKey.numLock}));
    expect(HardwareKeyboard.instance.logicalKeysPressed, equals(<LogicalKeyboardKey>{LogicalKeyboardKey.numLock}));
    expect(HardwareKeyboard.instance.lockModesEnabled, isEmpty);
    events.clear();

    await tester.sendKeyRepeatEvent(LogicalKeyboardKey.numLock);
    _verifyKeyEvent<KeyRepeatEvent>(events[0], PhysicalKeyboardKey.numLock, LogicalKeyboardKey.numLock, null);
    expect(HardwareKeyboard.instance.physicalKeysPressed, equals(<PhysicalKeyboardKey>{PhysicalKeyboardKey.numLock}));
    expect(HardwareKeyboard.instance.logicalKeysPressed, equals(<LogicalKeyboardKey>{LogicalKeyboardKey.numLock}));
    expect(HardwareKeyboard.instance.lockModesEnabled, isEmpty);
    events.clear();

    await tester.sendKeyUpEvent(LogicalKeyboardKey.numLock);
    _verifyKeyEvent<KeyUpEvent>(events[0], PhysicalKeyboardKey.numLock, LogicalKeyboardKey.numLock, null);
    expect(HardwareKeyboard.instance.physicalKeysPressed, isEmpty);
    expect(HardwareKeyboard.instance.logicalKeysPressed, isEmpty);
    expect(HardwareKeyboard.instance.lockModesEnabled, isEmpty);
    events.clear();

    await tester.idle();

    await tester.pumpWidget(Container());
    focusNode.dispose();

    debugKeyEventSimulatorTransitModeOverride = null;
  });

  testWidgets('simulates using the correct transit mode: rawKeyData', (WidgetTester tester) async {
    debugKeyEventSimulatorTransitModeOverride = KeyDataTransitMode.rawKeyData;

    final List<Object> events = <Object>[];

    final FocusNode focusNode = FocusNode();
    await tester.pumpWidget(
      Focus(
        focusNode: focusNode,
        onKey: (FocusNode node, RawKeyEvent event) {
          events.add(event);
          return KeyEventResult.ignored;
        },
        onKeyEvent: (FocusNode node, KeyEvent event) {
          events.add(event);
          return KeyEventResult.ignored;
        },
        child: Container(),
      ),
    );

    focusNode.requestFocus();
    await tester.idle();

    // A (physical keyA, logical keyA) is pressed.
    await simulateKeyDownEvent(LogicalKeyboardKey.keyA);
    expect(events.length, 2);
    expect(events[0], isA<KeyEvent>());
    _verifyKeyEvent<KeyDownEvent>(events[0] as KeyEvent, PhysicalKeyboardKey.keyA, LogicalKeyboardKey.keyA, 'a');
    expect(events[1], isA<RawKeyEvent>());
    _verifyRawKeyEvent<RawKeyDownEvent>(events[1] as RawKeyEvent, PhysicalKeyboardKey.keyA, LogicalKeyboardKey.keyA, 'a');
    events.clear();

    // A (physical keyA, logical keyB) is released.
    //
    // Since this event was synthesized and regularized before being sent to
    // HardwareKeyboard, this event will be accepted.
    await simulateKeyUpEvent(LogicalKeyboardKey.keyB, physicalKey: PhysicalKeyboardKey.keyA);
    expect(events.length, 2);
    expect(events[0], isA<KeyEvent>());
    _verifyKeyEvent<KeyUpEvent>(events[0] as KeyEvent, PhysicalKeyboardKey.keyA, LogicalKeyboardKey.keyA, null);
    expect(events[1], isA<RawKeyEvent>());
    _verifyRawKeyEvent<RawKeyUpEvent>(events[1] as RawKeyEvent, PhysicalKeyboardKey.keyA, LogicalKeyboardKey.keyB, null);
    events.clear();

    // Manually switch the transit mode to `keyDataThenRawKeyData`. This will
    // never happen in real applications so the assertion error can verify that
    // the transit mode is correctly applied.
    debugKeyEventSimulatorTransitModeOverride = KeyDataTransitMode.keyDataThenRawKeyData;

    await _shouldThrow<AssertionError>(() =>
      simulateKeyUpEvent(LogicalKeyboardKey.keyB, physicalKey: PhysicalKeyboardKey.keyA));

    debugKeyEventSimulatorTransitModeOverride = null;
  });

  testWidgets('simulates using the correct transit mode: keyDataThenRawKeyData', (WidgetTester tester) async {
    debugKeyEventSimulatorTransitModeOverride = KeyDataTransitMode.keyDataThenRawKeyData;

    final List<Object> events = <Object>[];

    final FocusNode focusNode = FocusNode();
    await tester.pumpWidget(
      Focus(
        focusNode: focusNode,
        onKey: (FocusNode node, RawKeyEvent event) {
          events.add(event);
          return KeyEventResult.ignored;
        },
        onKeyEvent: (FocusNode node, KeyEvent event) {
          events.add(event);
          return KeyEventResult.ignored;
        },
        child: Container(),
      ),
    );

    focusNode.requestFocus();
    await tester.idle();

    // A (physical keyA, logical keyA) is pressed.
    await simulateKeyDownEvent(LogicalKeyboardKey.keyA);
    expect(events.length, 2);
    expect(events[0], isA<KeyEvent>());
    _verifyKeyEvent<KeyDownEvent>(events[0] as KeyEvent, PhysicalKeyboardKey.keyA, LogicalKeyboardKey.keyA, 'a');
    expect(events[1], isA<RawKeyEvent>());
    _verifyRawKeyEvent<RawKeyDownEvent>(events[1] as RawKeyEvent, PhysicalKeyboardKey.keyA, LogicalKeyboardKey.keyA, 'a');
    events.clear();

    // A (physical keyA, logical keyB) is released.
    //
    // Since this event is transmitted to HardwareKeyboard as-is, it will be rejected due to
    // inconsistent logical key. This does not indicate behaviral difference,
    // since KeyData is will never send malformed data sequence in real applications.
    await _shouldThrow<AssertionError>(() =>
      simulateKeyUpEvent(LogicalKeyboardKey.keyB, physicalKey: PhysicalKeyboardKey.keyA));

    debugKeyEventSimulatorTransitModeOverride = null;
  });
}
