/* Copyright (C) 2010 The Android Open Source Project
**
** This software is licensed under the terms of the GNU General Public
** License version 2, as published by the Free Software Foundation, and
** may be copied, distributed, and modified under those terms.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
*/

#include "android/user-events.h"
#include "ui/console.h"
#include "android/looper.h"
#include "android/async-utils.h"
#include "android/utils/debug.h"
#include "android/protocol/core-connection.h"
#include "android/protocol/user-events-protocol.h"
#include "android/protocol/user-events-proxy.h"

/* Descriptor for the user events client. */
typedef struct UserEventsProxy {
    /* Core connection instance for the user events client. */
    CoreConnection* core_connection;

    /* Socket for the client. */
    int             sock;

    /* Writes user events to the socket. */
    SyncSocket*     sync_writer;
} UserEventsProxy;

/* One and only one user events client instance. */
static UserEventsProxy _userEventsProxy = { 0 };

/* Sends an event to the core.
 * Parameters:
 *  event - Event type. Must be one of the AUSER_EVENT_XXX.
 *  event_param - Event parameters.
 *  size - Byte size of the event parameters buffer.
 * Return:
 *  0 on success, or -1 on failure.
 */
static int
_userEventsProxy_send(uint8_t event, const void* event_param, size_t size)
{
    int res;
    UserEventHeader header;

    header.event_type = event;
    res = syncsocket_start_write(_userEventsProxy.sync_writer);
    if (!res) {
        // Send event type first (event header)
        res = syncsocket_write(_userEventsProxy.sync_writer, &header,
                               sizeof(header),
                               core_connection_get_timeout(sizeof(header)));
        if (res > 0) {
            // Send event param next.
            res = syncsocket_write(_userEventsProxy.sync_writer, event_param,
                                   size,
                                   core_connection_get_timeout(sizeof(size)));
        }
        res = syncsocket_result(res);
        syncsocket_stop_write(_userEventsProxy.sync_writer);
    }
    if (res < 0) {
        derror("Unable to send user event: %s\n", errno_str);
    }
    return res;
}

int
userEventsProxy_create(SockAddress* console_socket)
{
    char* handshake = NULL;

    // Connect to the user-events service.
    _userEventsProxy.core_connection =
        core_connection_create_and_switch(console_socket, "user-events",
                                          &handshake);
    if (_userEventsProxy.core_connection == NULL) {
        derror("Unable to connect to the user-events service: %s\n",
               errno_str);
        return -1;
    }

    // Initialze event writer.
    _userEventsProxy.sock =
        core_connection_get_socket(_userEventsProxy.core_connection);
    _userEventsProxy.sync_writer = syncsocket_init(_userEventsProxy.sock);
    if (_userEventsProxy.sync_writer == NULL) {
        derror("Unable to initialize UserEventsProxy writer: %s\n", errno_str);
        userEventsProxy_destroy();
        return -1;
    }

    fprintf(stdout, "user-events is now connected to the core at %s.",
            sock_address_to_string(console_socket));
    if (handshake != NULL) {
        if (handshake[0] != '\0') {
            fprintf(stdout, " Handshake: %s", handshake);
        }
        free(handshake);
    }
    fprintf(stdout, "\n");

    return 0;
}

void
userEventsProxy_destroy(void)
{
    if (_userEventsProxy.sync_writer != NULL) {
        syncsocket_close(_userEventsProxy.sync_writer);
        syncsocket_free(_userEventsProxy.sync_writer);
        _userEventsProxy.sync_writer = NULL;
    }
    if (_userEventsProxy.core_connection != NULL) {
        core_connection_close(_userEventsProxy.core_connection);
        core_connection_free(_userEventsProxy.core_connection);
        _userEventsProxy.core_connection = NULL;
    }
}
void
user_event_keycodes(int *kcodes, int count)
{
    int nn;
    for (nn = 0; nn < count; nn++)
        user_event_keycode(kcodes[nn]);
}

void
user_event_keycode(int  kcode)
{
    UserEventKeycode    message;
    message.keycode = kcode;
    _userEventsProxy_send(AUSER_EVENT_KEYCODE, &message, sizeof(message));
}

void
user_event_key(unsigned code, unsigned down)
{
    if(code == 0) {
        return;
    }
    if (VERBOSE_CHECK(keys))
        printf(">> KEY [0x%03x,%s]\n", (code & 0x1ff), down ? "down" : " up " );

    user_event_keycode((code & 0x1ff) | (down ? 0x200 : 0));
}


void
user_event_mouse(int dx, int dy, int dz, unsigned buttons_state)
{
    UserEventMouse    message;
    message.dx = dx;
    message.dy = dy;
    message.dz = dz;
    message.buttons_state = buttons_state;
    _userEventsProxy_send(AUSER_EVENT_MOUSE, &message, sizeof(message));
}

void
user_event_register_generic(void* opaque, QEMUPutGenericEvent *callback)
{
}

void
user_event_generic(int type, int code, int value)
{
    UserEventGeneric    message;
    message.type = type;
    message.code = code;
    message.value = value;
    _userEventsProxy_send(AUSER_EVENT_GENERIC, &message, sizeof(message));
}
