// Copyright 2019 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 "src/ui/input/lib/hid-input-report/keyboard.h"

#include <fuchsia/input/cpp/fidl.h>
#include <fuchsia/ui/input2/cpp/fidl.h>

#include <variant>

#include <fbl/auto_call.h>
#include <hid/boot.h>
#include <hid/usages.h>
#include <zxtest/zxtest.h>

#include "src/ui/input/lib/hid-input-report/device.h"
#include "src/ui/input/lib/hid-input-report/test/test.h"
#include "src/ui/lib/key_util/key_util.h"

namespace fuchsia_input_report = ::llcpp::fuchsia::input::report;

namespace {

// This is a keyboard with multiple keys of the same usage.
const uint8_t double_keys_keyboard[] = {
    0x05, 0x01,  // Usage Page (Generic Desktop Ctrls)
    0x09, 0x06,  // Usage (Keyboard)
    0xA1, 0x01,  // Collection (Application)
    0x05, 0x07,  //   Usage Page (Kbrd/Keypad)
    0x19, 0xE0,  //   Usage Minimum (0xE0)
    0x29, 0xE7,  //   Usage Maximum (0xE7)
    0x15, 0x00,  //   Logical Minimum (0)
    0x25, 0x01,  //   Logical Maximum (1)
    0x75, 0x01,  //   Report Size (1)
    0x95, 0x08,  //   Report Count (8)
    0x81, 0x02,  //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x19, 0xE0,  //   Usage Minimum (0xE0)
    0x29, 0xE7,  //   Usage Maximum (0xE7)
    0x15, 0x00,  //   Logical Minimum (0)
    0x25, 0x01,  //   Logical Maximum (1)
    0x75, 0x01,  //   Report Size (1)
    0x95, 0x08,  //   Report Count (8)
    0x81, 0x02,  //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x95, 0x02,  //   Report Count (2)
    0x75, 0x08,  //   Report Size (8)
    0x15, 0x00,  //   Logical Minimum (0)
    0x25, 0x65,  //   Logical Maximum (101)
    0x05, 0x07,  //   Usage Page (Kbrd/Keypad)
    0x19, 0x00,  //   Usage Minimum (0x00)
    0x29, 0x65,  //   Usage Maximum (0x65)
    0x81, 0x00,  //   Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0xC0,        // End Collection
};

// This keyboard declares keys up to 0xFF (256 keys).
const uint8_t full_keys_keyboard[] = {
    0x05, 0x01,        // Usage Page (Generic Desktop Ctrls)
    0x09, 0x06,        // Usage (Keyboard)
    0xA1, 0x01,        // Collection (Application)
    0x05, 0x07,        //   Usage Page (Kbrd/Keypad)
    0x19, 0xE0,        //   Usage Minimum (0xE0)
    0x29, 0xE7,        //   Usage Maximum (0xE7)
    0x15, 0x00,        //   Logical Minimum (0)
    0x25, 0x01,        //   Logical Maximum (1)
    0x75, 0x01,        //   Report Size (1)
    0x95, 0x08,        //   Report Count (8)
    0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x95, 0x01,        //   Report Count (1)
    0x75, 0x08,        //   Report Size (8)
    0x81, 0x01,        //   Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x95, 0x05,        //   Report Count (5)
    0x75, 0x01,        //   Report Size (1)
    0x05, 0x08,        //   Usage Page (LEDs)
    0x19, 0x01,        //   Usage Minimum (Num Lock)
    0x29, 0x05,        //   Usage Maximum (Kana)
    0x91, 0x02,        //   Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null
                       //   Position,Non-volatile)
    0x95, 0x01,        //   Report Count (1)
    0x75, 0x03,        //   Report Size (3)
    0x91, 0x01,        //   Output (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null
                       //   Position,Non-volatile)
    0x95, 0x06,        //   Report Count (6)
    0x75, 0x08,        //   Report Size (8)
    0x15, 0x00,        //   Logical Minimum (0)
    0x26, 0xFF, 0x00,  //   Logical Maximum (255)
    0x05, 0x07,        //   Usage Page (Kbrd/Keypad)
    0x19, 0x00,        //   Usage Minimum (0x00)
    0x2A, 0xFF, 0x00,  //   Usage Maximum (0xFF)
    0x81, 0x00,        //   Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0xC0,              // End Collection
};

}  // namespace

// Each test parses the report descriptor for the mouse and then sends one
// report to ensure that it has been parsed correctly.
TEST(KeyboardTest, BootKeyboard) {
  size_t descriptor_size;
  const uint8_t* boot_keyboard_descriptor = get_boot_kbd_report_desc(&descriptor_size);

  hid::DeviceDescriptor* dev_desc = nullptr;
  auto parse_res = hid::ParseReportDescriptor(boot_keyboard_descriptor, descriptor_size, &dev_desc);
  ASSERT_EQ(hid::ParseResult::kParseOk, parse_res);
  fbl::AutoCall free_descriptor([dev_desc]() { hid::FreeDeviceDescriptor(dev_desc); });

  hid_input_report::Keyboard keyboard;

  EXPECT_EQ(hid_input_report::ParseResult::kOk,
            keyboard.ParseReportDescriptor(dev_desc->report[0]));

  hid_input_report::TestDescriptorAllocator descriptor_allocator;
  auto descriptor_builder = fuchsia_input_report::DeviceDescriptor::Builder(
      descriptor_allocator.make<fuchsia_input_report::DeviceDescriptor::Frame>());
  EXPECT_EQ(hid_input_report::ParseResult::kOk,
            keyboard.CreateDescriptor(&descriptor_allocator, &descriptor_builder));
  fuchsia_input_report::DeviceDescriptor descriptor = descriptor_builder.build();
  EXPECT_TRUE(descriptor.has_keyboard());
  EXPECT_TRUE(descriptor.keyboard().has_input());
  EXPECT_TRUE(descriptor.keyboard().input().has_keys());
  EXPECT_EQ(105, descriptor.keyboard().input().keys().count());
  EXPECT_EQ(105, descriptor.keyboard().input().keys3().count());

  // Test a report parses correctly.
  hid_boot_kbd_report kbd_report = {};
  kbd_report.modifier = HID_KBD_MODIFIER_LEFT_SHIFT | HID_KBD_MODIFIER_RIGHT_GUI;
  kbd_report.usage[0] = HID_USAGE_KEY_A;
  kbd_report.usage[1] = HID_USAGE_KEY_NON_US_BACKSLASH;
  kbd_report.usage[2] = HID_USAGE_KEY_UP;

  hid_input_report::TestReportAllocator report_allocator;
  auto report_builder = fuchsia_input_report::InputReport::Builder(
      report_allocator.make<fuchsia_input_report::InputReport::Frame>());
  EXPECT_EQ(hid_input_report::ParseResult::kOk,
            keyboard.ParseInputReport(reinterpret_cast<uint8_t*>(&kbd_report), sizeof(kbd_report),
                                      &report_allocator, &report_builder));

  fuchsia_input_report::InputReport input_report = report_builder.build();
  ASSERT_TRUE(input_report.has_keyboard());

  ASSERT_EQ(input_report.keyboard().pressed_keys().count(), 5U);
  EXPECT_EQ(input_report.keyboard().pressed_keys()[0], llcpp::fuchsia::ui::input2::Key::LEFT_SHIFT);
  EXPECT_EQ(input_report.keyboard().pressed_keys()[1], llcpp::fuchsia::ui::input2::Key::RIGHT_META);
  EXPECT_EQ(input_report.keyboard().pressed_keys()[2], llcpp::fuchsia::ui::input2::Key::A);
  EXPECT_EQ(input_report.keyboard().pressed_keys()[3],
            llcpp::fuchsia::ui::input2::Key::NON_US_BACKSLASH);
  EXPECT_EQ(input_report.keyboard().pressed_keys()[4], llcpp::fuchsia::ui::input2::Key::UP);

  EXPECT_EQ(input_report.keyboard().pressed_keys3()[0], llcpp::fuchsia::input::Key::LEFT_SHIFT);
  EXPECT_EQ(input_report.keyboard().pressed_keys3()[1], llcpp::fuchsia::input::Key::RIGHT_META);
  EXPECT_EQ(input_report.keyboard().pressed_keys3()[2], llcpp::fuchsia::input::Key::A);
  EXPECT_EQ(input_report.keyboard().pressed_keys3()[3],
            llcpp::fuchsia::input::Key::NON_US_BACKSLASH);
  EXPECT_EQ(input_report.keyboard().pressed_keys3()[4], llcpp::fuchsia::input::Key::UP);
}

TEST(KeyboardTest, OutputDescriptor) {
  size_t descriptor_size;
  const uint8_t* boot_keyboard_descriptor = get_boot_kbd_report_desc(&descriptor_size);

  hid::DeviceDescriptor* dev_desc = nullptr;
  auto parse_res = hid::ParseReportDescriptor(boot_keyboard_descriptor, descriptor_size, &dev_desc);
  ASSERT_EQ(hid::ParseResult::kParseOk, parse_res);
  fbl::AutoCall free_descriptor([dev_desc]() { hid::FreeDeviceDescriptor(dev_desc); });

  hid_input_report::Keyboard keyboard;

  EXPECT_EQ(hid_input_report::ParseResult::kOk,
            keyboard.ParseReportDescriptor(dev_desc->report[0]));

  hid_input_report::TestDescriptorAllocator descriptor_allocator;
  auto descriptor_builder = fuchsia_input_report::DeviceDescriptor::Builder(
      descriptor_allocator.make<fuchsia_input_report::DeviceDescriptor::Frame>());
  EXPECT_EQ(hid_input_report::ParseResult::kOk,
            keyboard.CreateDescriptor(&descriptor_allocator, &descriptor_builder));
  fuchsia_input_report::DeviceDescriptor descriptor = descriptor_builder.build();

  ASSERT_EQ(descriptor.keyboard().output().leds().count(), 5);
  EXPECT_EQ(descriptor.keyboard().output().leds()[0],
            hid_input_report::fuchsia_input_report::LedType::NUM_LOCK);
  EXPECT_EQ(descriptor.keyboard().output().leds()[1],
            hid_input_report::fuchsia_input_report::LedType::CAPS_LOCK);
  EXPECT_EQ(descriptor.keyboard().output().leds()[2],
            hid_input_report::fuchsia_input_report::LedType::SCROLL_LOCK);
  EXPECT_EQ(descriptor.keyboard().output().leds()[3],
            hid_input_report::fuchsia_input_report::LedType::COMPOSE);
  EXPECT_EQ(descriptor.keyboard().output().leds()[4],
            hid_input_report::fuchsia_input_report::LedType::KANA);
}

// This test double checks that we don't double count keys that are included twice.
TEST(KeyboardTest, DoubleCountingKeys) {
  hid::DeviceDescriptor* dev_desc = nullptr;
  auto parse_res =
      hid::ParseReportDescriptor(double_keys_keyboard, sizeof(double_keys_keyboard), &dev_desc);
  ASSERT_EQ(hid::ParseResult::kParseOk, parse_res);
  fbl::AutoCall free_descriptor([dev_desc]() { hid::FreeDeviceDescriptor(dev_desc); });

  // Test the descriptor parses correctly.
  hid_input_report::Keyboard keyboard;

  EXPECT_EQ(hid_input_report::ParseResult::kOk,
            keyboard.ParseReportDescriptor(dev_desc->report[0]));

  hid_input_report::TestDescriptorAllocator descriptor_allocator;
  auto descriptor_builder = fuchsia_input_report::DeviceDescriptor::Builder(
      descriptor_allocator.make<fuchsia_input_report::DeviceDescriptor::Frame>());
  EXPECT_EQ(hid_input_report::ParseResult::kOk,
            keyboard.CreateDescriptor(&descriptor_allocator, &descriptor_builder));
  fuchsia_input_report::DeviceDescriptor descriptor = descriptor_builder.build();

  EXPECT_EQ(descriptor.keyboard().input().keys().count(), 105U);
}

TEST(KeyboardTest, BootKeyboardOutputReport) {
  size_t descriptor_size;
  const uint8_t* boot_keyboard_descriptor = get_boot_kbd_report_desc(&descriptor_size);
  hid::DeviceDescriptor* dev_desc = nullptr;
  auto parse_res = hid::ParseReportDescriptor(boot_keyboard_descriptor, descriptor_size, &dev_desc);
  ASSERT_EQ(hid::ParseResult::kParseOk, parse_res);
  fbl::AutoCall free_descriptor([dev_desc]() { hid::FreeDeviceDescriptor(dev_desc); });

  hid_input_report::Keyboard keyboard;
  EXPECT_EQ(hid_input_report::ParseResult::kOk,
            keyboard.ParseReportDescriptor(dev_desc->report[0]));
  std::array<hid_input_report::fuchsia_input_report::LedType, 2> led_array;
  led_array[0] = hid_input_report::fuchsia_input_report::LedType::NUM_LOCK;
  led_array[1] = hid_input_report::fuchsia_input_report::LedType::SCROLL_LOCK;
  // Build the FIDL table.
  auto led_view = fidl::unowned_vec(led_array);
  hid_input_report::fuchsia_input_report::KeyboardOutputReport::UnownedBuilder keyboard_builder;
  keyboard_builder.set_enabled_leds(fidl::unowned_ptr(&led_view));
  hid_input_report::fuchsia_input_report::KeyboardOutputReport fidl_keyboard =
      keyboard_builder.build();
  hid_input_report::fuchsia_input_report::OutputReport::UnownedBuilder builder;
  builder.set_keyboard(fidl::unowned_ptr(&fidl_keyboard));
  hid_input_report::fuchsia_input_report::OutputReport fidl_report = builder.build();
  uint8_t report_data;
  size_t out_report_size;
  auto result =
      keyboard.SetOutputReport(&fidl_report, &report_data, sizeof(report_data), &out_report_size);
  ASSERT_EQ(result, hid_input_report::ParseResult::kOk);
  ASSERT_EQ(1, out_report_size);
  ASSERT_EQ(0b101, report_data);
}

TEST(KeyboardTest, FullKeysKeyboard) {
  hid::DeviceDescriptor* dev_desc = nullptr;
  auto parse_res =
      hid::ParseReportDescriptor(full_keys_keyboard, sizeof(full_keys_keyboard), &dev_desc);
  ASSERT_EQ(hid::ParseResult::kParseOk, parse_res);
  fbl::AutoCall free_descriptor([dev_desc]() { hid::FreeDeviceDescriptor(dev_desc); });

  hid_input_report::Keyboard keyboard;

  EXPECT_EQ(hid_input_report::ParseResult::kOk,
            keyboard.ParseReportDescriptor(dev_desc->report[0]));

  hid_input_report::TestDescriptorAllocator descriptor_allocator;
  auto descriptor_builder = fuchsia_input_report::DeviceDescriptor::Builder(
      descriptor_allocator.make<fuchsia_input_report::DeviceDescriptor::Frame>());
  EXPECT_EQ(hid_input_report::ParseResult::kOk,
            keyboard.CreateDescriptor(&descriptor_allocator, &descriptor_builder));
  fuchsia_input_report::DeviceDescriptor descriptor = descriptor_builder.build();

  EXPECT_EQ(descriptor.keyboard().input().keys().count(), 107);
  EXPECT_EQ(descriptor.keyboard().input().keys3().count(), 107);

  // Test a report parses correctly.
  hid_boot_kbd_report kbd_report = {};
  kbd_report.modifier = HID_KBD_MODIFIER_LEFT_SHIFT | HID_KBD_MODIFIER_RIGHT_GUI;
  kbd_report.usage[0] = HID_USAGE_KEY_A;
  kbd_report.usage[1] = HID_USAGE_KEY_NON_US_BACKSLASH;
  kbd_report.usage[2] = HID_USAGE_KEY_UP;

  hid_input_report::TestReportAllocator report_allocator;
  auto report_builder = fuchsia_input_report::InputReport::Builder(
      report_allocator.make<fuchsia_input_report::InputReport::Frame>());
  EXPECT_EQ(hid_input_report::ParseResult::kOk,
            keyboard.ParseInputReport(reinterpret_cast<uint8_t*>(&kbd_report), sizeof(kbd_report),
                                      &report_allocator, &report_builder));
  fuchsia_input_report::InputReport input_report = report_builder.build();

  ASSERT_EQ(input_report.keyboard().pressed_keys().count(), 5U);
  EXPECT_EQ(input_report.keyboard().pressed_keys()[0], llcpp::fuchsia::ui::input2::Key::LEFT_SHIFT);
  EXPECT_EQ(input_report.keyboard().pressed_keys()[1], llcpp::fuchsia::ui::input2::Key::RIGHT_META);
  EXPECT_EQ(input_report.keyboard().pressed_keys()[2], llcpp::fuchsia::ui::input2::Key::A);
  EXPECT_EQ(input_report.keyboard().pressed_keys()[3],
            llcpp::fuchsia::ui::input2::Key::NON_US_BACKSLASH);
  EXPECT_EQ(input_report.keyboard().pressed_keys()[4], llcpp::fuchsia::ui::input2::Key::UP);

  ASSERT_EQ(input_report.keyboard().pressed_keys3().count(), 5U);
  EXPECT_EQ(input_report.keyboard().pressed_keys3()[0], llcpp::fuchsia::input::Key::LEFT_SHIFT);
  EXPECT_EQ(input_report.keyboard().pressed_keys3()[1], llcpp::fuchsia::input::Key::RIGHT_META);
  EXPECT_EQ(input_report.keyboard().pressed_keys3()[2], llcpp::fuchsia::input::Key::A);
  EXPECT_EQ(input_report.keyboard().pressed_keys3()[3],
            llcpp::fuchsia::input::Key::NON_US_BACKSLASH);
  EXPECT_EQ(input_report.keyboard().pressed_keys3()[4], llcpp::fuchsia::input::Key::UP);
}

TEST(KeyboardTest, DeviceType) {
  hid_input_report::Keyboard keyboard;
  ASSERT_EQ(hid_input_report::DeviceType::kKeyboard, keyboard.GetDeviceType());
}
