use vulkano::{
    device::{
        Device as VkDevice, DeviceCreateInfo,
        QueueFlags, QueueCreateInfo,
        physical::PhysicalDevice as VkPhysicalDevice,
    },
    instance::{Instance as VkInstance, InstanceCreateFlags, InstanceCreateInfo},
    memory::allocator::StandardMemoryAllocator,
    Version,
    VulkanLibrary,
    VulkanObject,
};
use std::sync::Arc;

pub struct Device {
    handle:Arc<VkPhysicalDevice>,
    name:String,
    
    queue_transfer:Vec<usize>,
    queue_graphics:Vec<usize>,
    queue_compute:Vec<usize>,

    usable:bool,
}

pub struct Vulkan {
    instance:Arc<VkInstance>,

    devices:Vec<Device>,
}
impl Vulkan {
    pub fn init() -> Result<Self,()>
    {
        if let Ok(library) = VulkanLibrary::new() {
            if let Ok(instance) = VkInstance::new(
                library,
                InstanceCreateInfo {
                    flags:InstanceCreateFlags::ENUMERATE_PORTABILITY,
                    ..Default::default()
                }
            ) {
                return Ok(Self {
                    instance,

                    devices:Vec::new(),
                });
            }
        }
        Err(())
    }

    pub fn enumerate_devices(&mut self) -> usize
    {
        self.devices.clear();
        if let Ok(devices) = self.instance.enumerate_physical_devices() {
            for device in devices {

                let mut queue_transfer = Vec::new();
                let mut queue_graphics = Vec::new();
                let mut queue_compute = Vec::new();

                let mut index = 0;
                for family in device.queue_family_properties() {
                    if family.queue_flags.contains(QueueFlags::TRANSFER) {
                        queue_transfer.push(index);
                    }
                    if family.queue_flags.contains(QueueFlags::GRAPHICS) {
                        queue_graphics.push(index);
                    }
                    if family.queue_flags.contains(QueueFlags::COMPUTE) {
                        queue_compute.push(index);
                    }

                    index += 1;
                }

                let usable = queue_graphics.len() > 0;

                self.devices.push(Device {
                    name:device.properties().device_name.clone(),
                    handle:device,
                    
                    queue_transfer,
                    queue_graphics,
                    queue_compute,

                    usable,
                })
            }
        }
        self.devices.len()
    }

    pub fn init_context(&mut self, device:usize, queue_family_index:u32) -> Result<usize,()>
    {
        // Acquire device and queues
        if let Ok((device, mut queues)) = VkDevice::new(
            self.devices[device].handle.clone(),
            DeviceCreateInfo {
                queue_create_infos:vec![QueueCreateInfo {
                    queue_family_index,
                    ..Default::default()
                }],
                ..Default::default()
            }
        ) {
            let queue = queues.next().unwrap();
            
        }

        Err(())
    }
}
