// 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 <fcntl.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <hid/hid.h>
#include <hid/usages.h>
#include <lib/fzl/fdio.h>
#include <zircon/input/c/fidl.h>
#include <zircon/syscalls.h>

#include <port/port.h>

#include <utility>

#include "keyboard.h"

#define LOW_REPEAT_KEY_FREQ 250000000
#define HIGH_REPEAT_KEY_FREQ 50000000

static int modifiers_from_keycode(uint8_t keycode) {
    switch (keycode) {
    case HID_USAGE_KEY_LEFT_SHIFT:
        return MOD_LSHIFT;
    case HID_USAGE_KEY_RIGHT_SHIFT:
        return MOD_RSHIFT;
    case HID_USAGE_KEY_LEFT_ALT:
        return MOD_LALT;
    case HID_USAGE_KEY_RIGHT_ALT:
        return MOD_RALT;
    case HID_USAGE_KEY_LEFT_CTRL:
        return MOD_LCTRL;
    case HID_USAGE_KEY_RIGHT_CTRL:
        return MOD_RCTRL;
    }
    return 0;
}

static void set_caps_lock_led(int keyboard_fd, bool caps_lock) {
    // The following bit to set is specified in "Device Class Definition
    // for Human Interface Devices (HID)", Version 1.11,
    // http://www.usb.org/developers/hidpage/HID1_11.pdf.  Zircon leaves
    // USB keyboards in boot mode, so the relevant section is Appendix B,
    // "Boot Interface Descriptors", "B.1 Protocol 1 (Keyboard)".
    const uint8_t kUsbCapsLockBit = 1 << 1;
    const uint8_t report_body[1] = { static_cast<uint8_t>(caps_lock ? kUsbCapsLockBit : 0) };

    // Temporarily wrap keyboard_fd, we will release it after the call so we don't close it.
    fzl::FdioCaller caller{fbl::unique_fd(keyboard_fd)};
    zx_status_t call_status;
    zx_status_t status = zircon_input_DeviceSetReport(caller.borrow_channel(),
                                                      zircon_input_ReportType_OUTPUT, 0,
                                                      report_body, sizeof(report_body),
                                                      &call_status);
    caller.release().release();
    if (status != ZX_OK || call_status != ZX_OK) {
#if !BUILD_FOR_TEST
        printf("zircon.input.Device.SetReport() failed (returned %d, %d)\n", status, call_status);
#endif
    }
}

struct vc_input {
    port_fd_handler_t fh;
    port_handler_t th;
    zx_handle_t timer;

    keypress_handler_t handler;
    int fd;

    uint8_t previous_report_buf[8];
    uint8_t report_buf[8];
    hid_keys_t state[2];
    int cur_idx;
    int prev_idx;
    int modifiers;
    uint64_t repeat_interval;
    bool repeat_enabled;
};

// returns true if key was pressed and none were released
bool vc_input_process(vc_input_t* vi, uint8_t report[8]) {
    bool do_repeat = false;

    // process the key
    uint8_t keycode;
    hid_keys_t keys;

    hid_kbd_parse_report(report, &vi->state[vi->cur_idx]);

    hid_kbd_pressed_keys(&vi->state[vi->prev_idx], &vi->state[vi->cur_idx], &keys);
    hid_for_every_key(&keys, keycode) {
        vi->modifiers |= modifiers_from_keycode(keycode);
        if (keycode == HID_USAGE_KEY_CAPSLOCK) {
            vi->modifiers ^= MOD_CAPSLOCK;
            set_caps_lock_led(vi->fd, vi->modifiers & MOD_CAPSLOCK);
        }
        vi->handler(keycode, vi->modifiers);
        do_repeat = true;
    }

    hid_kbd_released_keys(&vi->state[vi->prev_idx], &vi->state[vi->cur_idx], &keys);
    hid_for_every_key(&keys, keycode) {
        vi->modifiers &= ~modifiers_from_keycode(keycode);
        do_repeat = false;
    }

    // swap key states
    vi->cur_idx = 1 - vi->cur_idx;
    vi->prev_idx = 1 - vi->prev_idx;

    return do_repeat;
}

#if !BUILD_FOR_TEST
static void vc_input_destroy(vc_input_t* vi) {
    port_cancel(&port, &vi->th);
    if (vi->fd >= 0) {
        port_fd_handler_done(&vi->fh);
        close(vi->fd);
    }
    zx_handle_close(vi->timer);
    free(vi);
}

static zx_status_t vc_timer_cb(port_handler_t* ph, zx_signals_t signals, uint32_t evt) {
    vc_input_t* vi = containerof(ph, vc_input_t, th);

    // if interval is infinite, repeat was canceled
    if (vi->repeat_interval != ZX_TIME_INFINITE) {
        vc_input_process(vi, vi->previous_report_buf);
        vc_input_process(vi, vi->report_buf);

        // increase repeat rate if we're not yet at the fastest rate
        if ((vi->repeat_interval = vi->repeat_interval * 3 / 4) < HIGH_REPEAT_KEY_FREQ) {
            vi->repeat_interval = HIGH_REPEAT_KEY_FREQ;
        }

        zx_timer_set(vi->timer, zx_deadline_after(vi->repeat_interval), 0);
    }

    // return non-OK to avoid needlessly re-arming the repeating wait
    return ZX_ERR_NEXT;
}

static zx_status_t vc_input_cb(port_fd_handler_t* fh, unsigned pollevt, uint32_t evt) {
    vc_input_t* vi = containerof(fh, vc_input_t, fh);
    ssize_t r;

    if (!(pollevt & POLLIN)) {
        r = ZX_ERR_PEER_CLOSED;
    } else {
        memcpy(vi->previous_report_buf, vi->report_buf, sizeof(vi->report_buf));
        r = read(vi->fd, vi->report_buf, sizeof(vi->report_buf));
    }
    if (r <= 0) {
        vc_input_destroy(vi);
        return ZX_ERR_STOP;
    }
    if ((size_t)(r) != sizeof(vi->report_buf)) {
        vi->repeat_interval = ZX_TIME_INFINITE;
        return ZX_OK;
    }

    if (vc_input_process(vi, vi->report_buf) && vi->repeat_enabled) {
        vi->repeat_interval = LOW_REPEAT_KEY_FREQ;
        zx_timer_set(vi->timer, zx_deadline_after(vi->repeat_interval), 0);
    } else {
        vi->repeat_interval = ZX_TIME_INFINITE;
    }
    return ZX_OK;
}
#endif

zx_status_t vc_input_create(vc_input_t** out, keypress_handler_t handler, int fd) {
    vc_input_t* vi = reinterpret_cast<vc_input_t*>(calloc(1, sizeof(vc_input_t)));
    if (vi == NULL) {
        return ZX_ERR_NO_MEMORY;
    }

    vi->fd = fd;
    vi->handler = handler;

    vi->cur_idx = 0;
    vi->prev_idx = 1;
    vi->modifiers = 0;
    vi->repeat_interval = ZX_TIME_INFINITE;
    vi->repeat_enabled = true;

    char* flag = getenv("virtcon.keyrepeat");
    if (flag && (!strcmp(flag, "0") || !strcmp(flag, "false"))) {
        printf("vc: Key repeat disabled\n");
        vi->repeat_enabled = false;
    }

#if !BUILD_FOR_TEST
    zx_status_t r;
    if ((r = zx_timer_create(0, ZX_CLOCK_MONOTONIC, &vi->timer)) < 0) {
        free(vi);
        return r;
    }

    vi->fh.func = vc_input_cb;
    if ((r = port_fd_handler_init(&vi->fh, fd, POLLIN | POLLHUP | POLLRDHUP)) < 0) {
        zx_handle_close(vi->timer);
        free(vi);
        return r;
    }

    if ((r = port_wait(&port, &vi->fh.ph)) < 0) {
        port_fd_handler_done(&vi->fh);
        zx_handle_close(vi->timer);
        free(vi);
        return r;
    }

    vi->th.handle = vi->timer;
    vi->th.waitfor = ZX_TIMER_SIGNALED;
    vi->th.func = vc_timer_cb;
    port_wait_repeating(&port, &vi->th);
#endif

    *out = vi;
    return ZX_OK;
}

#if !BUILD_FOR_TEST
zx_status_t new_input_device(int fd, keypress_handler_t handler) {
    // test to see if this is a device we can read
    uint32_t proto = zircon_input_BootProtocol_NONE;

    // Temporarily wrap fd, we will release it after the call so we don't close it.
    fzl::FdioCaller caller{fbl::unique_fd(fd)};
    zx_status_t status = zircon_input_DeviceGetBootProtocol(caller.borrow_channel(), &proto);
    caller.release().release();
    if ((status != ZX_OK) || (proto != zircon_input_BootProtocol_KBD)) {
        // skip devices that aren't keyboards
        close(fd);
        return ZX_ERR_NOT_SUPPORTED;
    }

    vc_input_t* vi;
    if ((status = vc_input_create(&vi, handler, fd)) < 0) {
        close(fd);
    }
    return status;
}
#endif
