// socket_playdate.c - Socket stub for Playdate
// Raw sockets are not directly supported on Playdate.
// Use the http module for HTTP requests or enet for game networking.

#include "cell.h"

// All socket functions throw "not supported" errors

JSC_CCALL(socket_getaddrinfo,
    return JS_RaiseDisrupt(js, "socket.getaddrinfo: not supported on Playdate");
)

JSC_CCALL(socket_socket,
    return JS_RaiseDisrupt(js, "socket.socket: not supported on Playdate");
)

JSC_CCALL(socket_bind,
    return JS_RaiseDisrupt(js, "socket.bind: not supported on Playdate");
)

JSC_CCALL(socket_connect,
    return JS_RaiseDisrupt(js, "socket.connect: not supported on Playdate");
)

JSC_CCALL(socket_listen,
    return JS_RaiseDisrupt(js, "socket.listen: not supported on Playdate");
)

JSC_CCALL(socket_accept,
    return JS_RaiseDisrupt(js, "socket.accept: not supported on Playdate");
)

JSC_CCALL(socket_send,
    return JS_RaiseDisrupt(js, "socket.send: not supported on Playdate");
)

JSC_CCALL(socket_recv,
    return JS_RaiseDisrupt(js, "socket.recv: not supported on Playdate");
)

JSC_CCALL(socket_sendto,
    return JS_RaiseDisrupt(js, "socket.sendto: not supported on Playdate");
)

JSC_CCALL(socket_recvfrom,
    return JS_RaiseDisrupt(js, "socket.recvfrom: not supported on Playdate");
)

JSC_CCALL(socket_shutdown,
    return JS_RaiseDisrupt(js, "socket.shutdown: not supported on Playdate");
)

JSC_CCALL(socket_getpeername,
    return JS_RaiseDisrupt(js, "socket.getpeername: not supported on Playdate");
)

JSC_CCALL(socket_gethostname,
    return JS_NewString(js, "playdate");
)

JSC_CCALL(socket_gai_strerror,
    return JS_NewString(js, "not supported on Playdate");
)

JSC_CCALL(socket_setsockopt,
    return JS_RaiseDisrupt(js, "socket.setsockopt: not supported on Playdate");
)

JSC_CCALL(socket_close,
    return JS_RaiseDisrupt(js, "socket.close: not supported on Playdate");
)

static const JSCFunctionListEntry js_socket_funcs[] = {
    MIST_FUNC_DEF(socket, getaddrinfo, 3),
    MIST_FUNC_DEF(socket, socket, 3),
    MIST_FUNC_DEF(socket, bind, 2),
    MIST_FUNC_DEF(socket, connect, 2),
    MIST_FUNC_DEF(socket, listen, 2),
    MIST_FUNC_DEF(socket, accept, 1),
    MIST_FUNC_DEF(socket, send, 3),
    MIST_FUNC_DEF(socket, recv, 3),
    MIST_FUNC_DEF(socket, sendto, 4),
    MIST_FUNC_DEF(socket, recvfrom, 3),
    MIST_FUNC_DEF(socket, shutdown, 2),
    MIST_FUNC_DEF(socket, getpeername, 1),
    MIST_FUNC_DEF(socket, gethostname, 0),
    MIST_FUNC_DEF(socket, gai_strerror, 1),
    MIST_FUNC_DEF(socket, setsockopt, 4),
    MIST_FUNC_DEF(socket, close, 1),
};

JSValue js_socket_use(JSContext *js) {
    JSValue mod = JS_NewObject(js);
    JS_SetPropertyFunctionList(js, mod, js_socket_funcs, countof(js_socket_funcs));
    
    // Add constants (even though they won't be useful)
    JS_SetPropertyStr(js, mod, "AF_UNSPEC", JS_NewInt32(js, 0));
    JS_SetPropertyStr(js, mod, "AF_INET", JS_NewInt32(js, 2));
    JS_SetPropertyStr(js, mod, "AF_INET6", JS_NewInt32(js, 10));
    JS_SetPropertyStr(js, mod, "AF_UNIX", JS_NewInt32(js, 1));
    
    JS_SetPropertyStr(js, mod, "SOCK_STREAM", JS_NewInt32(js, 1));
    JS_SetPropertyStr(js, mod, "SOCK_DGRAM", JS_NewInt32(js, 2));
    
    JS_SetPropertyStr(js, mod, "AI_PASSIVE", JS_NewInt32(js, 1));
    
    JS_SetPropertyStr(js, mod, "SHUT_RD", JS_NewInt32(js, 0));
    JS_SetPropertyStr(js, mod, "SHUT_WR", JS_NewInt32(js, 1));
    JS_SetPropertyStr(js, mod, "SHUT_RDWR", JS_NewInt32(js, 2));
    
    JS_SetPropertyStr(js, mod, "SOL_SOCKET", JS_NewInt32(js, 1));
    JS_SetPropertyStr(js, mod, "SO_REUSEADDR", JS_NewInt32(js, 2));
    
    return mod;
}
