// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use crate::check_errors;
use crate::device::physical::QueueFamily;
use crate::device::Device;
use crate::device::DeviceOwned;
use crate::Error;
use crate::OomError;
use crate::Version;
use crate::VulkanObject;
use smallvec::SmallVec;
use std::error;
use std::fmt;
use std::marker::PhantomData;
use std::mem::MaybeUninit;
use std::ptr;
use std::sync::Arc;
use std::vec::IntoIter as VecIntoIter;

/// Low-level implementation of a command pool.
///
/// A command pool is always tied to a specific queue family. Command buffers allocated from a pool
/// can only be executed on the corresponding queue family.
///
/// This struct doesn't implement the `Sync` trait because Vulkan command pools are not thread
/// safe. In other words, you can only use a pool from one thread at a time.
#[derive(Debug)]
pub struct UnsafeCommandPool {
    pool: ash::vk::CommandPool,
    device: Arc<Device>,

    // Index of the associated queue family in the physical device.
    queue_family_index: u32,

    // We don't want `UnsafeCommandPool` to implement Sync.
    // This marker unimplements both Send and Sync, but we reimplement Send manually right under.
    dummy_avoid_sync: PhantomData<*const u8>,
}

unsafe impl Send for UnsafeCommandPool {}

impl UnsafeCommandPool {
    /// Creates a new pool.
    ///
    /// The command buffers created with this pool can only be executed on queues of the given
    /// family.
    ///
    /// Setting `transient` to true is a hint to the implementation that the command buffers will
    /// be short-lived.
    /// Setting `reset_cb` to true means that command buffers can be reset individually.
    ///
    /// # Panic
    ///
    /// - Panics if the queue family doesn't belong to the same physical device as `device`.
    ///
    pub fn new(
        device: Arc<Device>,
        queue_family: QueueFamily,
        transient: bool,
        reset_cb: bool,
    ) -> Result<UnsafeCommandPool, OomError> {
        assert_eq!(
            device.physical_device().internal_object(),
            queue_family.physical_device().internal_object(),
            "Device doesn't match physical device when creating a command pool"
        );

        let fns = device.fns();

        let flags = {
            let flag1 = if transient {
                ash::vk::CommandPoolCreateFlags::TRANSIENT
            } else {
                ash::vk::CommandPoolCreateFlags::empty()
            };
            let flag2 = if reset_cb {
                ash::vk::CommandPoolCreateFlags::RESET_COMMAND_BUFFER
            } else {
                ash::vk::CommandPoolCreateFlags::empty()
            };
            flag1 | flag2
        };

        let pool = unsafe {
            let infos = ash::vk::CommandPoolCreateInfo {
                flags: flags,
                queue_family_index: queue_family.id(),
                ..Default::default()
            };

            let mut output = MaybeUninit::uninit();
            check_errors(fns.v1_0.create_command_pool(
                device.internal_object(),
                &infos,
                ptr::null(),
                output.as_mut_ptr(),
            ))?;
            output.assume_init()
        };

        Ok(UnsafeCommandPool {
            pool: pool,
            device: device.clone(),
            queue_family_index: queue_family.id(),
            dummy_avoid_sync: PhantomData,
        })
    }

    /// Resets the pool, which resets all the command buffers that were allocated from it.
    ///
    /// If `release_resources` is true, it is a hint to the implementation that it should free all
    /// the memory internally allocated for this pool.
    ///
    /// # Safety
    ///
    /// The command buffers allocated from this pool jump to the initial state.
    ///
    pub unsafe fn reset(&self, release_resources: bool) -> Result<(), OomError> {
        let flags = if release_resources {
            ash::vk::CommandPoolResetFlags::RELEASE_RESOURCES
        } else {
            ash::vk::CommandPoolResetFlags::empty()
        };

        let fns = self.device.fns();
        check_errors(
            fns.v1_0
                .reset_command_pool(self.device.internal_object(), self.pool, flags),
        )?;
        Ok(())
    }

    /// Trims a command pool, which recycles unused internal memory from the command pool back to
    /// the system.
    ///
    /// Command buffers allocated from the pool are not affected by trimming.
    ///
    /// This function is supported only if the `VK_KHR_maintenance1` extension was enabled at
    /// device creation. Otherwise an error is returned.
    /// Since this operation is purely an optimization it is legitimate to call this function and
    /// simply ignore any possible error.
    pub fn trim(&self) -> Result<(), CommandPoolTrimError> {
        unsafe {
            if !(self.device.api_version() >= Version::V1_1
                || self.device.enabled_extensions().khr_maintenance1)
            {
                return Err(CommandPoolTrimError::Maintenance1ExtensionNotEnabled);
            }

            let fns = self.device.fns();

            if self.device.api_version() >= Version::V1_1 {
                fns.v1_1.trim_command_pool(
                    self.device.internal_object(),
                    self.pool,
                    ash::vk::CommandPoolTrimFlags::empty(),
                );
            } else {
                fns.khr_maintenance1.trim_command_pool_khr(
                    self.device.internal_object(),
                    self.pool,
                    ash::vk::CommandPoolTrimFlagsKHR::empty(),
                );
            }

            Ok(())
        }
    }

    /// Allocates `count` command buffers.
    ///
    /// If `secondary` is true, allocates secondary command buffers. Otherwise, allocates primary
    /// command buffers.
    pub fn alloc_command_buffers(
        &self,
        secondary: bool,
        count: u32,
    ) -> Result<UnsafeCommandPoolAllocIter, OomError> {
        if count == 0 {
            return Ok(UnsafeCommandPoolAllocIter {
                device: self.device.clone(),
                list: vec![].into_iter(),
            });
        }

        let infos = ash::vk::CommandBufferAllocateInfo {
            command_pool: self.pool,
            level: if secondary {
                ash::vk::CommandBufferLevel::SECONDARY
            } else {
                ash::vk::CommandBufferLevel::PRIMARY
            },
            command_buffer_count: count,
            ..Default::default()
        };

        unsafe {
            let fns = self.device.fns();
            let mut out = Vec::with_capacity(count as usize);
            check_errors(fns.v1_0.allocate_command_buffers(
                self.device.internal_object(),
                &infos,
                out.as_mut_ptr(),
            ))?;

            out.set_len(count as usize);

            Ok(UnsafeCommandPoolAllocIter {
                device: self.device.clone(),
                list: out.into_iter(),
            })
        }
    }

    /// Frees individual command buffers.
    ///
    /// # Safety
    ///
    /// The command buffers must have been allocated from this pool. They must not be in use.
    ///
    pub unsafe fn free_command_buffers<I>(&self, command_buffers: I)
    where
        I: Iterator<Item = UnsafeCommandPoolAlloc>,
    {
        let command_buffers: SmallVec<[_; 4]> =
            command_buffers.map(|cb| cb.command_buffer).collect();
        let fns = self.device.fns();
        fns.v1_0.free_command_buffers(
            self.device.internal_object(),
            self.pool,
            command_buffers.len() as u32,
            command_buffers.as_ptr(),
        )
    }

    /// Returns the queue family on which command buffers of this pool can be executed.
    #[inline]
    pub fn queue_family(&self) -> QueueFamily {
        self.device
            .physical_device()
            .queue_family_by_id(self.queue_family_index)
            .unwrap()
    }
}

unsafe impl DeviceOwned for UnsafeCommandPool {
    #[inline]
    fn device(&self) -> &Arc<Device> {
        &self.device
    }
}

unsafe impl VulkanObject for UnsafeCommandPool {
    type Object = ash::vk::CommandPool;

    #[inline]
    fn internal_object(&self) -> ash::vk::CommandPool {
        self.pool
    }
}

impl Drop for UnsafeCommandPool {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let fns = self.device.fns();
            fns.v1_0
                .destroy_command_pool(self.device.internal_object(), self.pool, ptr::null());
        }
    }
}

/// Opaque type that represents a command buffer allocated from a pool.
pub struct UnsafeCommandPoolAlloc {
    command_buffer: ash::vk::CommandBuffer,
    device: Arc<Device>,
}

unsafe impl DeviceOwned for UnsafeCommandPoolAlloc {
    #[inline]
    fn device(&self) -> &Arc<Device> {
        &self.device
    }
}

unsafe impl VulkanObject for UnsafeCommandPoolAlloc {
    type Object = ash::vk::CommandBuffer;

    #[inline]
    fn internal_object(&self) -> ash::vk::CommandBuffer {
        self.command_buffer
    }
}

/// Iterator for newly-allocated command buffers.
#[derive(Debug)]
pub struct UnsafeCommandPoolAllocIter {
    device: Arc<Device>,
    list: VecIntoIter<ash::vk::CommandBuffer>,
}

impl Iterator for UnsafeCommandPoolAllocIter {
    type Item = UnsafeCommandPoolAlloc;

    #[inline]
    fn next(&mut self) -> Option<UnsafeCommandPoolAlloc> {
        self.list
            .next()
            .map(|command_buffer| UnsafeCommandPoolAlloc {
                command_buffer,
                device: self.device.clone(),
            })
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.list.size_hint()
    }
}

impl ExactSizeIterator for UnsafeCommandPoolAllocIter {}

/// Error that can happen when trimming command pools.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum CommandPoolTrimError {
    /// The `KHR_maintenance1` extension was not enabled.
    Maintenance1ExtensionNotEnabled,
}

impl error::Error for CommandPoolTrimError {}

impl fmt::Display for CommandPoolTrimError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(
            fmt,
            "{}",
            match *self {
                CommandPoolTrimError::Maintenance1ExtensionNotEnabled => {
                    "the `KHR_maintenance1` extension was not enabled"
                }
            }
        )
    }
}

impl From<Error> for CommandPoolTrimError {
    #[inline]
    fn from(err: Error) -> CommandPoolTrimError {
        panic!("unexpected error: {:?}", err)
    }
}

#[cfg(test)]
mod tests {
    use crate::command_buffer::pool::CommandPoolTrimError;
    use crate::command_buffer::pool::UnsafeCommandPool;
    use crate::Version;

    #[test]
    fn basic_create() {
        let (device, queue) = gfx_dev_and_queue!();
        let _ = UnsafeCommandPool::new(device, queue.family(), false, false).unwrap();
    }

    #[test]
    fn queue_family_getter() {
        let (device, queue) = gfx_dev_and_queue!();
        let pool = UnsafeCommandPool::new(device, queue.family(), false, false).unwrap();
        assert_eq!(pool.queue_family().id(), queue.family().id());
    }

    #[test]
    fn panic_if_not_match_family() {
        let (device, _) = gfx_dev_and_queue!();
        let (_, queue) = gfx_dev_and_queue!();

        assert_should_panic!(
            "Device doesn't match physical device when creating a command pool",
            {
                let _ = UnsafeCommandPool::new(device, queue.family(), false, false);
            }
        );
    }

    #[test]
    fn check_maintenance_when_trim() {
        let (device, queue) = gfx_dev_and_queue!();
        let pool = UnsafeCommandPool::new(device.clone(), queue.family(), false, false).unwrap();

        if device.api_version() >= Version::V1_1 {
            match pool.trim() {
                Err(CommandPoolTrimError::Maintenance1ExtensionNotEnabled) => panic!(),
                _ => (),
            }
        } else {
            match pool.trim() {
                Err(CommandPoolTrimError::Maintenance1ExtensionNotEnabled) => (),
                _ => panic!(),
            }
        }
    }

    // TODO: test that trim works if VK_KHR_maintenance1 if enabled ; the test macro doesn't
    //       support enabling extensions yet

    #[test]
    fn basic_alloc() {
        let (device, queue) = gfx_dev_and_queue!();
        let pool = UnsafeCommandPool::new(device, queue.family(), false, false).unwrap();
        let iter = pool.alloc_command_buffers(false, 12).unwrap();
        assert_eq!(iter.count(), 12);
    }
}
