// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library KeyboardEventTest;

import 'dart:html';

import 'package:expect/minitest.dart';

// Test that we are correctly determining keyCode and charCode uniformly across
// browsers.

void testKeyboardEventConstructor() {
  new KeyboardEvent('keyup');
}

void keydownHandlerTest(KeyEvent e) {
  expect(e.charCode, 0);
}

void testKeys() {
  var subscription =
      KeyboardEventStream.onKeyDown(document.body!).listen(keydownHandlerTest);
  var subscription2 =
      KeyEvent.keyDownEvent.forTarget(document.body).listen(keydownHandlerTest);
  var subscription3 =
      document.body!.onKeyDown.listen((e) => print('regular listener'));
  subscription.cancel();
  subscription2.cancel();
  subscription3.cancel();
}

void testConstructKeyEvent() {
  int handlerCallCount = 0;
  CustomStream<KeyEvent> stream = KeyEvent.keyPressEvent
      .forTarget(document.body!) as CustomStream<KeyEvent>;
  var subscription = stream.listen((keyEvent) {
    expect(keyEvent.charCode, 97);
    expect(keyEvent.keyCode, 65);
    handlerCallCount++;
  });
  var k = new KeyEvent('keypress', keyCode: 65, charCode: 97);
  stream.add(k);
  subscription.cancel();
  // Capital "A":
  stream.add(new KeyEvent('keydown', keyCode: 16, charCode: 0));

  subscription = stream.listen((keyEvent) {
    expect(keyEvent.charCode, 65);
    expect(keyEvent.keyCode, 65);
    handlerCallCount++;
  });
  stream.add(new KeyEvent('keypress', keyCode: 65, charCode: 65));
  subscription.cancel();

  expect(handlerCallCount, 2);
}

void testKeyEventSequence() {
  int handlerCallCount = 0;
  // Press "?" by simulating "shift" and then the key that has "/" and "?" on
  // it.
  CustomStream<KeyEvent> streamDown =
      KeyEvent.keyDownEvent.forTarget(document.body!) as CustomStream<KeyEvent>;
  CustomStream<KeyEvent> streamPress = KeyEvent.keyPressEvent
      .forTarget(document.body!) as CustomStream<KeyEvent>;
  CustomStream<KeyEvent> streamUp =
      KeyEvent.keyUpEvent.forTarget(document.body!) as CustomStream<KeyEvent>;

  var subscription = streamDown.listen((keyEvent) {
    expect(keyEvent.keyCode, predicate([16, 191].contains));
    expect(keyEvent.charCode, 0);
    handlerCallCount++;
  });

  var subscription2 = streamPress.listen((keyEvent) {
    expect(keyEvent.keyCode, 23);
    expect(keyEvent.charCode, 63);
    handlerCallCount++;
  });

  var subscription3 = streamUp.listen((keyEvent) {
    expect(keyEvent.keyCode, predicate([16, 191].contains));
    expect(keyEvent.charCode, 0);
    handlerCallCount++;
  });

  streamDown.add(new KeyEvent('keydown', keyCode: 16, charCode: 0));
  streamDown.add(new KeyEvent('keydown', keyCode: 191, charCode: 0));

  streamPress.add(new KeyEvent('keypress', keyCode: 23, charCode: 63));

  streamUp.add(new KeyEvent('keyup', keyCode: 191, charCode: 0));
  streamUp.add(new KeyEvent('keyup', keyCode: 16, charCode: 0));
  subscription.cancel();
  subscription2.cancel();
  subscription3.cancel();

  expect(handlerCallCount, 5);
}

void testKeyEventKeyboardEvent() {
  int handlerCallCount = 0;
  window.onKeyDown.listen((event) {
    expect(event.keyCode, 16);
    handlerCallCount++;
  });
  CustomStream<KeyEvent> streamDown =
      KeyEvent.keyDownEvent.forTarget(document.body!) as CustomStream<KeyEvent>;
  streamDown.add(new KeyEvent('keydown', keyCode: 16, charCode: 0));
  expect(handlerCallCount, 1);
}

main() {
  testKeyboardEventConstructor();
  testKeys();
  testConstructKeyEvent();
  testKeyEventSequence();
  testKeyEventKeyboardEvent();
}
