#pragma once

#include <optional>
#include <vector>
#include <vulkan/vulkan_core.h>

#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>

const std::vector<const char*> DeviceExtensions = {
	VK_KHR_SWAPCHAIN_EXTENSION_NAME
};
//
// struct SwapChainSupportDetails
// {
// 	VkSurfaceCapabilitiesKHR		Capabilities;
// 	std::vector<VkSurfaceFormatKHR> Formats;
// 	std::vector<VkPresentModeKHR>	PresentModes;
// };

struct FSwapConfig
{
	VkDevice						Device;
	VkSurfaceKHR					Surface;
	GLFWwindow*						Window;
	std::optional<uint32_t>			GraphicsFamily;
	std::optional<uint32_t>			PresentFamily;
	VkSurfaceCapabilitiesKHR		Capabilities;
	std::vector<VkSurfaceFormatKHR> Formats;
	std::vector<VkPresentModeKHR>	PresentModes;
};

class VulkanSwapChain
{
public:
	VulkanSwapChain();
	~VulkanSwapChain();

	void Initialize(FSwapConfig InConfig);

	// void Initialize(
	// 	VkDevice	 InDevice,
	// 	VkSurfaceKHR InSurface,
	// 	GLFWwindow*	 InWindow);

	void Cleanup();

	void CreateSwapChain();
	// void CreateSwapChain(
	// 	std::optional<uint32_t>			GraphicsFamily,
	// 	std::optional<uint32_t>			PresentFamily,
	// 	VkSurfaceCapabilitiesKHR		Capabilities,
	// 	std::vector<VkSurfaceFormatKHR> Formats,
	// 	std::vector<VkPresentModeKHR>	PresentModes);

	void CreateImageViews();

	// void RecreateSwapChain();

	VkSwapchainKHR			 GetSwapChain() { return SwapChain; }
	VkFormat				 GetSwapChainImageFormat() { return SwapChainImageFormat; }
	VkExtent2D				 GetSwapChainExtent() { return SwapChainExtent; }
	std::vector<VkImageView> GetSwapChainImageViews() { return SwapChainImageViews; }

private:
	FSwapConfig SwapConfig;
	// VkPhysicalDevice PhysicalDevice;
	// VkDevice		 Device;
	// VkSurfaceKHR	 Surface;
	//
	// GLFWwindow* Window = nullptr;

	std::vector<VkImage> SwapChainImages;
	VkSwapchainKHR		 SwapChain = VK_NULL_HANDLE;
	VkFormat			 SwapChainImageFormat;
	VkExtent2D			 SwapChainExtent;

	std::vector<VkImageView> SwapChainImageViews;

	// bool IsDeviceSuitable(VkPhysicalDevice Device);
	//
	// int RateDeviceSuitability(VkPhysicalDevice Device);
	//
	// bool CheckDeviceExtensionSupport(VkPhysicalDevice Device);

	// SwapChainSupportDetails QuerySwapChainSupport(VkPhysicalDevice Device);

	VkSurfaceFormatKHR ChooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& AvailableFormats);

	VkPresentModeKHR ChooseSwapPresentMode(const std::vector<VkPresentModeKHR>& AvailablePresentModes);

	VkExtent2D ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& Capabilities);
};
