package org.xbib.net.socket.v4.unix;

import com.sun.jna.LastErrorException;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import java.io.IOException;
import java.net.Socket;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.xbib.net.socket.NetworkUnreachableException;
import org.xbib.net.socket.v4.datagram.DatagramPacket;
import static org.xbib.net.socket.v4.Constants.AF_UNIX;

public class NativeUnixSocket extends Socket {

    static {
        Native.register((String) null);
    }

    private static final Logger logger = Logger.getLogger(NativeUnixSocket.class.getName());

    private final int socket;

    private volatile boolean closed;

    public NativeUnixSocket(String path, int type, int protocol) {
        try {
            this.socket = socket(AF_UNIX, type, protocol);
            if (socket < 0) {
                throw new IllegalStateException("socket < 0");
            }
            SocketAddressUnix socketAddressUnix = new SocketAddressUnix(path);
            connect(socket, socketAddressUnix);
            closed = false;
        } catch (LastErrorException e) {
            logger.log(Level.SEVERE, e.getMessage(), e);
            throw e;
        }
    }

    public native int connect(int socket, SocketAddressUnix socketAddressUnix) throws LastErrorException;

    public native int socket(int domain, int type, int protocol) throws LastErrorException;

    public native int setsockopt(int socket, int level, int option_name, Pointer value, int option_len);

    public native int sendto(int socket, Buffer buffer, int buflen, int flags, SocketAddressUnix socketAddressUnix) throws LastErrorException;

    public native int recvfrom(int socket, Buffer buffer, int buflen, int flags, SocketAddressInternet in_addr, int[] in_addr_len) throws LastErrorException;

    public native int close(int socket) throws LastErrorException;

    public native String strerror(int errnum);
    @Override
    public void close() throws IOException {
        super.close();
        closed = true;
        close(socket);
    }
}
