// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "keyboard.h"

#include <array>

#include <hid/hid.h>
#include <hid/usages.h>
#include <zxtest/zxtest.h>

#include "keyboard-vt100.h"
#include "src/ui/input/lib/hid-input-report/keyboard.h"
#include "src/ui/lib/key_util/key_util.h"

namespace {

namespace fuchsia_input_report = fuchsia_input_report;

// State reported to keypress_handler().
uint8_t g_keycode;
int g_modifiers;
bool g_got_keypress = false;

void keypress_handler(uint8_t keycode, int modifiers) {
  g_keycode = keycode;
  g_modifiers = modifiers;
  g_got_keypress = true;
}

void expect_keypress(uint8_t expected_keycode, int expected_modifiers, uint8_t expected_char) {
  EXPECT_EQ(g_got_keypress, true);
  g_got_keypress = false;

  EXPECT_EQ(g_keycode, expected_keycode);
  EXPECT_EQ(g_modifiers, expected_modifiers);

  std::array<char, 4> output = {};
  uint32_t length =
      hid_key_to_vt100_code(g_keycode, g_modifiers, qwerty_map, output.data(), output.size());
  if (expected_char == 0) {
    EXPECT_EQ(length, 0);
  } else {
    ASSERT_EQ(length, 1);
    EXPECT_EQ(output[0], expected_char);
  }
}

class KeyboardInputHelper {
 public:
  KeyboardInputHelper(async_dispatcher_t* dispatcher)
      : keyboard_(dispatcher, keypress_handler, true) {}

  ~KeyboardInputHelper() {}

  void WriteReportBuf(std::vector<uint32_t> keys) {
    fidl::FidlAllocator allocator;
    fuchsia_input_report::wire::InputReport input_report(allocator);
    fuchsia_input_report::wire::KeyboardInputReport keyboard_input_report(allocator);

    size_t index = 0;
    fidl::VectorView<fuchsia_input::wire::Key> fidl_keys(allocator, keys.size());
    for (auto& key : keys) {
      auto fidl_key =
          *key_util::hid_key_to_fuchsia_key3(hid::USAGE(hid::usage::Page::kKeyboardKeypad, key));
      fidl_keys[index++] = static_cast<fuchsia_input::wire::Key>(fidl_key);
    }
    keyboard_input_report.set_pressed_keys3(allocator, std::move(fidl_keys));
    input_report.set_keyboard(allocator, std::move(keyboard_input_report));
    keyboard_.ProcessInput(input_report);
  }

  // Byte 0 contains one bit per modifier key.
  void set_modifiers_byte(uint8_t value) {}
  // Bytes 2+ contain USB HID key codes.
  void set_first_keycode(uint8_t value) {}

 private:
  Keyboard keyboard_;
};

TEST(GfxConsoleKeyboardTests, KeyboardInputThread) {
  async::Loop loop = async::Loop(&kAsyncLoopConfigNeverAttachToThread);
  KeyboardInputHelper helper(loop.dispatcher());
  std::vector<uint32_t> keypresses;

  // Test pressing keys without any modifiers.
  keypresses = {HID_USAGE_KEY_M};
  helper.WriteReportBuf(keypresses);
  ASSERT_NO_FAILURES(expect_keypress(HID_USAGE_KEY_M, 0, 'm'));

  keypresses = {HID_USAGE_KEY_6};
  helper.WriteReportBuf(keypresses);
  ASSERT_NO_FAILURES(expect_keypress(HID_USAGE_KEY_6, 0, '6'));

  // Press a modifier (but no other keys).
  keypresses = {HID_USAGE_KEY_LEFT_SHIFT};
  helper.WriteReportBuf(keypresses);
  ASSERT_NO_FAILURES(expect_keypress(HID_USAGE_KEY_LEFT_SHIFT, MOD_LSHIFT, '\0'));

  // Test keys with modifiers pressed.
  // Test Shift-N.
  keypresses = {HID_USAGE_KEY_LEFT_SHIFT, HID_USAGE_KEY_N};
  helper.WriteReportBuf(keypresses);
  ASSERT_NO_FAILURES(expect_keypress(HID_USAGE_KEY_N, MOD_LSHIFT, 'N'));

  // Test Shift-8.
  keypresses = {HID_USAGE_KEY_LEFT_SHIFT, HID_USAGE_KEY_8};
  helper.WriteReportBuf(keypresses);
  ASSERT_NO_FAILURES(expect_keypress(HID_USAGE_KEY_8, MOD_LSHIFT, '*'));

  // Test Ctrl modifier.
  keypresses = {HID_USAGE_KEY_LEFT_CTRL};
  helper.WriteReportBuf(keypresses);
  ASSERT_NO_FAILURES(expect_keypress(HID_USAGE_KEY_LEFT_CTRL, MOD_LCTRL, '\0'));

  // Test Ctrl-J.
  keypresses = {HID_USAGE_KEY_J, HID_USAGE_KEY_LEFT_CTRL};
  helper.WriteReportBuf(keypresses);
  ASSERT_NO_FAILURES(expect_keypress(HID_USAGE_KEY_J, MOD_LCTRL, 10));

  // Test Ctrl-1.  The Ctrl modifier should be ignored in this case so
  // that we just get '1'.
  keypresses = {HID_USAGE_KEY_1, HID_USAGE_KEY_LEFT_CTRL};
  helper.WriteReportBuf(keypresses);
  ASSERT_NO_FAILURES(expect_keypress(HID_USAGE_KEY_1, MOD_LCTRL, '1'));

  // Try Shift and Ctrl together.
  keypresses = {HID_USAGE_KEY_LEFT_SHIFT, HID_USAGE_KEY_LEFT_CTRL};
  helper.WriteReportBuf(keypresses);
  ASSERT_NO_FAILURES(expect_keypress(HID_USAGE_KEY_LEFT_SHIFT, MOD_LSHIFT | MOD_LCTRL, '\0'));

  // Test Shift-Ctrl-J.  This should be equivalent to Ctrl-J.
  keypresses = {HID_USAGE_KEY_LEFT_SHIFT, HID_USAGE_KEY_LEFT_CTRL, HID_USAGE_KEY_J};
  helper.WriteReportBuf(keypresses);
  ASSERT_NO_FAILURES(expect_keypress(HID_USAGE_KEY_J, MOD_LSHIFT | MOD_LCTRL, 10));

  // Test Shift-Ctrl-1.  This should be equivalent to Shift-1.
  keypresses = {HID_USAGE_KEY_LEFT_SHIFT, HID_USAGE_KEY_LEFT_CTRL, HID_USAGE_KEY_1};
  helper.WriteReportBuf(keypresses);
  ASSERT_NO_FAILURES(expect_keypress(HID_USAGE_KEY_1, MOD_LSHIFT | MOD_LCTRL, '!'));
}

TEST(GfxConsoleKeyboardTests, CapsLock) {
  async::Loop loop = async::Loop(&kAsyncLoopConfigNeverAttachToThread);
  KeyboardInputHelper helper(loop.dispatcher());
  std::vector<uint32_t> keypresses;

  keypresses = {HID_USAGE_KEY_CAPSLOCK};
  helper.WriteReportBuf(keypresses);
  ASSERT_NO_FAILURES(expect_keypress(HID_USAGE_KEY_CAPSLOCK, MOD_CAPSLOCK, '\0'));

  // Test that letters are capitalized.
  keypresses = {HID_USAGE_KEY_M};
  helper.WriteReportBuf(keypresses);
  ASSERT_NO_FAILURES(expect_keypress(HID_USAGE_KEY_M, MOD_CAPSLOCK, 'M'));

  // Non-letter characters should not be affected.  This isn't Shift Lock.
  keypresses = {HID_USAGE_KEY_1};
  helper.WriteReportBuf(keypresses);
  ASSERT_NO_FAILURES(expect_keypress(HID_USAGE_KEY_1, MOD_CAPSLOCK, '1'));

  // Test unsetting Caps Lock.
  keypresses = {HID_USAGE_KEY_CAPSLOCK};
  helper.WriteReportBuf(keypresses);
  ASSERT_NO_FAILURES(expect_keypress(HID_USAGE_KEY_CAPSLOCK, 0, '\0'));

  keypresses = {HID_USAGE_KEY_M};
  helper.WriteReportBuf(keypresses);
  ASSERT_NO_FAILURES(expect_keypress(HID_USAGE_KEY_M, 0, 'm'));
}

TEST(GfxConsoleKeyboardTests, CapsLockWithShift) {
  async::Loop loop = async::Loop(&kAsyncLoopConfigNeverAttachToThread);
  KeyboardInputHelper helper(loop.dispatcher());
  std::vector<uint32_t> keypresses;

  keypresses = {HID_USAGE_KEY_LEFT_SHIFT};
  helper.WriteReportBuf(keypresses);
  ASSERT_NO_FAILURES(expect_keypress(HID_USAGE_KEY_LEFT_SHIFT, MOD_LSHIFT, '\0'));

  keypresses = {HID_USAGE_KEY_LEFT_SHIFT, HID_USAGE_KEY_CAPSLOCK};
  helper.WriteReportBuf(keypresses);
  ASSERT_NO_FAILURES(expect_keypress(HID_USAGE_KEY_CAPSLOCK, MOD_LSHIFT | MOD_CAPSLOCK, '\0'));

  // Shift should undo the effect of Caps Lock for letters.
  keypresses = {HID_USAGE_KEY_LEFT_SHIFT, HID_USAGE_KEY_M};
  helper.WriteReportBuf(keypresses);
  ASSERT_NO_FAILURES(expect_keypress(HID_USAGE_KEY_M, MOD_LSHIFT | MOD_CAPSLOCK, 'm'));

  keypresses = {HID_USAGE_KEY_LEFT_SHIFT, HID_USAGE_KEY_1};
  helper.WriteReportBuf(keypresses);
  ASSERT_NO_FAILURES(expect_keypress(HID_USAGE_KEY_1, MOD_LSHIFT | MOD_CAPSLOCK, '!'));

  // Test unsetting Caps Lock.
  keypresses = {HID_USAGE_KEY_LEFT_SHIFT, HID_USAGE_KEY_CAPSLOCK};
  helper.WriteReportBuf(keypresses);
  ASSERT_NO_FAILURES(expect_keypress(HID_USAGE_KEY_CAPSLOCK, MOD_LSHIFT, '\0'));

  keypresses = {HID_USAGE_KEY_LEFT_SHIFT, HID_USAGE_KEY_M};
  helper.WriteReportBuf(keypresses);
  ASSERT_NO_FAILURES(expect_keypress(HID_USAGE_KEY_M, MOD_LSHIFT, 'M'));
}

}  // namespace
