package jnr.posix;

import jnr.constants.platform.AddressFamily;
import jnr.constants.platform.PosixFadvise;
import jnr.constants.platform.OpenFlags;
import jnr.constants.platform.Sock;
import jnr.constants.platform.SocketLevel;
import jnr.constants.platform.SocketOption;
import jnr.ffi.Platform;
import jnr.posix.util.ConditionalTestRule;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.io.File;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Lock;

import static jnr.posix.LinuxIoPrio.*;

public class LinuxPOSIXTest {

    @ClassRule
    public static RunningOnLinux rule = new RunningOnLinux();

    private static Linux linuxPOSIX = null;

    @BeforeClass
    public static void setUpClass() throws Exception {
        POSIX posix = POSIXFactory.getNativePOSIX();

        if (posix instanceof Linux) {
            linuxPOSIX = (Linux) posix;
        }
    }

    /**
     * Tests that IO priority can be set to a thread and that it doesn't change priority set on
     * another thread
     * @throws InterruptedException
     * @throws ExecutionException
     */
    @Test
    public void ioprioThreadedTest() throws InterruptedException, ExecutionException {
        linuxPOSIX.ioprio_set(IOPRIO_WHO_PROCESS, 0, IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4));

        Future<Integer> threadPriorityFuture = Executors.newFixedThreadPool(1).submit(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                linuxPOSIX.ioprio_set(IOPRIO_WHO_PROCESS, 0, IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 7));
                return linuxPOSIX.ioprio_get(IOPRIO_WHO_PROCESS, 0);
            }
        });

        int threadPriority = threadPriorityFuture.get().intValue();

        Assert.assertEquals(7, IOPRIO_PRIO_DATA(threadPriority));
        Assert.assertEquals(IOPRIO_CLASS_IDLE, IOPRIO_PRIO_CLASS(threadPriority));
        Assert.assertEquals(4, IOPRIO_PRIO_DATA(linuxPOSIX.ioprio_get(IOPRIO_WHO_PROCESS, 0)));
        Assert.assertEquals(IOPRIO_CLASS_BE, IOPRIO_PRIO_CLASS(linuxPOSIX.ioprio_get(IOPRIO_WHO_PROCESS, 0)));
    }

    @Test
    public void testMessageHdrMultipleControl() {
        if (jnr.posix.util.Platform.IS_WINDOWS) {
            return;
        }

        int[] fds = {0, 0};

        int ret = linuxPOSIX.socketpair(AddressFamily.AF_UNIX.intValue(),
                Sock.SOCK_STREAM.intValue(),
                0,
                fds);


        String data = "twoControlMessages";
        byte[] dataBytes = data.getBytes();

        Assert.assertTrue(ret >= 0);
        Assert.assertTrue(fds[0] > 0);
        Assert.assertTrue(fds[1] > 0);

        ByteBuffer buf = ByteBuffer.allocate(4);
        buf.order(ByteOrder.nativeOrder());
        buf.putInt(1).flip();

        ret = linuxPOSIX.libc().setsockopt(fds[1],
                SocketLevel.SOL_SOCKET.intValue(),
                SocketOption.SO_PASSCRED.intValue(),
                buf,
                buf.remaining());

        Assert.assertTrue(ret >= 0);

        MsgHdr outMessage = linuxPOSIX.allocateMsgHdr();

        ByteBuffer[] outIov = new ByteBuffer[1];
        outIov[0] = ByteBuffer.allocateDirect(dataBytes.length);
        outIov[0].put(dataBytes);
        outIov[0].flip();

        outMessage.setIov(outIov);

        CmsgHdr[] outControl = outMessage.allocateControls(new int[]{4});
        outControl[0].setLevel(SocketLevel.SOL_SOCKET.intValue());
        outControl[0].setType(0x01);

        ByteBuffer fdBuf = ByteBuffer.allocateDirect(4);
        fdBuf.order(ByteOrder.nativeOrder());
        fdBuf.putInt(0, fds[0]);
        outControl[0].setData(fdBuf);

        int sendStatus = linuxPOSIX.sendmsg(fds[0], outMessage, 0);
        if (sendStatus == -1) {
            String sendmsgError = "Error with sendmsg: " + linuxPOSIX.strerror(linuxPOSIX.errno());
            Assert.fail(sendmsgError);
            return;
        }

        Assert.assertEquals(dataBytes.length, sendStatus);

        // ----------------

        MsgHdr inMessage = linuxPOSIX.allocateMsgHdr();
        ByteBuffer[] inIov = new ByteBuffer[1];
        inIov[0] = ByteBuffer.allocateDirect(1024);
        inMessage.setIov(inIov);

        inMessage.allocateControls(new int[]{4, 12});
        int recvStatus = linuxPOSIX.recvmsg(fds[1], inMessage, 0);

        Assert.assertEquals(dataBytes.length, recvStatus);

        Assert.assertEquals(2, inMessage.getControls().length);

        CmsgHdr[] controls = inMessage.getControls();
        for (int x = 0; x < controls.length; x++) {
            validateCmsghdr(controls[x]);
        }
    }

    private void validateCmsghdr(CmsgHdr control) {
        if (control.getLevel() == SocketLevel.SOL_SOCKET.intValue()
                && control.getType() == 0x01) {
            // Passing a FD
            ByteBuffer inFdBuf = control.getData();
            inFdBuf.order(ByteOrder.nativeOrder());

            int fd = inFdBuf.getInt();

            Assert.assertTrue(fd != 0);
        } else if (control.getLevel() == SocketLevel.SOL_SOCKET.intValue()
                && control.getType() == 0x02) {
            //Credentials
            ByteBuffer data = control.getData();
            data.order(ByteOrder.nativeOrder());

            int got_pid = data.getInt();
            int got_uid = data.getInt();
            int got_gid = data.getInt();

            Assert.assertEquals(linuxPOSIX.getpid(), got_pid);
            Assert.assertEquals(linuxPOSIX.getuid(), got_uid);
            Assert.assertEquals(linuxPOSIX.getgid(), got_gid);
        } else {
            Assert.fail("Unable to determine cmsghdr type");
        }
    }

    @Test
    public void testPosixFadvise() throws Throwable {
        File file = File.createTempFile("posix_fadvise", null);
        int fd = linuxPOSIX.open(file.getAbsolutePath(), OpenFlags.O_RDWR.intValue(), 0444);

        Assert.assertEquals(0, linuxPOSIX.posix_fadvise(fd, 0, 0, PosixFadvise.POSIX_FADV_SEQUENTIAL));
        Assert.assertEquals(0, linuxPOSIX.posix_fadvise(fd, 0, 0, PosixFadvise.POSIX_FADV_RANDOM));
        Assert.assertEquals(0, linuxPOSIX.posix_fadvise(fd, 0, 0, PosixFadvise.POSIX_FADV_NOREUSE));
        Assert.assertEquals(0, linuxPOSIX.posix_fadvise(fd, 0, 0, PosixFadvise.POSIX_FADV_WILLNEED));
        Assert.assertEquals(0, linuxPOSIX.posix_fadvise(fd, 0, 0, PosixFadvise.POSIX_FADV_DONTNEED));
        Assert.assertEquals(0, linuxPOSIX.posix_fadvise(fd, 0, 0, PosixFadvise.POSIX_FADV_NORMAL)); // normal last to reset it

        linuxPOSIX.close(fd);
    }
}

class RunningOnLinux extends ConditionalTestRule {
    public boolean isSatisfied() {
        return jnr.ffi.Platform.getNativePlatform().getOS().equals(Platform.OS.LINUX);
    }
}
