#include <string.h>

#include <SDL.h>
#include <SDL_net.h>

#define PORT 4444
#define MAX_CLIENTS 16

static TCPsocket client_connections[MAX_CLIENTS];
static SDLNet_SocketSet socket_set;

static void NewConnection(TCPsocket server_socket)
{
    TCPsocket new_socket;
    int i;

    printf("accept new connection\n");

    // Accept new connection

    new_socket = SDLNet_TCP_Accept(server_socket);

    // Find a slot in the client connections array for this new socket
    
    for (i=0; i<MAX_CLIENTS; ++i)
    {
        if (client_connections[i] == NULL)
        {
            SDLNet_TCP_AddSocket(socket_set, new_socket);
            client_connections[i] = new_socket;
            return;
        }
    }

    // Failed to find a slot

    SDLNet_TCP_Close(new_socket);
}

int SDL_PrivateMouseMotion(Uint8 buttonstate, int relative, Sint16 x, Sint16 y);

static void ReceivedEvent(SDL_Event *event)
{
    if (event->type == SDL_MOUSEMOTION)
    {
        SDL_PrivateMouseMotion(event->motion.state,
                               1, 
                               event->motion.xrel,
                               event->motion.yrel);
    }
    else
    {
        SDL_PushEvent(event);
    }
}

static void ReadSocketData(TCPsocket sock)
{
    SDL_Event event;
    int bytes;
    int i;

    bytes = SDLNet_TCP_Recv(sock, &event, sizeof(event));

    if (bytes == 0)
    {
        // Connection closed

        SDLNet_TCP_DelSocket(socket_set, sock);

        for (i=0; i<MAX_CLIENTS; ++i)
        {
            if (client_connections[i] == sock)
                client_connections[i] = NULL;
        }
    }
    else if (bytes == sizeof(event))
    {
        ReceivedEvent(&event);
    }
    else
    {
        printf("%i / %i bytes read :-(\n", bytes, sizeof(event));
    }
}

static int ServerThread(void *data)
{
    TCPsocket server_socket;
    IPaddress addr;
    int i;

    SDLNet_Init();

    SDLNet_ResolveHost(&addr, NULL, PORT);

    server_socket = SDLNet_TCP_Open(&addr);

    printf("started server socket\n");

    memset(client_connections, 0, sizeof(TCPsocket) * MAX_CLIENTS);
    socket_set = SDLNet_AllocSocketSet(MAX_CLIENTS + 1);
    SDLNet_TCP_AddSocket(socket_set, server_socket);

    for (;;)
    {
        SDLNet_CheckSockets(socket_set, 1000);

        if (SDLNet_SocketReady(server_socket))
        {
            NewConnection(server_socket);
        }

        for (i=0; i<MAX_CLIENTS; ++i)
        {
            if (client_connections[i] 
             && SDLNet_SocketReady(client_connections[i]))
            {
                ReadSocketData(client_connections[i]);
            }
        }
    }
}

void SDL_Remote_StartServer(void)
{
    SDL_CreateThread(ServerThread, NULL);
}

