// Copyright 2018 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/drivers/virtio/input_kbd.h"

#include <lib/ddk/debug.h>
#include <zircon/status.h>

#include <fbl/algorithm.h>

#include "src/devices/bus/lib/virtio/trace.h"

#define LOCAL_TRACE 0

namespace virtio {

namespace {

// These are Linux input event codes:
// https://github.com/torvalds/linux/blob/HEAD/include/uapi/linux/input-event-codes.h
constexpr std::optional<fuchsia_input::wire::Key> kEventCodeMap[] = {
    /* 0x00 */ std::nullopt,
    /* 0x01 */ fuchsia_input::wire::Key::kEscape,
    /* 0x02 */ fuchsia_input::wire::Key::kKey1,
    /* 0x03 */ fuchsia_input::wire::Key::kKey2,
    /* 0x04 */ fuchsia_input::wire::Key::kKey3,
    /* 0x05 */ fuchsia_input::wire::Key::kKey4,
    /* 0x06 */ fuchsia_input::wire::Key::kKey5,
    /* 0x07 */ fuchsia_input::wire::Key::kKey6,
    /* 0x08 */ fuchsia_input::wire::Key::kKey7,
    /* 0x09 */ fuchsia_input::wire::Key::kKey8,
    /* 0x0a */ fuchsia_input::wire::Key::kKey9,
    /* 0x0b */ fuchsia_input::wire::Key::kKey0,
    /* 0x0c */ fuchsia_input::wire::Key::kMinus,
    /* 0x0d */ fuchsia_input::wire::Key::kEquals,
    /* 0x0e */ fuchsia_input::wire::Key::kBackspace,
    /* 0x0f */ fuchsia_input::wire::Key::kTab,
    /* 0x10 */ fuchsia_input::wire::Key::kQ,
    /* 0x11 */ fuchsia_input::wire::Key::kW,
    /* 0x12 */ fuchsia_input::wire::Key::kE,
    /* 0x13 */ fuchsia_input::wire::Key::kR,
    /* 0x14 */ fuchsia_input::wire::Key::kT,
    /* 0x15 */ fuchsia_input::wire::Key::kY,
    /* 0x16 */ fuchsia_input::wire::Key::kU,
    /* 0x17 */ fuchsia_input::wire::Key::kI,
    /* 0x18 */ fuchsia_input::wire::Key::kO,
    /* 0x19 */ fuchsia_input::wire::Key::kP,
    /* 0x1a */ fuchsia_input::wire::Key::kLeftBrace,
    /* 0x1b */ fuchsia_input::wire::Key::kRightBrace,
    /* 0x1c */ fuchsia_input::wire::Key::kEnter,
    /* 0x1d */ fuchsia_input::wire::Key::kLeftCtrl,
    /* 0x1e */ fuchsia_input::wire::Key::kA,
    /* 0x1f */ fuchsia_input::wire::Key::kS,
    /* 0x20 */ fuchsia_input::wire::Key::kD,
    /* 0x21 */ fuchsia_input::wire::Key::kF,
    /* 0x22 */ fuchsia_input::wire::Key::kG,
    /* 0x23 */ fuchsia_input::wire::Key::kH,
    /* 0x24 */ fuchsia_input::wire::Key::kJ,
    /* 0x25 */ fuchsia_input::wire::Key::kK,
    /* 0x26 */ fuchsia_input::wire::Key::kL,
    /* 0x27 */ fuchsia_input::wire::Key::kSemicolon,
    /* 0x28 */ fuchsia_input::wire::Key::kApostrophe,
    /* 0x29 */ fuchsia_input::wire::Key::kGraveAccent,
    /* 0x2a */ fuchsia_input::wire::Key::kLeftShift,
    /* 0x2b */ fuchsia_input::wire::Key::kBackslash,
    /* 0x2c */ fuchsia_input::wire::Key::kZ,
    /* 0x2d */ fuchsia_input::wire::Key::kX,
    /* 0x2e */ fuchsia_input::wire::Key::kC,
    /* 0x2f */ fuchsia_input::wire::Key::kV,
    /* 0x30 */ fuchsia_input::wire::Key::kB,
    /* 0x31 */ fuchsia_input::wire::Key::kN,
    /* 0x32 */ fuchsia_input::wire::Key::kM,
    /* 0x33 */ fuchsia_input::wire::Key::kComma,
    /* 0x34 */ fuchsia_input::wire::Key::kDot,
    /* 0x35 */ fuchsia_input::wire::Key::kSlash,
    /* 0x36 */ fuchsia_input::wire::Key::kRightShift,
    /* 0x37 */ fuchsia_input::wire::Key::kKeypadAsterisk,
    /* 0x38 */ fuchsia_input::wire::Key::kLeftAlt,
    /* 0x39 */ fuchsia_input::wire::Key::kSpace,
    /* 0x3a */ fuchsia_input::wire::Key::kCapsLock,
    /* 0x3b */ fuchsia_input::wire::Key::kF1,
    /* 0x3c */ fuchsia_input::wire::Key::kF2,
    /* 0x3d */ fuchsia_input::wire::Key::kF3,
    /* 0x3e */ fuchsia_input::wire::Key::kF4,
    /* 0x3f */ fuchsia_input::wire::Key::kF5,
    /* 0x40 */ fuchsia_input::wire::Key::kF6,
    /* 0x41 */ fuchsia_input::wire::Key::kF7,
    /* 0x42 */ fuchsia_input::wire::Key::kF8,
    /* 0x43 */ fuchsia_input::wire::Key::kF9,
    /* 0x44 */ fuchsia_input::wire::Key::kF10,
    /* 0x45 */ fuchsia_input::wire::Key::kNumLock,
    /* 0x46 */ fuchsia_input::wire::Key::kScrollLock,
    /* 0x47 */ fuchsia_input::wire::Key::kKeypad7,
    /* 0x48 */ fuchsia_input::wire::Key::kKeypad8,
    /* 0x49 */ fuchsia_input::wire::Key::kKeypad9,
    /* 0x4a */ fuchsia_input::wire::Key::kKeypadMinus,
    /* 0x4b */ fuchsia_input::wire::Key::kKeypad4,
    /* 0x4c */ fuchsia_input::wire::Key::kKeypad5,
    /* 0x4d */ fuchsia_input::wire::Key::kKeypad6,
    /* 0x4e */ fuchsia_input::wire::Key::kKeypadPlus,
    /* 0x4f */ fuchsia_input::wire::Key::kKeypad1,
    /* 0x50 */ fuchsia_input::wire::Key::kKeypad2,
    /* 0x51 */ fuchsia_input::wire::Key::kKeypad3,
    /* 0x52 */ fuchsia_input::wire::Key::kKeypad0,
    /* 0x53 */ fuchsia_input::wire::Key::kKeypadDot,
    /* 0x54 */ std::nullopt,
    /* 0x55 */ std::nullopt,
    /* 0x56 */ std::nullopt,
    /* 0x57 */ std::nullopt,
    /* 0x58 */ std::nullopt,
    /* 0x59 */ std::nullopt,
    /* 0x5a */ std::nullopt,
    /* 0x5b */ std::nullopt,
    /* 0x5c */ std::nullopt,
    /* 0x5d */ std::nullopt,
    /* 0x5e */ std::nullopt,
    /* 0x5f */ std::nullopt,
    /* 0x60 */ std::nullopt,
    /* 0x61 */ fuchsia_input::wire::Key::kRightCtrl,
    /* 0x62 */ std::nullopt,
    /* 0x63 */ std::nullopt,
    /* 0x64 */ fuchsia_input::wire::Key::kRightAlt,
    /* 0x65 */ std::nullopt,
    /* 0x66 */ std::nullopt,
    /* 0x67 */ fuchsia_input::wire::Key::kUp,
    /* 0x68 */ std::nullopt,
    /* 0x69 */ fuchsia_input::wire::Key::kLeft,
    /* 0x6a */ fuchsia_input::wire::Key::kRight,
    /* 0x6b */ std::nullopt,
    /* 0x6c */ fuchsia_input::wire::Key::kDown,
    /* 0x6d */ fuchsia_input::wire::Key::kPageDown,
    /* 0x6e */ fuchsia_input::wire::Key::kInsert,
    /* 0x6f */ fuchsia_input::wire::Key::kDelete,
    /* 0x70 */ std::nullopt,
    /* 0x71 */ std::nullopt,
    /* 0x72 */ std::nullopt,
    /* 0x73 */ std::nullopt,
    /* 0x74 */ std::nullopt,
    /* 0x75 */ std::nullopt,
    /* 0x76 */ std::nullopt,
    /* 0x77 */ fuchsia_input::wire::Key::kPause,
    /* 0x78 */ std::nullopt,
    /* 0x79 */ std::nullopt,
    /* 0x7a */ std::nullopt,
    /* 0x7b */ std::nullopt,
    /* 0x7c */ std::nullopt,
    /* 0x7d */ fuchsia_input::wire::Key::kLeftMeta,
    /* 0x7e */ fuchsia_input::wire::Key::kRightMeta,
};

constexpr size_t kKeyCount = []() {
  size_t count = 0;
  for (const auto& k : kEventCodeMap) {
    if (k.has_value()) {
      count++;
    }
  }
  return count;
}();

constexpr std::array<fuchsia_input::wire::Key, kKeyCount> kKeys = []() {
  std::array<fuchsia_input::wire::Key, kKeyCount> keys;
  size_t i = 0;
  for (const auto& k : kEventCodeMap) {
    if (k.has_value()) {
      keys[i++] = k.value();
    }
  }
  return keys;
}();

}  // namespace

void KeyboardReport::ToFidlInputReport(
    fidl::WireTableBuilder<::fuchsia_input_report::wire::InputReport>& input_report,
    fidl::AnyArena& allocator) const {
  fidl::VectorView<fuchsia_input::wire::Key> keys3(allocator, kMaxKeys);
  size_t idx = 0;
  for (const auto& key : usage) {
    if (!key.has_value()) {
      break;
    }
    keys3[idx++] = *key;
  }
  keys3.set_size(idx);

  auto keyboard_report =
      fuchsia_input_report::wire::KeyboardInputReport::Builder(allocator).pressed_keys3(keys3);
  input_report.event_time(event_time.get()).keyboard(keyboard_report.Build());
}

fuchsia_input_report::wire::DeviceDescriptor HidKeyboard::GetDescriptor(fidl::AnyArena& allocator) {
  auto device_info = fuchsia_input_report::wire::DeviceInformation::Builder(allocator);
  device_info.vendor_id(static_cast<uint32_t>(fuchsia_input_report::wire::VendorId::kGoogle));
  device_info.product_id(
      static_cast<uint32_t>(fuchsia_input_report::wire::VendorGoogleProductId::kVirtioKeyboard));

  const auto input =
      fuchsia_input_report::wire::KeyboardInputDescriptor::Builder(allocator).keys3(kKeys).Build();

  const auto output =
      fuchsia_input_report::wire::KeyboardOutputDescriptor::Builder(allocator)
          .leds({allocator,
                 {fuchsia_input_report::LedType::kNumLock, fuchsia_input_report::LedType::kCapsLock,
                  fuchsia_input_report::LedType::kScrollLock,
                  fuchsia_input_report::LedType::kCompose, fuchsia_input_report::LedType::kKana}})
          .Build();

  const auto keyboard = fuchsia_input_report::wire::KeyboardDescriptor::Builder(allocator)
                            .input(input)
                            .output(output)
                            .Build();

  return fuchsia_input_report::wire::DeviceDescriptor::Builder(allocator)
      .device_information(device_info.Build())
      .keyboard(keyboard)
      .Build();
}

void HidKeyboard::AddKeypressToReport(uint16_t event_code) {
  auto hid_code = kEventCodeMap[event_code];
  if (!hid_code.has_value()) {
    return;
  }
  for (auto& usage : report_.usage) {
    if (!usage.has_value()) {
      usage = hid_code;
      return;
    }
    if (*usage == *hid_code) {
      // The key already exists in the report so we ignore it.
      return;
    }
  }

  // There's no free slot in the report.
  // TODO: Record a rollover status.
}

void HidKeyboard::RemoveKeypressFromReport(uint16_t event_code) {
  auto hid_code = kEventCodeMap[event_code];
  if (!hid_code.has_value()) {
    return;
  }
  int id = -1;
  for (int i = 0; i != kMaxKeys; ++i) {
    if (report_.usage[i].has_value() && *report_.usage[i] == *hid_code) {
      id = i;
      break;
    }
  }

  if (id == -1) {
    // They key is not in the report so we ignore it.
    return;
  }

  for (size_t i = id; i != kMaxKeys - 1; ++i) {
    report_.usage[i] = report_.usage[i + 1];
  }
  report_.usage[kMaxKeys - 1] = std::nullopt;
}

void HidKeyboard::ReceiveEvent(virtio_input_event_t* event) {
  if (event->type != VIRTIO_INPUT_EV_KEY) {
    zxlogf(TRACE, "Unsupported event type %d\n", event->type);
    return;
  }
  if (event->code == 0 || event->code >= std::size(kEventCodeMap)) {
    zxlogf(TRACE, "Unknown key %d\n", event->code);
    return;
  }
  if (event->value == VIRTIO_INPUT_EV_KEY_PRESSED) {
    AddKeypressToReport(event->code);
  } else if (event->value == VIRTIO_INPUT_EV_KEY_RELEASED) {
    RemoveKeypressFromReport(event->code);
  }
}

}  // namespace virtio
