// 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::format::ClearValue;
use crate::image::traits::ImageAccess;
use crate::image::traits::ImageClearValue;
use crate::image::traits::ImageContent;
use crate::image::ImageDescriptorLayouts;
use crate::image::ImageInner;
use crate::image::ImageLayout;
use crate::swapchain::Swapchain;
use crate::sync::AccessError;
use crate::OomError;
use std::hash::Hash;
use std::hash::Hasher;
use std::sync::Arc;

/// An image that is part of a swapchain.
///
/// Creating a `SwapchainImage` is automatically done when creating a swapchain.
///
/// A swapchain image is special in the sense that it can only be used after being acquired by
/// calling the `acquire` method on the swapchain. You have no way to know in advance which
/// swapchain image is going to be acquired, so you should keep all of them alive.
///
/// After a swapchain image has been acquired, you are free to perform all the usual operations
/// on it. When you are done you can then *present* the image (by calling the corresponding
/// method on the swapchain), which will have the effect of showing the content of the image to
/// the screen. Once an image has been presented, it can no longer be used unless it is acquired
/// again.
// TODO: #[derive(Debug)]
pub struct SwapchainImage<W> {
    swapchain: Arc<Swapchain<W>>,
    image_offset: usize,
}

impl<W> SwapchainImage<W> {
    /// Builds a `SwapchainImage` from raw components.
    ///
    /// This is an internal method that you shouldn't call.
    pub unsafe fn from_raw(
        swapchain: Arc<Swapchain<W>>,
        id: usize,
    ) -> Result<Arc<SwapchainImage<W>>, OomError> {
        let image = swapchain.raw_image(id).unwrap();

        Ok(Arc::new(SwapchainImage {
            swapchain: swapchain.clone(),
            image_offset: id,
        }))
    }

    /// Returns the dimensions of the image.
    ///
    /// A `SwapchainImage` is always two-dimensional.
    #[inline]
    pub fn dimensions(&self) -> [u32; 2] {
        let dims = self.my_image().image.dimensions();
        [dims.width(), dims.height()]
    }

    /// Returns the swapchain this image belongs to.
    #[inline]
    pub fn swapchain(&self) -> &Arc<Swapchain<W>> {
        &self.swapchain
    }

    #[inline]
    fn my_image(&self) -> ImageInner {
        self.swapchain.raw_image(self.image_offset).unwrap()
    }

    #[inline]
    fn layout_initialized(&self) {
        self.swapchain.image_layout_initialized(self.image_offset);
    }

    #[inline]
    fn is_layout_initialized(&self) -> bool {
        self.swapchain
            .is_image_layout_initialized(self.image_offset)
    }
}

unsafe impl<W> ImageAccess for SwapchainImage<W> {
    #[inline]
    fn inner(&self) -> ImageInner {
        self.my_image()
    }

    #[inline]
    fn initial_layout_requirement(&self) -> ImageLayout {
        ImageLayout::PresentSrc
    }

    #[inline]
    fn final_layout_requirement(&self) -> ImageLayout {
        ImageLayout::PresentSrc
    }

    #[inline]
    fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
        Some(ImageDescriptorLayouts {
            storage_image: ImageLayout::ShaderReadOnlyOptimal,
            combined_image_sampler: ImageLayout::ShaderReadOnlyOptimal,
            sampled_image: ImageLayout::ShaderReadOnlyOptimal,
            input_attachment: ImageLayout::ShaderReadOnlyOptimal,
        })
    }

    #[inline]
    fn conflict_key(&self) -> u64 {
        self.my_image().image.key()
    }

    #[inline]
    fn try_gpu_lock(&self, _: bool, _: bool, _: ImageLayout) -> Result<(), AccessError> {
        if self.swapchain.is_fullscreen_exclusive() {
            Ok(())
        } else {
            // Swapchain image are only accessible after being acquired.
            Err(AccessError::SwapchainImageAcquireOnly)
        }
    }

    #[inline]
    unsafe fn layout_initialized(&self) {
        self.layout_initialized();
    }

    #[inline]
    fn is_layout_initialized(&self) -> bool {
        self.is_layout_initialized()
    }

    #[inline]
    unsafe fn increase_gpu_lock(&self) {}

    #[inline]
    unsafe fn unlock(&self, _: Option<ImageLayout>) {
        // TODO: store that the image was initialized
    }

    #[inline]
    fn current_miplevels_access(&self) -> std::ops::Range<u32> {
        0..self.mipmap_levels()
    }

    #[inline]
    fn current_layer_levels_access(&self) -> std::ops::Range<u32> {
        0..1
    }
}

unsafe impl<W> ImageClearValue<ClearValue> for SwapchainImage<W> {
    #[inline]
    fn decode(&self, value: ClearValue) -> Option<ClearValue> {
        Some(self.swapchain.format().decode_clear_value(value))
    }
}

unsafe impl<P, W> ImageContent<P> for SwapchainImage<W> {
    #[inline]
    fn matches_format(&self) -> bool {
        true // FIXME:
    }
}

impl<W> PartialEq for SwapchainImage<W> {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ImageAccess::inner(self) == ImageAccess::inner(other)
    }
}

impl<W> Eq for SwapchainImage<W> {}

impl<W> Hash for SwapchainImage<W> {
    #[inline]
    fn hash<H: Hasher>(&self, state: &mut H) {
        ImageAccess::inner(self).hash(state);
    }
}
