package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.GPUSynchronisation;

import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.vulkan.VkFenceCreateInfo;

import java.nio.LongBuffer;

import static net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils.vkCheck;
import static org.lwjgl.vulkan.VK13.vkResetFences;
import static org.lwjgl.vulkan.VK13.vkWaitForFences;
import static org.lwjgl.vulkan.VK13.vkDestroyFence;
import static org.lwjgl.vulkan.VK13.VK_FENCE_CREATE_SIGNALED_BIT;
import static org.lwjgl.vulkan.VK13.vkCreateFence;

public class Fence {
    private final long VulkanFence;
    public Fence(VulkanContext vulkanContext, boolean Signaled){
        try(var MemStack = MemoryStack.stackPush()){
            var VulkanFenceCreateInfo = VkFenceCreateInfo.calloc(MemStack)
                    .sType$Default()
                    .flags(Signaled ? VK_FENCE_CREATE_SIGNALED_BIT : 0);
            LongBuffer LongPointers = MemStack.mallocLong(1);
            vkCheck(vkCreateFence(vulkanContext.GetDevice().FetchVulkanDevice(),VulkanFenceCreateInfo, null, LongPointers),"Failed to create Vulkan Fence");
            VulkanFence = LongPointers.get(0);
        }
    }

    public void cleanup(VulkanContext vulkanContext){
        vkDestroyFence(vulkanContext.GetDevice().FetchVulkanDevice(), VulkanFence, null);
    }

    public void FenceWait(VulkanContext vulkanContext){
        vkWaitForFences(vulkanContext.GetDevice().FetchVulkanDevice(), VulkanFence,true,Long.MAX_VALUE);
    }

    public long GetVulkanFence(){
        return VulkanFence;
    }

    public void Reset(VulkanContext vulkanContext){
        vkResetFences(vulkanContext.GetDevice().FetchVulkanDevice(), VulkanFence);
    }
}
