/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

#pragma once

#include <vulkan/vulkan.hpp>
#include "DeviceManager.hpp"
#include "SwapChain.hpp"
#include "RenderPass.hpp"

namespace OpenVulkano
{
	class IVulkanWindow;
	class IGraphicsAppManager;

	namespace Vulkan
	{
		class Device;

		class Context final : public ICloseable
		{
			bool enableValidationLayer, initialized;
			std::set<std::string> requiredExtensions;
		public:
			DeviceManager deviceManager;
			vk::Instance instance; // Vulkan instance
			vk::DispatchLoaderDynamic dynamicDispatch; // for access to features not available in statically linked Vulkan lib
			vk::SurfaceKHR surface; // Vulkan surface to display framebuffer on
			std::shared_ptr<Device> device;
			SwapChain swapChain;
			RenderPass swapChainRenderPass;
			IVulkanWindow* window = nullptr;
			IGraphicsAppManager* graphicsAppManager = nullptr;

			Context() : initialized(false)
			{
#ifdef DEBUG
				enableValidationLayer = true;
#else
				enableValidationLayer = false;
#endif
			}

			~Context() override
			{
				if (initialized) Close();
			}

			void Init(IGraphicsAppManager* graphicsAppManager, IVulkanWindow* window);

			void Close() override;

			void Resize(uint32_t newWidth, uint32_t newHeight);

			void RequireExtension(const char* extension)
			{
				requiredExtensions.emplace(extension);
			}
		private:
			void CreateInstance();

			void CreateDevice();
		};
	}
}
