// 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 = ::llcpp::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) {
    auto report_builder = fuchsia_input_report::InputReport::Builder(
        std::make_unique<fuchsia_input_report::InputReport::Frame>());
    auto keyboard_builder = fuchsia_input_report::KeyboardInputReport::Builder(
        std::make_unique<fuchsia_input_report::KeyboardInputReport::Frame>());

    std::vector<llcpp::fuchsia::ui::input2::Key> fidl_keys;
    for (auto& key : keys) {
      auto fidl_key =
          *key_util::hid_key_to_fuchsia_key(hid::USAGE(hid::usage::Page::kKeyboardKeypad, key));
      fidl_keys.push_back(static_cast<::llcpp::fuchsia::ui::input2::Key>(fidl_key));
    }
    keyboard_builder.set_pressed_keys(
        std::make_unique<fidl::VectorView<::llcpp::fuchsia::ui::input2::Key>>(
            fidl::unowned_ptr(fidl_keys.data()), fidl_keys.size()));
    report_builder.set_keyboard(
        std::make_unique<fuchsia_input_report::KeyboardInputReport>(keyboard_builder.build()));
    keyboard_.ProcessInput(report_builder.build());
  }

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