/*
 * QEMU System Emulator
 *
 * Copyright (c) 2003-2008 Fabrice Bellard
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "sysemu/sysemu.h"
#include "ui/console.h"
#include "qapi/error.h"
#include "qmp-commands.h"
#include "qapi-types.h"
#include "ui/keymaps.h"
#include "ui/input.h"

struct QEMUPutMouseEntry {
    QEMUPutMouseEvent *qemu_put_mouse_event;
    void *qemu_put_mouse_event_opaque;
    int qemu_put_mouse_event_absolute;

    /* new input core */
    QemuInputHandler h;
    QemuInputHandlerState *s;
    int axis[INPUT_AXIS__MAX];
    int buttons;
};

struct QEMUPutKbdEntry {
    QEMUPutKBDEvent *put_kbd;
    void *opaque;
    QemuInputHandlerState *s;
};

struct QEMUPutLEDEntry {
    QEMUPutLEDEvent *put_led;
    void *opaque;
    QTAILQ_ENTRY(QEMUPutLEDEntry) next;
};

static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers =
    QTAILQ_HEAD_INITIALIZER(led_handlers);

int index_from_key(const char *key)
{
    int i;

    for (i = 0; QKeyCode_lookup[i] != NULL; i++) {
        if (!strcmp(key, QKeyCode_lookup[i])) {
            break;
        }
    }

    /* Return Q_KEY_CODE__MAX if the key is invalid */
    return i;
}

static KeyValue *copy_key_value(KeyValue *src)
{
    KeyValue *dst = g_new(KeyValue, 1);
    memcpy(dst, src, sizeof(*src));
    return dst;
}

void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time,
                  Error **errp)
{
    KeyValueList *p;
    KeyValue **up = NULL;
    int count = 0;

    if (!has_hold_time) {
        hold_time = 0; /* use default */
    }

    for (p = keys; p != NULL; p = p->next) {
        qemu_input_event_send_key(NULL, copy_key_value(p->value), true);
        qemu_input_event_send_key_delay(hold_time);
        up = g_realloc(up, sizeof(*up) * (count+1));
        up[count] = copy_key_value(p->value);
        count++;
    }
    while (count) {
        count--;
        qemu_input_event_send_key(NULL, up[count], false);
        qemu_input_event_send_key_delay(hold_time);
    }
    g_free(up);
}

static void legacy_kbd_event(DeviceState *dev, QemuConsole *src,
                             InputEvent *evt)
{
    QEMUPutKbdEntry *entry = (QEMUPutKbdEntry *)dev;
    int scancodes[3], i, count;

    if (!entry || !entry->put_kbd) {
        return;
    }
    count = qemu_input_key_value_to_scancode(evt->u.key->key,
                                             evt->u.key->down,
                                             scancodes);
    for (i = 0; i < count; i++) {
        entry->put_kbd(entry->opaque, scancodes[i]);
    }
}

static QemuInputHandler legacy_kbd_handler = {
    .name  = "legacy-kbd",
    .mask  = INPUT_EVENT_MASK_KEY,
    .event = legacy_kbd_event,
};

QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
{
    QEMUPutKbdEntry *entry;

    entry = g_new0(QEMUPutKbdEntry, 1);
    entry->put_kbd = func;
    entry->opaque = opaque;
    entry->s = qemu_input_handler_register((DeviceState *)entry,
                                           &legacy_kbd_handler);
    qemu_input_handler_activate(entry->s);
    return entry;
}

static void legacy_mouse_event(DeviceState *dev, QemuConsole *src,
                               InputEvent *evt)
{
    static const int bmap[INPUT_BUTTON__MAX] = {
        [INPUT_BUTTON_LEFT]   = MOUSE_EVENT_LBUTTON,
        [INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON,
        [INPUT_BUTTON_RIGHT]  = MOUSE_EVENT_RBUTTON,
    };
    QEMUPutMouseEntry *s = (QEMUPutMouseEntry *)dev;

    switch (evt->type) {
    case INPUT_EVENT_KIND_BTN:
        if (evt->u.btn->down) {
            s->buttons |= bmap[evt->u.btn->button];
        } else {
            s->buttons &= ~bmap[evt->u.btn->button];
        }
        if (evt->u.btn->down && evt->u.btn->button == INPUT_BUTTON_WHEELUP) {
            s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
                                    s->axis[INPUT_AXIS_X],
                                    s->axis[INPUT_AXIS_Y],
                                    -1,
                                    s->buttons);
        }
        if (evt->u.btn->down &&
            evt->u.btn->button == INPUT_BUTTON_WHEELDOWN) {
            s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
                                    s->axis[INPUT_AXIS_X],
                                    s->axis[INPUT_AXIS_Y],
                                    1,
                                    s->buttons);
        }
        break;
    case INPUT_EVENT_KIND_ABS:
        s->axis[evt->u.abs->axis] = evt->u.abs->value;
        break;
    case INPUT_EVENT_KIND_REL:
        s->axis[evt->u.rel->axis] += evt->u.rel->value;
        break;
    default:
        break;
    }
}

static void legacy_mouse_sync(DeviceState *dev)
{
    QEMUPutMouseEntry *s = (QEMUPutMouseEntry *)dev;

    s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
                            s->axis[INPUT_AXIS_X],
                            s->axis[INPUT_AXIS_Y],
                            0,
                            s->buttons);

    if (!s->qemu_put_mouse_event_absolute) {
        s->axis[INPUT_AXIS_X] = 0;
        s->axis[INPUT_AXIS_Y] = 0;
    }
}

QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
                                                void *opaque, int absolute,
                                                const char *name)
{
    QEMUPutMouseEntry *s;

    s = g_new0(QEMUPutMouseEntry, 1);

    s->qemu_put_mouse_event = func;
    s->qemu_put_mouse_event_opaque = opaque;
    s->qemu_put_mouse_event_absolute = absolute;

    s->h.name = name;
    s->h.mask = INPUT_EVENT_MASK_BTN |
        (absolute ? INPUT_EVENT_MASK_ABS : INPUT_EVENT_MASK_REL);
    s->h.event = legacy_mouse_event;
    s->h.sync = legacy_mouse_sync;
    s->s = qemu_input_handler_register((DeviceState *)s,
                                       &s->h);

    return s;
}

void qemu_activate_mouse_event_handler(QEMUPutMouseEntry *entry)
{
    qemu_input_handler_activate(entry->s);
}

void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry)
{
    qemu_input_handler_unregister(entry->s);

    g_free(entry);
}

QEMUPutLEDEntry *qemu_add_led_event_handler(QEMUPutLEDEvent *func,
                                            void *opaque)
{
    QEMUPutLEDEntry *s;

    s = g_new0(QEMUPutLEDEntry, 1);

    s->put_led = func;
    s->opaque = opaque;
    QTAILQ_INSERT_TAIL(&led_handlers, s, next);
    return s;
}

void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry)
{
    if (entry == NULL)
        return;
    QTAILQ_REMOVE(&led_handlers, entry, next);
    g_free(entry);
}

void kbd_put_ledstate(int ledstate)
{
    QEMUPutLEDEntry *cursor;

    QTAILQ_FOREACH(cursor, &led_handlers, next) {
        cursor->put_led(cursor->opaque, ledstate);
    }
}
