use crate::error::{Error, Result};
use crate::raw;
use crate::{IoctlFlags, Uffd};
use bitflags::bitflags;
use nix::errno::Errno;
use std::fs::{File, OpenOptions};
use std::io::ErrorKind;
use std::os::fd::AsRawFd;

const UFFD_DEVICE_PATH: &str = "/dev/userfaultfd";

cfg_if::cfg_if! {
    if #[cfg(any(feature = "linux5_7", feature = "linux4_14"))] {
        bitflags! {
            /// Used with `UffdBuilder` to determine which features are available in the current kernel.
            #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
            pub struct FeatureFlags: u64 {
                const PAGEFAULT_FLAG_WP = raw::UFFD_FEATURE_PAGEFAULT_FLAG_WP;
                const EVENT_FORK = raw::UFFD_FEATURE_EVENT_FORK;
                const EVENT_REMAP = raw::UFFD_FEATURE_EVENT_REMAP;
                const EVENT_REMOVE = raw::UFFD_FEATURE_EVENT_REMOVE;
                const MISSING_HUGETLBFS = raw::UFFD_FEATURE_MISSING_HUGETLBFS;
                const MISSING_SHMEM = raw::UFFD_FEATURE_MISSING_SHMEM;
                const EVENT_UNMAP = raw::UFFD_FEATURE_EVENT_UNMAP;
                const SIGBUS = raw::UFFD_FEATURE_SIGBUS;
                const THREAD_ID = raw::UFFD_FEATURE_THREAD_ID;
            }
        }
    } else {
        bitflags! {
            /// Used with `UffdBuilder` to determine which features are available in the current kernel.
            #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
            pub struct FeatureFlags: u64 {
                const PAGEFAULT_FLAG_WP = raw::UFFD_FEATURE_PAGEFAULT_FLAG_WP;
                const EVENT_FORK = raw::UFFD_FEATURE_EVENT_FORK;
                const EVENT_REMAP = raw::UFFD_FEATURE_EVENT_REMAP;
                const EVENT_REMOVE = raw::UFFD_FEATURE_EVENT_REMOVE;
                const MISSING_HUGETLBFS = raw::UFFD_FEATURE_MISSING_HUGETLBFS;
                const MISSING_SHMEM = raw::UFFD_FEATURE_MISSING_SHMEM;
                const EVENT_UNMAP = raw::UFFD_FEATURE_EVENT_UNMAP;
            }
        }
    }
}
/// A builder for initializing `Uffd` objects.
///
/// ```
/// use userfaultfd::UffdBuilder;
///
/// let uffd = UffdBuilder::new()
///     .close_on_exec(true)
///     .non_blocking(true)
///     .user_mode_only(true)
///     .create();
/// assert!(uffd.is_ok());
/// ```
pub struct UffdBuilder {
    close_on_exec: bool,
    non_blocking: bool,
    user_mode_only: bool,
    req_features: FeatureFlags,
    req_ioctls: IoctlFlags,
}

impl UffdBuilder {
    /// Create a new builder with no required features or ioctls, `close_on_exec` and
    /// `non_blocking` both set to `false`, and `user_mode_only` set to `true`.
    pub fn new() -> UffdBuilder {
        UffdBuilder {
            close_on_exec: false,
            non_blocking: false,
            user_mode_only: true,
            req_features: FeatureFlags::empty(),
            req_ioctls: IoctlFlags::empty(),
        }
    }

    /// Enable the close-on-exec flag for the new userfaultfd object (see the description of
    /// `O_CLOEXEC` in [`open(2)`](http://man7.org/linux/man-pages/man2/open.2.html)).
    pub fn close_on_exec(&mut self, close_on_exec: bool) -> &mut Self {
        self.close_on_exec = close_on_exec;
        self
    }

    /// Enable non-blocking operation for the userfaultfd object.
    ///
    /// If this is set to `false`, `Uffd::read_event()` will block until an event is available to
    /// read. Otherwise, it will immediately return `None` if no event is available.
    pub fn non_blocking(&mut self, non_blocking: bool) -> &mut Self {
        self.non_blocking = non_blocking;
        self
    }

    /// Enable user-mode only flag for the userfaultfd object.
    ///
    /// If set to `false`, the process must have the `CAP_SYS_PTRACE` capability starting with Linux 5.11
    /// or object creation will fail with EPERM. When set to `true`, userfaultfd can't be used
    /// to handle kernel-mode page faults such as when kernel tries copying data to userspace.
    ///
    /// When used with kernels older than 5.11, this has no effect; the process doesn't need
    /// `CAP_SYS_PTRACE` and can handle kernel-mode page faults.
    pub fn user_mode_only(&mut self, user_mode_only: bool) -> &mut Self {
        self.user_mode_only = user_mode_only;
        self
    }

    /// Add a requirement that a particular feature or set of features is available.
    ///
    /// If a required feature is unavailable, `UffdBuilder.create()` will return an error.
    pub fn require_features(&mut self, feature: FeatureFlags) -> &mut Self {
        self.req_features |= feature;
        self
    }

    /// Add a requirement that a particular ioctl or set of ioctls is available.
    ///
    /// If a required ioctl is unavailable, `UffdBuilder.create()` will return an error.
    pub fn require_ioctls(&mut self, ioctls: IoctlFlags) -> &mut Self {
        self.req_ioctls |= ioctls;
        self
    }

    fn uffd_from_dev(&self, file: &mut File, flags: i32) -> Result<Uffd> {
        match unsafe { raw::new_uffd(file.as_raw_fd(), flags) } {
            Err(err) => Err(err.into()),
            Ok(fd) => Ok(Uffd { fd }),
        }
    }

    fn uffd_from_syscall(&self, flags: i32) -> Result<Uffd> {
        let fd = match Errno::result(unsafe { raw::userfaultfd(flags) }) {
            Ok(fd) => fd,
            // setting the USER_MODE_ONLY flag on kernel pre-5.11 causes it to return EINVAL.
            // If the user asks for the flag, we first try with it set, and if kernel gives
            // EINVAL we try again without the flag set.
            Err(Errno::EINVAL) if self.user_mode_only => Errno::result(unsafe {
                raw::userfaultfd(flags & !raw::UFFD_USER_MODE_ONLY as i32)
            })?,
            Err(e) => return Err(e.into()),
        };

        // Wrap the fd up so that a failure in this function body closes it with the drop.
        Ok(Uffd { fd })
    }

    // Try to get a UFFD file descriptor using `/dev/userfaultfd`. If that fails
    // fall back to calling the system call.
    fn open_file_descriptor(&self, flags: i32) -> Result<Uffd> {
        // If `/dev/userfaultfd` exists we'll try to get the file descriptor from it. If the file
        // doesn't exist we will fall back to calling the system call. This means, that if the
        // device exists but the calling process does not have access rights to it, this will fail,
        // i.e. we will not fall back to calling the system call.
        match OpenOptions::new()
            .read(true)
            .write(true)
            .open(UFFD_DEVICE_PATH)
        {
            Ok(mut file) => self.uffd_from_dev(&mut file, flags),
            Err(err) if err.kind() == ErrorKind::NotFound => self.uffd_from_syscall(flags),
            Err(err) => Err(Error::OpenDevUserfaultfd(err)),
        }
    }

    /// Create a `Uffd` object with the current settings of this builder.
    pub fn create(&self) -> Result<Uffd> {
        // first do the syscall to get the file descriptor
        let mut flags = 0;
        if self.close_on_exec {
            flags |= libc::O_CLOEXEC;
        }
        if self.non_blocking {
            flags |= libc::O_NONBLOCK;
        }

        if self.user_mode_only {
            flags |= raw::UFFD_USER_MODE_ONLY as i32;
        }

        let uffd = self.open_file_descriptor(flags)?;

        // then do the UFFDIO_API ioctl to set up and ensure features and other ioctls are available
        let mut api = raw::uffdio_api {
            api: raw::UFFD_API,
            features: self.req_features.bits(),
            ioctls: 0,
        };
        unsafe {
            raw::api(uffd.fd, &mut api as *mut raw::uffdio_api)?;
        }
        let supported = IoctlFlags::from_bits_retain(api.ioctls);
        if !supported.contains(self.req_ioctls) {
            Err(Error::UnsupportedIoctls(supported))
        } else {
            Ok(uffd)
        }
    }
}
