/*
 * This work is licensed under the terms of the GNU GPL, version 2 or
 * (at your option) any later version.  See the COPYING file in the
 * top-level directory.
 */
#include "qemu/osdep.h"
#include "qemu/bitmap.h"
#include "qemu/queue.h"
#include "ui/console.h"
#include "ui/input.h"
#include "ui/kbd-state.h"

struct QKbdState {
    QemuConsole *con;
    int key_delay_ms;
    DECLARE_BITMAP(keys, Q_KEY_CODE__MAX);
    DECLARE_BITMAP(mods, QKBD_MOD__MAX);
};

static void qkbd_state_modifier_update(QKbdState *kbd,
                                      QKeyCode qcode1, QKeyCode qcode2,
                                      QKbdModifier mod)
{
    if (test_bit(qcode1, kbd->keys) || test_bit(qcode2, kbd->keys)) {
        set_bit(mod, kbd->mods);
    } else {
        clear_bit(mod, kbd->mods);
    }
}

bool qkbd_state_modifier_get(QKbdState *kbd, QKbdModifier mod)
{
    return test_bit(mod, kbd->mods);
}

bool qkbd_state_key_get(QKbdState *kbd, QKeyCode qcode)
{
    return test_bit(qcode, kbd->keys);
}

void qkbd_state_key_event(QKbdState *kbd, QKeyCode qcode, bool down)
{
    bool state = test_bit(qcode, kbd->keys);

    if (state == down) {
        /*
         * Filter out events which don't change the keyboard state.
         *
         * Most notably this allows to simply send along all key-up
         * events, and this function will filter out everything where
         * the corresponding key-down event wasn't send to the guest,
         * for example due to being a host hotkey.
         */
        return;
    }

    /* update key and modifier state */
    change_bit(qcode, kbd->keys);
    switch (qcode) {
    case Q_KEY_CODE_SHIFT:
    case Q_KEY_CODE_SHIFT_R:
        qkbd_state_modifier_update(kbd, Q_KEY_CODE_SHIFT, Q_KEY_CODE_SHIFT_R,
                                   QKBD_MOD_SHIFT);
        break;
    case Q_KEY_CODE_CTRL:
    case Q_KEY_CODE_CTRL_R:
        qkbd_state_modifier_update(kbd, Q_KEY_CODE_CTRL, Q_KEY_CODE_CTRL_R,
                                   QKBD_MOD_CTRL);
        break;
    case Q_KEY_CODE_ALT:
        qkbd_state_modifier_update(kbd, Q_KEY_CODE_ALT, Q_KEY_CODE_ALT,
                                   QKBD_MOD_ALT);
        break;
    case Q_KEY_CODE_ALT_R:
        qkbd_state_modifier_update(kbd, Q_KEY_CODE_ALT_R, Q_KEY_CODE_ALT_R,
                                   QKBD_MOD_ALTGR);
        break;
    case Q_KEY_CODE_CAPS_LOCK:
        if (down) {
            change_bit(QKBD_MOD_CAPSLOCK, kbd->mods);
        }
        break;
    case Q_KEY_CODE_NUM_LOCK:
        if (down) {
            change_bit(QKBD_MOD_NUMLOCK, kbd->mods);
        }
        break;
    default:
        /* keep gcc happy */
        break;
    }

    /* send to guest */
    if (qemu_console_is_graphic(kbd->con)) {
        qemu_input_event_send_key_qcode(kbd->con, qcode, down);
        if (kbd->key_delay_ms) {
            qemu_input_event_send_key_delay(kbd->key_delay_ms);
        }
    }
}

void qkbd_state_lift_all_keys(QKbdState *kbd)
{
    int qcode;

    for (qcode = 0; qcode < Q_KEY_CODE__MAX; qcode++) {
        if (test_bit(qcode, kbd->keys)) {
            qkbd_state_key_event(kbd, qcode, false);
        }
    }
}

void qkbd_state_set_delay(QKbdState *kbd, int delay_ms)
{
    kbd->key_delay_ms = delay_ms;
}

void qkbd_state_free(QKbdState *kbd)
{
    g_free(kbd);
}

QKbdState *qkbd_state_init(QemuConsole *con)
{
    QKbdState *kbd = g_new0(QKbdState, 1);

    kbd->con = con;

    return kbd;
}
