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

import 'dart:html' as html;
import 'dart:js_util' as js_util;
import 'dart:typed_data';

import 'package:quiver/testing/async.dart';
import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
import 'package:ui/src/engine/browser_detection.dart';
import 'package:ui/src/engine/keyboard.dart';
import 'package:ui/src/engine/services.dart';
import 'package:ui/src/engine/text_editing/text_editing.dart';
import 'package:ui/ui.dart' as ui;

void main() {
  internalBootstrapBrowserTest(() => testMain);
}

void testMain() {
  group('Keyboard', () {
    /// Used to save and restore [ui.window.onPlatformMessage] after each test.
    ui.PlatformMessageCallback? savedCallback;

    setUp(() {
      savedCallback = ui.window.onPlatformMessage;
    });

    tearDown(() {
      ui.window.onPlatformMessage = savedCallback;
    });

    test('initializes and disposes', () {
      expect(Keyboard.instance, isNull);
      Keyboard.initialize();
      expect(Keyboard.instance, isA<Keyboard>());
      Keyboard.instance!.dispose();
      expect(Keyboard.instance, isNull);
    });

    test('dispatches keyup to flutter/keyevent channel', () {
      Keyboard.initialize();

      String? channelReceived;
      Map<String, dynamic>? dataReceived;
      ui.window.onPlatformMessage = (String channel, ByteData? data,
          ui.PlatformMessageResponseCallback? callback) {
        channelReceived = channel;
        dataReceived = const JSONMessageCodec().decodeMessage(data) as Map<String, dynamic>?;
      };

      html.KeyboardEvent event;

      event = dispatchKeyboardEvent('keyup', key: 'SomeKey', code: 'SomeCode', keyCode: 1);

      expect(event.defaultPrevented, isFalse);
      expect(channelReceived, 'flutter/keyevent');
      expect(dataReceived, <String, dynamic>{
        'type': 'keyup',
        'keymap': 'web',
        'code': 'SomeCode',
        'location': 0,
        'key': 'SomeKey',
        'metaState': 0x0,
        'keyCode': 1,
      });

      Keyboard.instance!.dispose();
    },
        // TODO(mdebbar): https://github.com/flutter/flutter/issues/50815
        skip: browserEngine == BrowserEngine.edge);

    test('dispatches keydown to flutter/keyevent channel', () {
      Keyboard.initialize();

      String? channelReceived;
      Map<String, dynamic>? dataReceived;
      ui.window.onPlatformMessage = (String channel, ByteData? data,
          ui.PlatformMessageResponseCallback? callback) {
        channelReceived = channel;
        dataReceived = const JSONMessageCodec().decodeMessage(data) as Map<String, dynamic>?;
      };

      html.KeyboardEvent event;

      event =
          dispatchKeyboardEvent('keydown', key: 'SomeKey', code: 'SomeCode', keyCode: 1);

      expect(channelReceived, 'flutter/keyevent');
      expect(dataReceived, <String, dynamic>{
        'type': 'keydown',
        'keymap': 'web',
        'code': 'SomeCode',
        'key': 'SomeKey',
        'location': 0,
        'metaState': 0x0,
        'keyCode': 1,
      });
      expect(event.defaultPrevented, isFalse);

      Keyboard.instance!.dispose();
    },
        // TODO(mdebbar): https://github.com/flutter/flutter/issues/50815
        skip: browserEngine == BrowserEngine.edge);

    test('dispatches correct meta state', () {
      Keyboard.initialize();

      Map<String, dynamic>? dataReceived;
      ui.window.onPlatformMessage = (String channel, ByteData? data,
          ui.PlatformMessageResponseCallback? callback) {
        dataReceived = const JSONMessageCodec().decodeMessage(data) as Map<String, dynamic>?;
      };

      html.KeyboardEvent event;

      event = dispatchKeyboardEvent(
        'keydown',
        key: 'SomeKey',
        code: 'SomeCode',
        isControlPressed: true,
      );
      expect(event.defaultPrevented, isFalse);
      expect(dataReceived, <String, dynamic>{
        'type': 'keydown',
        'keymap': 'web',
        'code': 'SomeCode',
        'key': 'SomeKey',
        'location': 0,
        //          ctrl
        'metaState': 0x4,
        'keyCode': 0,
      });

      event = dispatchKeyboardEvent(
        'keydown',
        key: 'SomeKey',
        code: 'SomeCode',
        isShiftPressed: true,
        isAltPressed: true,
        isMetaPressed: true,
      );
      expect(event.defaultPrevented, isFalse);
      expect(dataReceived, <String, dynamic>{
        'type': 'keydown',
        'keymap': 'web',
        'code': 'SomeCode',
        'key': 'SomeKey',
        'location': 0,
        //          shift  alt   meta
        'metaState': 0x1 | 0x2 | 0x8,
        'keyCode': 0,
      });

      Keyboard.instance!.dispose();
    },
        // TODO(mdebbar): https://github.com/flutter/flutter/issues/50815
        skip: browserEngine == BrowserEngine.edge);

    test('dispatches repeat events', () {
      Keyboard.initialize();

      final List<Map<String, dynamic>> messages = <Map<String, dynamic>>[];
      ui.window.onPlatformMessage = (String channel, ByteData? data,
          ui.PlatformMessageResponseCallback? callback) {
        messages.add(const JSONMessageCodec().decodeMessage(data) as Map<String, dynamic>);
      };

      html.KeyboardEvent event;

      event = dispatchKeyboardEvent(
        'keydown',
        key: 'SomeKey',
        code: 'SomeCode',
        repeat: true,
      );
      expect(event.defaultPrevented, isFalse);

      event = dispatchKeyboardEvent(
        'keydown',
        key: 'SomeKey',
        code: 'SomeCode',
        repeat: true,
      );
      expect(event.defaultPrevented, isFalse);

      event = dispatchKeyboardEvent(
        'keydown',
        key: 'SomeKey',
        code: 'SomeCode',
        repeat: true,
      );
      expect(event.defaultPrevented, isFalse);

      final Map<String, dynamic> expectedMessage = <String, dynamic>{
        'type': 'keydown',
        'keymap': 'web',
        'code': 'SomeCode',
        'key': 'SomeKey',
        'location': 0,
        'metaState': 0,
        'keyCode': 0,
      };
      expect(messages, <Map<String, dynamic>>[
        expectedMessage,
        expectedMessage,
        expectedMessage,
      ]);

      Keyboard.instance!.dispose();
    },
        // TODO(mdebbar): https://github.com/flutter/flutter/issues/50815
        skip: browserEngine == BrowserEngine.edge);

    test('stops dispatching events after dispose', () {
      Keyboard.initialize();

      int count = 0;
      ui.window.onPlatformMessage = (String channel, ByteData? data,
          ui.PlatformMessageResponseCallback? callback) {
        count += 1;
      };

      dispatchKeyboardEvent('keydown');
      expect(count, 1);
      dispatchKeyboardEvent('keyup');
      expect(count, 2);

      Keyboard.instance!.dispose();
      expect(Keyboard.instance, isNull);

      // No more event dispatching.
      dispatchKeyboardEvent('keydown');
      expect(count, 2);
      dispatchKeyboardEvent('keyup');
      expect(count, 2);
    });

    test('prevents default when key is handled by the framework', () {
      Keyboard.initialize();

      int count = 0;
      ui.window.onPlatformMessage = (String channel, ByteData? data,
          ui.PlatformMessageResponseCallback? callback) {
        count += 1;
        final ByteData response = const JSONMessageCodec().encodeMessage(<String, dynamic>{'handled': true})!;
        callback!(response);
      };

      final html.KeyboardEvent event = dispatchKeyboardEvent(
        'keydown',
        key: 'Tab',
        code: 'Tab',
      );

      expect(event.defaultPrevented, isTrue);
      expect(count, 1);

      Keyboard.instance!.dispose();
    });

    test("Doesn't prevent default when key is not handled by the framework", () {
      Keyboard.initialize();

      int count = 0;
      ui.window.onPlatformMessage = (String channel, ByteData? data,
          ui.PlatformMessageResponseCallback? callback) {
        count += 1;
        final ByteData response = const JSONMessageCodec().encodeMessage(<String, dynamic>{'handled': false})!;
        callback!(response);
      };

      final html.KeyboardEvent event = dispatchKeyboardEvent(
        'keydown',
        key: 'Tab',
        code: 'Tab',
      );

      expect(event.defaultPrevented, isFalse);
      expect(count, 1);

      Keyboard.instance!.dispose();
    });

    test('keyboard events should be triggered on text fields', () {
      Keyboard.initialize();

      int count = 0;
      ui.window.onPlatformMessage = (String channel, ByteData? data,
          ui.PlatformMessageResponseCallback? callback) {
        count += 1;
      };

      useTextEditingElement((html.Element element) {
        final html.KeyboardEvent event = dispatchKeyboardEvent(
          'keydown',
          key: 'SomeKey',
          code: 'SomeCode',
          target: element,
        );

        expect(event.defaultPrevented, isFalse);
        expect(count, 1);
      });

      Keyboard.instance!.dispose();
    });

    test('the "Tab" key should never be ignored', () {
      Keyboard.initialize();

      int count = 0;
      ui.window.onPlatformMessage = (String channel, ByteData? data,
          ui.PlatformMessageResponseCallback? callback) {
        count += 1;
        final ByteData response = const JSONMessageCodec().encodeMessage(<String, dynamic>{'handled': true})!;
        callback!(response);
      };

      useTextEditingElement((html.Element element) {
        final html.KeyboardEvent event = dispatchKeyboardEvent(
          'keydown',
          key: 'Tab',
          code: 'Tab',
          target: element,
        );

        expect(event.defaultPrevented, isTrue);
        expect(count, 1);
      });

      Keyboard.instance!.dispose();
    });

    testFakeAsync(
      'On macOS, synthesize keyup when shortcut is handled by the system',
      (FakeAsync async) {
        // This can happen when the user clicks `cmd+alt+i` to open devtools. Here
        // is the sequence we receive from the browser in such case:
        //
        // keydown(cmd) -> keydown(alt) -> keydown(i) -> keyup(alt) -> keyup(cmd)
        //
        // There's no `keyup(i)`. The web engine is expected to synthesize a
        // `keyup(i)` event.
        Keyboard.initialize(onMacOs: true);

        final List<Map<String, dynamic>> messages = <Map<String, dynamic>>[];
        ui.window.onPlatformMessage = (String channel, ByteData? data,
            ui.PlatformMessageResponseCallback? callback) {
          messages.add(const JSONMessageCodec().decodeMessage(data) as Map<String, dynamic>);
        };

        dispatchKeyboardEvent(
          'keydown',
          key: 'Meta',
          code: 'MetaLeft',
          location: 1,
          isMetaPressed: true,
        );
        dispatchKeyboardEvent(
          'keydown',
          key: 'Alt',
          code: 'AltLeft',
          location: 1,
          isMetaPressed: true,
          isAltPressed: true,
        );
        dispatchKeyboardEvent(
          'keydown',
          key: 'i',
          code: 'KeyI',
          isMetaPressed: true,
          isAltPressed: true,
        );
        async.elapse(const Duration(milliseconds: 10));
        dispatchKeyboardEvent(
          'keyup',
          key: 'Meta',
          code: 'MetaLeft',
          location: 1,
          isAltPressed: true,
        );
        dispatchKeyboardEvent(
          'keyup',
          key: 'Alt',
          code: 'AltLeft',
          location: 1,
        );
        // Notice no `keyup` for "i".

        expect(messages, <Map<String, dynamic>>[
          <String, dynamic>{
            'type': 'keydown',
            'keymap': 'web',
            'key': 'Meta',
            'code': 'MetaLeft',
            'location': 1,
            //           meta
            'metaState': 0x8,
            'keyCode': 0,
          },
          <String, dynamic>{
            'type': 'keydown',
            'keymap': 'web',
            'key': 'Alt',
            'code': 'AltLeft',
            'location': 1,
            //           alt   meta
            'metaState': 0x2 | 0x8,
            'keyCode': 0,
          },
          <String, dynamic>{
            'type': 'keydown',
            'keymap': 'web',
            'key': 'i',
            'code': 'KeyI',
            'location': 0,
            //           alt   meta
            'metaState': 0x2 | 0x8,
            'keyCode': 0,
          },
          <String, dynamic>{
            'type': 'keyup',
            'keymap': 'web',
            'key': 'Meta',
            'code': 'MetaLeft',
            'location': 1,
            //           alt
            'metaState': 0x2,
            'keyCode': 0,
          },
          <String, dynamic>{
            'type': 'keyup',
            'keymap': 'web',
            'key': 'Alt',
            'code': 'AltLeft',
            'location': 1,
            'metaState': 0x0,
            'keyCode': 0,
          },
        ]);
        messages.clear();

        // Still too eary to synthesize a keyup event.
        async.elapse(const Duration(milliseconds: 50));
        expect(messages, isEmpty);

        async.elapse(const Duration(seconds: 3));
        expect(messages, <Map<String, dynamic>>[
          <String, dynamic>{
            'type': 'keyup',
            'keymap': 'web',
            'key': 'i',
            'code': 'KeyI',
            'location': 0,
            'metaState': 0x0,
            'keyCode': 0,
          }
        ]);

        Keyboard.instance!.dispose();
      },
    );

    testFakeAsync(
      'On macOS, do not synthesize keyup when we receive repeat events',
      (FakeAsync async) {
        Keyboard.initialize(onMacOs: true);

        final List<Map<String, dynamic>> messages = <Map<String, dynamic>>[];
        ui.window.onPlatformMessage = (String channel, ByteData? data,
            ui.PlatformMessageResponseCallback? callback) {
          messages.add(const JSONMessageCodec().decodeMessage(data) as Map<String, dynamic>);
        };

        dispatchKeyboardEvent(
          'keydown',
          key: 'Meta',
          code: 'MetaLeft',
          location: 1,
          isMetaPressed: true,
        );
        dispatchKeyboardEvent(
          'keydown',
          key: 'Alt',
          code: 'AltLeft',
          location: 1,
          isMetaPressed: true,
          isAltPressed: true,
        );
        dispatchKeyboardEvent(
          'keydown',
          key: 'i',
          code: 'KeyI',
          isMetaPressed: true,
          isAltPressed: true,
        );
        async.elapse(const Duration(milliseconds: 10));
        dispatchKeyboardEvent(
          'keyup',
          key: 'Meta',
          code: 'MetaLeft',
          location: 1,
          isAltPressed: true,
        );
        dispatchKeyboardEvent(
          'keyup',
          key: 'Alt',
          code: 'AltLeft',
          location: 1,
        );
        // Notice no `keyup` for "i".

        messages.clear();

        // Spend more than 2 seconds sending repeat events and make sure no
        // keyup was synthesized.
        for (int i = 0; i < 20; i++) {
          async.elapse(const Duration(milliseconds: 100));
          dispatchKeyboardEvent(
            'keydown',
            key: 'i',
            code: 'KeyI',
            repeat: true,
          );
        }

        // There should be no synthesized keyup.
        expect(messages, hasLength(20));
        for (int i = 0; i < 20; i++) {
          expect(messages[i], <String, dynamic>{
            'type': 'keydown',
            'keymap': 'web',
            'key': 'i',
            'code': 'KeyI',
            'location': 0,
            'metaState': 0x0,
            'keyCode': 0,
          });
        }
        messages.clear();

        Keyboard.instance!.dispose();
      },
    );

    testFakeAsync(
      'On macOS, do not synthesize keyup when keys are not affected by meta modifiers',
      (FakeAsync async) {
        Keyboard.initialize();

        final List<Map<String, dynamic>> messages = <Map<String, dynamic>>[];
        ui.window.onPlatformMessage = (String channel, ByteData? data,
            ui.PlatformMessageResponseCallback? callback) {
          messages.add(const JSONMessageCodec().decodeMessage(data) as Map<String, dynamic>);
        };

        dispatchKeyboardEvent(
          'keydown',
          key: 'i',
          code: 'KeyI',
        );
        dispatchKeyboardEvent(
          'keydown',
          key: 'o',
          code: 'KeyO',
        );
        messages.clear();

        // Wait for a long-enough period of time and no events
        // should be synthesized
        async.elapse(const Duration(seconds: 3));
        expect(messages, hasLength(0));

        Keyboard.instance!.dispose();
      },
    );

    testFakeAsync('On macOS, do not synthesize keyup for meta keys', (FakeAsync async) {
      Keyboard.initialize(onMacOs: true);

      final List<Map<String, dynamic>> messages = <Map<String, dynamic>>[];
      ui.window.onPlatformMessage = (String channel, ByteData? data,
          ui.PlatformMessageResponseCallback? callback) {
        messages.add(const JSONMessageCodec().decodeMessage(data) as Map<String, dynamic>);
      };

      dispatchKeyboardEvent(
        'keydown',
        key: 'Meta',
        code: 'MetaLeft',
        location: 1,
        isMetaPressed: true,
      );
      dispatchKeyboardEvent(
        'keydown',
        key: 'Alt',
        code: 'AltLeft',
        location: 1,
        isMetaPressed: true,
        isAltPressed: true,
      );
      dispatchKeyboardEvent(
        'keydown',
        key: 'i',
        code: 'KeyI',
        isMetaPressed: true,
        isAltPressed: true,
      );
      async.elapse(const Duration(milliseconds: 10));
      dispatchKeyboardEvent(
        'keyup',
        key: 'Meta',
        code: 'MetaLeft',
        location: 1,
        isAltPressed: true,
      );
      // Notice no `keyup` for "AltLeft" and "i".

      messages.clear();

      // There has been no repeat events for "AltLeft" nor "i". Only "i" should
      // synthesize a keyup event.
      async.elapse(const Duration(seconds: 3));
      expect(messages, <Map<String, dynamic>>[
        <String, dynamic>{
          'type': 'keyup',
          'keymap': 'web',
          'key': 'i',
          'code': 'KeyI',
          'location': 0,
          //           alt
          'metaState': 0x2,
          'keyCode': 0,
        }
      ]);

      Keyboard.instance!.dispose();
    });

    testFakeAsync(
      'On non-macOS, do not synthesize keyup for shortcuts',
      (FakeAsync async) {
        Keyboard.initialize(onMacOs: false);

        final List<Map<String, dynamic>> messages = <Map<String, dynamic>>[];
        ui.window.onPlatformMessage = (String channel, ByteData? data,
            ui.PlatformMessageResponseCallback? callback) {
          messages.add(const JSONMessageCodec().decodeMessage(data) as Map<String, dynamic>);
        };

        dispatchKeyboardEvent(
          'keydown',
          key: 'Meta',
          code: 'MetaLeft',
          location: 1,
          isMetaPressed: true,
        );
        dispatchKeyboardEvent(
          'keydown',
          key: 'Alt',
          code: 'AltLeft',
          location: 1,
          isMetaPressed: true,
          isAltPressed: true,
        );
        dispatchKeyboardEvent(
          'keydown',
          key: 'i',
          code: 'KeyI',
          isMetaPressed: true,
          isAltPressed: true,
        );
        async.elapse(const Duration(milliseconds: 10));
        dispatchKeyboardEvent(
          'keyup',
          key: 'Meta',
          code: 'MetaLeft',
          location: 1,
          isAltPressed: true,
        );
        dispatchKeyboardEvent(
          'keyup',
          key: 'Alt',
          code: 'AltLeft',
          location: 1,
        );
        // Notice no `keyup` for "i".

        expect(messages, hasLength(5));
        messages.clear();

        // Never synthesize keyup events.
        async.elapse(const Duration(seconds: 3));
        expect(messages, isEmpty);

        Keyboard.instance!.dispose();
      },
    );

  });
}

typedef ElementCallback = void Function(html.Element element);

void useTextEditingElement(ElementCallback callback) {
  final html.InputElement input = html.InputElement();
  input.classes.add(HybridTextEditing.textEditingClass);

  try {
    html.document.body!.append(input);
    callback(input);
  } finally {
    input.remove();
  }
}

html.KeyboardEvent dispatchKeyboardEvent(
  String type, {
  html.EventTarget? target,
  String? key,
  String? code,
  int location = 0,
  bool repeat = false,
  bool isShiftPressed = false,
  bool isAltPressed = false,
  bool isControlPressed = false,
  bool isMetaPressed = false,
  int keyCode = 0,
}) {
  target ??= html.window;

  final Function jsKeyboardEvent =
      js_util.getProperty<Function>(html.window, 'KeyboardEvent');
  final List<dynamic> eventArgs = <dynamic>[
    type,
    <String, dynamic>{
      'key': key,
      'code': code,
      'location': location,
      'repeat': repeat,
      'shiftKey': isShiftPressed,
      'altKey': isAltPressed,
      'ctrlKey': isControlPressed,
      'metaKey': isMetaPressed,
      'keyCode': keyCode,
      'bubbles': true,
      'cancelable': true,
    }
  ];
  final html.KeyboardEvent event = js_util.callConstructor<html.KeyboardEvent>(
    jsKeyboardEvent,
    js_util.jsify(eventArgs) as List<Object?>,
  );
  target.dispatchEvent(event);

  return event;
}

typedef FakeAsyncTest = void Function(FakeAsync);

void testFakeAsync(String description, FakeAsyncTest fn) {
  test(description, () {
    FakeAsync().run(fn);
  });
}
