/*
 * (C) Copyright 2014, Fuji Xerox Co.,Ltd.  All rights reserved.
 * File name : fx-swkeyboard.c
 * Title : shell controller from gimlet.
 */
#include "config.h"

#include <string.h>
#include <limits.h>
#include <linux/input.h>
#include "compositor-fx-fbdev.h"
#include "shared/helpers.h"
#include "shared/timespec-util.h"
#include "protocol/fx-swkeyboard-server-protocol.h"
#include "fx-seat.h"
#include "fx-shell.h"
#include "fx-swkeyboard.h"

/* Typedefs */
struct fx_swkeyboard_seat {
    struct weston_seat base;
    struct wl_listener seat_released;
    struct xkb_context *xkb_context;
    struct fx_shell *
        shell;
};
struct fx_swkeyboard {
    struct wl_resource *
        resource;
    struct wl_listener
        destroy_listener;
    struct fx_swkeyboard_seat*
        swkeyboard_seat;
    struct fx_shell *
        shell;
} ;

/* Procedures */
static struct fx_swkeyboard_seat *
swkeyboard_seat_create( struct fx_shell *shell )
{
    struct fx_swkeyboard_seat *swkeyboard_seat;

    swkeyboard_seat = zalloc(sizeof *swkeyboard_seat);
    if (swkeyboard_seat == NULL)
        return NULL;

    weston_seat_init(
            &swkeyboard_seat->base,
            shell->compositor,
            "fx_swkeyboard_surface" );
/*
    swkeyboard_seat->seat_released.notify = seat_released;
    wl_signal_add(
            &swkeyboard_seat->base.released_signal,
            &swkeyboard_seat->seat_released );
*/
    swkeyboard_seat->shell = shell;

    weston_seat_init_touch( &swkeyboard_seat->base );

    {
        FILE *fp = fopen( "integ/data/swkeyboard_keymap", "r" );
        struct xkb_keymap *xkb_keymap = NULL;

        if ( fp != NULL ) {
            swkeyboard_seat->xkb_context = xkb_context_new( 0 );
            if ( swkeyboard_seat->xkb_context != NULL ) {
                xkb_keymap = xkb_map_new_from_file(
                        swkeyboard_seat->xkb_context,
                        fp,
                        XKB_KEYMAP_FORMAT_TEXT_V1,
                        0 );

                fclose( fp );
            }
        }
        weston_seat_init_keyboard( &swkeyboard_seat->base, xkb_keymap );
        if ( xkb_keymap != NULL ) xkb_keymap_unref( xkb_keymap );
    }
    return swkeyboard_seat;
}
static void
notify_swkey(
        struct wl_client *client,
        struct wl_resource *resource,
        int32_t key,
        int32_t state )
{
    struct fx_swkeyboard *swkeyboard
        = wl_resource_get_user_data( resource );
    struct timespec ts;
    int result = clock_gettime(
            CLOCK_MONOTONIC,
            &ts );

    if ( result < 0 ) {
        assert( false );
        return;
    }
    notify_key(
            &swkeyboard->swkeyboard_seat->base,
            &ts,
            key - 8,
            state,
            STATE_UPDATE_AUTOMATIC );
}

static void
swkeyboard_destroyed(
        struct wl_listener *listener,
        void *data )
{
    struct fx_swkeyboard *swkeyboard
        = container_of(listener, struct fx_swkeyboard, destroy_listener);

    weston_seat_release( &swkeyboard->swkeyboard_seat->base );
    free( swkeyboard->swkeyboard_seat );
    free( swkeyboard );
}

static struct fx_swkeyboard_interface fx_swkeyboard_implementation
= {
    notify_swkey,
};
static void 
bind_fx_swkeyboard(
        struct wl_client *client,
        void *data,
        uint32_t version,
        uint32_t id )
{
    struct fx_shell *shell = data;
    struct fx_swkeyboard * swkeyboard;

    swkeyboard = zalloc( sizeof ( *swkeyboard ) );

    if ( swkeyboard == NULL ) {
        return;
    }
    swkeyboard->resource = wl_resource_create(
            client,
            &fx_swkeyboard_interface,
            1,
            id );
    wl_resource_set_implementation(
            swkeyboard->resource,
            &fx_swkeyboard_implementation,
            swkeyboard,
            NULL );
    swkeyboard->destroy_listener.notify = swkeyboard_destroyed;
    wl_client_add_destroy_listener(
            client,
            &swkeyboard->destroy_listener );

    swkeyboard->swkeyboard_seat = swkeyboard_seat_create( shell );
    if ( swkeyboard->swkeyboard_seat == NULL ) {
        weston_log( "can't create swkeyboard seat\n" );
    }
    swkeyboard->shell = shell;

/*
    send_session( swkeyboard );

    swkeyboard->key_listener.notify = key_notify;
    wl_signal_add(
            &shell->compositor->key_signal,
            &swkeyboard->key_listener );
    swkeyboard->touch_listener.notify = touch_notify;
    wl_signal_add(
            &shell->compositor->touch_signal,
            &swkeyboard->touch_listener );
    swkeyboard->button_listener.notify = button_notify;
    wl_signal_add(
            &shell->compositor->button_signal,
            &swkeyboard->button_listener );

    swkeyboard->listener.connection = connection;
*/
}

struct wl_global*
fx_swkeyboard_create( struct fx_shell* shell )
{
    return wl_global_create(
            shell->compositor->wl_display,
            &fx_swkeyboard_interface,
            1,
            shell,
            bind_fx_swkeyboard );
}

