// Copyright (c) 2017 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 smallvec::SmallVec;
use std::error;
use std::fmt;
use std::marker::PhantomData;
use std::ptr;

use crate::device::DeviceOwned;
use crate::device::Queue;
use crate::swapchain::PresentRegion;
use crate::swapchain::Swapchain;
use crate::sync::Semaphore;

use crate::check_errors;
use crate::Error;
use crate::OomError;
use crate::SynchronizedVulkanObject;
use crate::VulkanObject;

/// Prototype for a submission that presents a swapchain on the screen.
// TODO: example here
pub struct SubmitPresentBuilder<'a> {
    wait_semaphores: SmallVec<[ash::vk::Semaphore; 8]>,
    swapchains: SmallVec<[ash::vk::SwapchainKHR; 4]>,
    image_indices: SmallVec<[u32; 4]>,
    present_regions: SmallVec<[ash::vk::PresentRegionKHR; 4]>,
    rect_layers: SmallVec<[ash::vk::RectLayerKHR; 4]>,
    marker: PhantomData<&'a ()>,
}

impl<'a> SubmitPresentBuilder<'a> {
    /// Builds a new empty `SubmitPresentBuilder`.
    #[inline]
    pub fn new() -> SubmitPresentBuilder<'a> {
        SubmitPresentBuilder {
            wait_semaphores: SmallVec::new(),
            swapchains: SmallVec::new(),
            image_indices: SmallVec::new(),
            present_regions: SmallVec::new(),
            rect_layers: SmallVec::new(),
            marker: PhantomData,
        }
    }

    /// Adds a semaphore to be waited upon before the presents are executed.
    ///
    /// # Safety
    ///
    /// - If you submit this builder, the semaphore must be kept alive until you are guaranteed
    ///   that the GPU has presented the swapchains.
    ///
    /// - If you submit this builder, no other queue must be waiting on these semaphores. In other
    ///   words, each semaphore signal can only correspond to one semaphore wait.
    ///
    /// - If you submit this builder, the semaphores must be signaled when the queue execution
    ///   reaches this submission, or there must be one or more submissions in queues that are
    ///   going to signal these semaphores. In other words, you must not block the queue with
    ///   semaphores that can't get signaled.
    ///
    /// - The swapchains and semaphores must all belong to the same device.
    ///
    #[inline]
    pub unsafe fn add_wait_semaphore(&mut self, semaphore: &'a Semaphore) {
        self.wait_semaphores.push(semaphore.internal_object());
    }

    /// Adds an image of a swapchain to be presented.
    ///
    /// Allows to specify a present region.
    /// Areas outside the present region *can* be ignored by the Vulkan implementation for
    /// optimizations purposes.
    ///
    /// If `VK_KHR_incremental_present` is not enabled, the `present_region` parameter is ignored.
    ///
    /// # Safety
    ///
    /// - If you submit this builder, the swapchain must be kept alive until you are
    ///   guaranteed that the GPU has finished presenting.
    ///
    /// - The swapchains and semaphores must all belong to the same device.
    ///
    #[inline]
    pub unsafe fn add_swapchain<W>(
        &mut self,
        swapchain: &'a Swapchain<W>,
        image_num: u32,
        present_region: Option<&'a PresentRegion>,
    ) {
        debug_assert!(image_num < swapchain.num_images());

        if swapchain
            .device()
            .enabled_extensions()
            .khr_incremental_present
        {
            let vk_present_region = match present_region {
                Some(present_region) => {
                    assert!(present_region.is_compatible_with(swapchain));
                    for rectangle in &present_region.rectangles {
                        self.rect_layers.push(rectangle.into());
                    }
                    ash::vk::PresentRegionKHR {
                        rectangle_count: present_region.rectangles.len() as u32,
                        // Set this to null for now; in submit fill it with self.rect_layers
                        p_rectangles: ptr::null(),
                    }
                }
                None => ash::vk::PresentRegionKHR {
                    rectangle_count: 0,
                    p_rectangles: ptr::null(),
                },
            };
            self.present_regions.push(vk_present_region);
        }

        self.swapchains.push(swapchain.internal_object());
        self.image_indices.push(image_num);
    }

    /// Submits the command. Calls `vkQueuePresentKHR`.
    ///
    /// # Panic
    ///
    /// Panics if no swapchain image has been added to the builder.
    ///
    pub fn submit(mut self, queue: &Queue) -> Result<(), SubmitPresentError> {
        unsafe {
            debug_assert_eq!(self.swapchains.len(), self.image_indices.len());
            assert!(
                !self.swapchains.is_empty(),
                "Tried to submit a present command without any swapchain"
            );

            let present_regions = {
                if !self.present_regions.is_empty() {
                    debug_assert!(queue.device().enabled_extensions().khr_incremental_present);
                    debug_assert_eq!(self.swapchains.len(), self.present_regions.len());
                    let mut current_index = 0;
                    for present_region in &mut self.present_regions {
                        present_region.p_rectangles = self.rect_layers[current_index..].as_ptr();
                        current_index += present_region.rectangle_count as usize;
                    }
                    Some(ash::vk::PresentRegionsKHR {
                        swapchain_count: self.present_regions.len() as u32,
                        p_regions: self.present_regions.as_ptr(),
                        ..Default::default()
                    })
                } else {
                    None
                }
            };

            let mut results = vec![ash::vk::Result::SUCCESS; self.swapchains.len()];

            let fns = queue.device().fns();
            let queue = queue.internal_object_guard();

            let infos = ash::vk::PresentInfoKHR {
                p_next: present_regions
                    .as_ref()
                    .map(|pr| pr as *const ash::vk::PresentRegionsKHR as *const _)
                    .unwrap_or(ptr::null()),
                wait_semaphore_count: self.wait_semaphores.len() as u32,
                p_wait_semaphores: self.wait_semaphores.as_ptr(),
                swapchain_count: self.swapchains.len() as u32,
                p_swapchains: self.swapchains.as_ptr(),
                p_image_indices: self.image_indices.as_ptr(),
                p_results: results.as_mut_ptr(),
                ..Default::default()
            };

            check_errors(fns.khr_swapchain.queue_present_khr(*queue, &infos))?;

            for result in results {
                check_errors(result)?;
            }

            Ok(())
        }
    }
}

impl<'a> fmt::Debug for SubmitPresentBuilder<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        fmt.debug_struct("SubmitPresentBuilder")
            .field("wait_semaphores", &self.wait_semaphores)
            .field("swapchains", &self.swapchains)
            .field("image_indices", &self.image_indices)
            .finish()
    }
}

/// Error that can happen when submitting the present prototype.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum SubmitPresentError {
    /// Not enough memory.
    OomError(OomError),

    /// The connection to the device has been lost.
    DeviceLost,

    /// The surface is no longer accessible and must be recreated.
    SurfaceLost,

    /// The swapchain has lost or doesn't have fullscreen exclusivity possibly for
    /// implementation-specific reasons outside of the application’s control.
    FullscreenExclusiveLost,

    /// The surface has changed in a way that makes the swapchain unusable. You must query the
    /// surface's new properties and recreate a new swapchain if you want to continue drawing.
    OutOfDate,
}

impl error::Error for SubmitPresentError {
    #[inline]
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        match *self {
            SubmitPresentError::OomError(ref err) => Some(err),
            _ => None,
        }
    }
}

impl fmt::Display for SubmitPresentError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(
            fmt,
            "{}",
            match *self {
                SubmitPresentError::OomError(_) => "not enough memory",
                SubmitPresentError::DeviceLost => "the connection to the device has been lost",
                SubmitPresentError::SurfaceLost =>
                    "the surface of this swapchain is no longer valid",
                SubmitPresentError::OutOfDate => "the swapchain needs to be recreated",
                SubmitPresentError::FullscreenExclusiveLost => {
                    "the swapchain no longer has fullscreen exclusivity"
                }
            }
        )
    }
}

impl From<Error> for SubmitPresentError {
    #[inline]
    fn from(err: Error) -> SubmitPresentError {
        match err {
            err @ Error::OutOfHostMemory => SubmitPresentError::OomError(OomError::from(err)),
            err @ Error::OutOfDeviceMemory => SubmitPresentError::OomError(OomError::from(err)),
            Error::DeviceLost => SubmitPresentError::DeviceLost,
            Error::SurfaceLost => SubmitPresentError::SurfaceLost,
            Error::OutOfDate => SubmitPresentError::OutOfDate,
            Error::FullscreenExclusiveLost => SubmitPresentError::FullscreenExclusiveLost,
            _ => panic!("unexpected error: {:?}", err),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn no_swapchain_added() {
        let (_, queue) = gfx_dev_and_queue!();
        assert_should_panic!("Tried to submit a present command without any swapchain", {
            let _ = SubmitPresentBuilder::new().submit(&queue);
        });
    }
}
