/* 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.
*/

/*
 * Contains the Core-side of the "user events" service. Here we receive and
 * handle user events sent from the UI.
 */

#include "android/user-events.h"
#include "android/globals.h"
#include "android/android.h"
#include "android/looper.h"
#include "android/async-utils.h"
#include "android/sync-utils.h"
#include "android/utils/system.h"
#include "android/utils/debug.h"
#include "android/protocol/user-events-protocol.h"
#include "android/protocol/user-events-impl.h"

/* Enumerates state values for the event reader in the UserEventsImpl descriptor.
 */
typedef enum UserEventsImplState {
    /* The reader is waiting on event header. */
    EXPECTS_HEADER,

    /* The reader is waiting on event parameters. */
    EXPECTS_PARAMETERS,
} UserEventsImplState;


/* Core user events service descriptor. */
typedef struct UserEventsImpl {
    /* Reader to receive user events. */
    AsyncReader         user_events_reader;

    /* I/O associated with this descriptor. */
    LoopIo              io;

    /* Looper used to communicate user events. */
    Looper*             looper;

    /* Socket for this service. */
    int                 sock;

    /* State of the service (see UE_STATE_XXX for possible values). */
    UserEventsImplState state;

    /* Current event header. */
    UserEventHeader     event_header;

    /* Current event parameters. */
    union {
        UserEventGeneric    generic_event;
        UserEventMouse      mouse_event;
        UserEventKeycode    keycode_event;
    };
} UserEventsImpl;

/* Implemented in android/console.c */
extern void destroy_user_events_client(void);

/* One and only one UserEventsImpl instance. */
static UserEventsImpl   _UserEventsImpl;

/* Asynchronous I/O callback reading user events.
 * Param:
 *  opaque - UserEventsImpl instance.
 */
static void
_userEventsImpl_io_func(void* opaque, int fd, unsigned events)
{
    UserEventsImpl* ueimpl;
    AsyncStatus status;

    if (events & LOOP_IO_WRITE) {
        // We don't use async writer here, so we don't expect
        // any write callbacks.
        derror("Unexpected LOOP_IO_WRITE in _userEventsImpl_io_func\n");
        return;
    }

    ueimpl = (UserEventsImpl*)opaque;
    // Read whatever is expected from the socket.
    status = asyncReader_read(&ueimpl->user_events_reader);


    switch (status) {
        case ASYNC_COMPLETE:
            switch (ueimpl->state) {
                case EXPECTS_HEADER:
                    // We just read event header. Now we expect event parameters.
                    ueimpl->state = EXPECTS_PARAMETERS;
                    // Setup the reader depending on the event type.
                    switch (ueimpl->event_header.event_type) {
                        case AUSER_EVENT_MOUSE:
                            asyncReader_init(&ueimpl->user_events_reader,
                                             &ueimpl->mouse_event,
                                             sizeof(ueimpl->mouse_event),
                                             &ueimpl->io);
                            break;

                        case AUSER_EVENT_KEYCODE:
                            asyncReader_init(&ueimpl->user_events_reader,
                                             &ueimpl->keycode_event,
                                             sizeof(ueimpl->keycode_event),
                                             &ueimpl->io);
                            break;

                        case AUSER_EVENT_GENERIC:
                            asyncReader_init(&ueimpl->user_events_reader,
                                             &ueimpl->generic_event,
                                             sizeof(ueimpl->generic_event),
                                             &ueimpl->io);
                            break;

                        default:
                            derror("Unexpected user event type %d\n",
                                   ueimpl->event_header.event_type);
                            break;
                    }
                    break;

                case EXPECTS_PARAMETERS:
                    // We just read event parameters. Lets fire the event.
                    switch (ueimpl->event_header.event_type) {
                        case AUSER_EVENT_MOUSE:
                            user_event_mouse(ueimpl->mouse_event.dx,
                                             ueimpl->mouse_event.dy,
                                             ueimpl->mouse_event.dz,
                                             ueimpl->mouse_event.buttons_state);
                            break;

                        case AUSER_EVENT_KEYCODE:
                            user_event_keycode(ueimpl->keycode_event.keycode);
                            break;

                        case AUSER_EVENT_GENERIC:
                            user_event_generic(ueimpl->generic_event.type,
                                               ueimpl->generic_event.code,
                                               ueimpl->generic_event.value);
                            break;

                        default:
                            derror("Unexpected user event type %d\n",
                                   ueimpl->event_header.event_type);
                            break;
                    }
                    // Prepare to receive the next event header.
                    ueimpl->event_header.event_type = -1;
                    ueimpl->state = EXPECTS_HEADER;
                    asyncReader_init(&ueimpl->user_events_reader,
                                     &ueimpl->event_header,
                                     sizeof(ueimpl->event_header), &ueimpl->io);
                    break;
            }
            break;
        case ASYNC_ERROR:
            loopIo_dontWantRead(&ueimpl->io);
            if (errno == ECONNRESET) {
                // UI has exited. We need to destroy user event service.
                destroy_user_events_client();
            } else {
                derror("User event read error %d -> %s\n", errno, errno_str);
            }
            break;

        case ASYNC_NEED_MORE:
            // Transfer will eventually come back into this routine.
            return;
    }
}

int
userEventsImpl_create(int fd)
{
    _UserEventsImpl.sock = fd;
    _UserEventsImpl.event_header.event_type = -1;
    _UserEventsImpl.state = EXPECTS_HEADER;
    _UserEventsImpl.looper = looper_newCore();
    loopIo_init(&_UserEventsImpl.io, _UserEventsImpl.looper, _UserEventsImpl.sock,
                _userEventsImpl_io_func, &_UserEventsImpl);
    asyncReader_init(&_UserEventsImpl.user_events_reader,
                     &_UserEventsImpl.event_header,
                     sizeof(_UserEventsImpl.event_header), &_UserEventsImpl.io);
    return 0;
}

void
userEventsImpl_destroy(void)
{
    if (_UserEventsImpl.looper != NULL) {
        // Stop all I/O that may still be going on.
        loopIo_done(&_UserEventsImpl.io);
        looper_free(_UserEventsImpl.looper);
        _UserEventsImpl.looper = NULL;
    }
}
