use arceos_posix_api::{
    sys_accept, sys_bind, sys_connect, sys_freeaddrinfo, sys_getaddrinfo, sys_getpeername,
    sys_getsockname, sys_listen, sys_recv, sys_recvfrom, sys_send, sys_sendmsg, sys_sendto,
    sys_shutdown, sys_socket,
};
use core::ffi::{c_char, c_int, c_void};
use crate::{ctypes, utils::e};
#[no_mangle]
pub unsafe extern "C" fn socket(domain: c_int, socktype: c_int, protocol: c_int) -> c_int {
    e(sys_socket(domain, socktype, protocol))
}
#[no_mangle]
pub unsafe extern "C" fn bind(
    socket_fd: c_int,
    socket_addr: *const ctypes::sockaddr,
    addrlen: ctypes::socklen_t,
) -> c_int {
    e(sys_bind(socket_fd, socket_addr, addrlen))
}
#[no_mangle]
pub unsafe extern "C" fn connect(
    socket_fd: c_int,
    socket_addr: *const ctypes::sockaddr,
    addrlen: ctypes::socklen_t,
) -> c_int {
    e(sys_connect(socket_fd, socket_addr, addrlen))
}
#[no_mangle]
pub unsafe extern "C" fn sendto(
    socket_fd: c_int,
    buf_ptr: *const c_void,
    len: ctypes::size_t,
    flag: c_int, socket_addr: *const ctypes::sockaddr,
    addrlen: ctypes::socklen_t,
) -> ctypes::ssize_t {
    if socket_addr.is_null() && addrlen == 0 {
        return e(sys_send(socket_fd, buf_ptr, len, flag) as _) as _;
    }
    e(sys_sendto(socket_fd, buf_ptr, len, flag, socket_addr, addrlen) as _) as _
}
#[no_mangle]
pub unsafe extern "C" fn send(
    socket_fd: c_int,
    buf_ptr: *const c_void,
    len: ctypes::size_t,
    flag: c_int, ) -> ctypes::ssize_t {
    e(sys_send(socket_fd, buf_ptr, len, flag) as _) as _
}
#[no_mangle]
pub unsafe extern "C" fn recvfrom(
    socket_fd: c_int,
    buf_ptr: *mut c_void,
    len: ctypes::size_t,
    flag: c_int, socket_addr: *mut ctypes::sockaddr,
    addrlen: *mut ctypes::socklen_t,
) -> ctypes::ssize_t {
    if socket_addr.is_null() {
        return e(sys_recv(socket_fd, buf_ptr, len, flag) as _) as _;
    }
    e(sys_recvfrom(socket_fd, buf_ptr, len, flag, socket_addr, addrlen) as _) as _
}
#[no_mangle]
pub unsafe extern "C" fn recv(
    socket_fd: c_int,
    buf_ptr: *mut c_void,
    len: ctypes::size_t,
    flag: c_int, ) -> ctypes::ssize_t {
    e(sys_recv(socket_fd, buf_ptr, len, flag) as _) as _
}
#[no_mangle]
pub unsafe extern "C" fn listen(
    socket_fd: c_int,
    backlog: c_int, ) -> c_int {
    e(sys_listen(socket_fd, backlog))
}
#[no_mangle]
pub unsafe extern "C" fn accept(
    socket_fd: c_int,
    socket_addr: *mut ctypes::sockaddr,
    socket_len: *mut ctypes::socklen_t,
) -> c_int {
    e(sys_accept(socket_fd, socket_addr, socket_len))
}
#[no_mangle]
pub unsafe extern "C" fn shutdown(
    socket_fd: c_int,
    flag: c_int, ) -> c_int {
    e(sys_shutdown(socket_fd, flag))
}
#[no_mangle]
pub unsafe extern "C" fn getaddrinfo(
    nodename: *const c_char,
    servname: *const c_char,
    hints: *const ctypes::addrinfo,
    res: *mut *mut ctypes::addrinfo,
) -> c_int {
    let ret = e(sys_getaddrinfo(nodename, servname, hints, res));
    match ret {
        r if r < 0 => ctypes::EAI_FAIL,
        0 => ctypes::EAI_NONAME,
        _ => 0,
    }
}
#[no_mangle]
pub unsafe extern "C" fn freeaddrinfo(res: *mut ctypes::addrinfo) {
    sys_freeaddrinfo(res);
}
#[no_mangle]
pub unsafe extern "C" fn getsockname(
    sock_fd: c_int,
    addr: *mut ctypes::sockaddr,
    addrlen: *mut ctypes::socklen_t,
) -> c_int {
    e(sys_getsockname(sock_fd, addr, addrlen))
}
#[no_mangle]
pub unsafe extern "C" fn getpeername(
    sock_fd: c_int,
    addr: *mut ctypes::sockaddr,
    addrlen: *mut ctypes::socklen_t,
) -> c_int {
    e(sys_getpeername(sock_fd, addr, addrlen))
}
#[no_mangle]
pub unsafe extern "C" fn ax_sendmsg(
    socket_fd: c_int,
    msg: *const ctypes::msghdr,
    flags: c_int,
) -> ctypes::ssize_t {
    e(sys_sendmsg(socket_fd, msg, flags) as _) as _
}