// =====================================================================================================================
//  fennec, a free and open source game engine
//  Copyright © 2025  Medusa Slockbower
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================

///
/// \file enum.h
/// \brief
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///


#ifndef FENNEC_RENDERERS_VULKAN_LIB_ENUM_H
#define FENNEC_RENDERERS_VULKAN_LIB_ENUM_H

#include <fennec/renderers/vulkan/lib/forward.h>

namespace fennec::vk
{

// Objects =============================================================================================================

///
/// \brief An enum representing the Vulkan object types
enum object_ : uint32_t {
    object_unknown                      = VK_OBJECT_TYPE_UNKNOWN,                      //!< Unknown type
    object_instance                     = VK_OBJECT_TYPE_INSTANCE,                     //!< Vulkan Instance
    object_physical_device              = VK_OBJECT_TYPE_PHYSICAL_DEVICE,              //!< Physical Device
    object_logical_device               = VK_OBJECT_TYPE_DEVICE,                       //!< Logical Device
    object_queue                        = VK_OBJECT_TYPE_QUEUE,                        //!< Queue
    object_semaphore                    = VK_OBJECT_TYPE_SEMAPHORE,                    //!< Semaphore
    object_command_buffer               = VK_OBJECT_TYPE_COMMAND_BUFFER,               //!< Command Buffer
    object_fence                        = VK_OBJECT_TYPE_FENCE,                        //!< Fence
    object_device_memory                = VK_OBJECT_TYPE_DEVICE_MEMORY,                //!< Device Memory
    object_buffer                       = VK_OBJECT_TYPE_BUFFER,                       //!< Buffer
    object_image                        = VK_OBJECT_TYPE_IMAGE,                        //!< Image
    object_event                        = VK_OBJECT_TYPE_EVENT,                        //!< Event
    object_query_pool                   = VK_OBJECT_TYPE_QUERY_POOL,                   //!< Query Pool
    object_buffer_view                  = VK_OBJECT_TYPE_BUFFER_VIEW,                  //!< Buffer View
    object_image_view                   = VK_OBJECT_TYPE_IMAGE_VIEW,                   //!< Image View
    object_shader_module                = VK_OBJECT_TYPE_SHADER_MODULE,                //!< Shader Module
    object_pipeline_cache               = VK_OBJECT_TYPE_PIPELINE_CACHE,               //!< Pipeline Cache
    object_pipeline_layout              = VK_OBJECT_TYPE_PIPELINE_LAYOUT,              //!< Pipeline Layout
    object_render_pass                  = VK_OBJECT_TYPE_RENDER_PASS,                  //!< Render Pass
    object_pipeline                     = VK_OBJECT_TYPE_PIPELINE,                     //!< Pipeline
    object_descriptor_set_layout        = VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT,        //!< Descriptor Set
    object_sampler                      = VK_OBJECT_TYPE_SAMPLER,                      //!< Sampler
    object_descriptor_pool              = VK_OBJECT_TYPE_DESCRIPTOR_POOL,              //!< Descriptor Pool
    object_descriptor_set               = VK_OBJECT_TYPE_DESCRIPTOR_SET,               //!< Descriptor Set
    object_framebuffer                  = VK_OBJECT_TYPE_FRAMEBUFFER,                  //!< Framebuffer
    object_command_pool                 = VK_OBJECT_TYPE_COMMAND_POOL,                 //!< Command Pool
    object_sampler_ycbcr_conversion     = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION,     //!< YCBCR Conversion Sampler
    object_descriptor_update_template   = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE,   //!< Descriptor Update Template
    object_private_data_slot            = VK_OBJECT_TYPE_PRIVATE_DATA_SLOT,            //!< Private Data Slot
    object_debug_report_callback_ext    = VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT,    //!< Debug Report Callback
    object_debug_utils_messenger_ext    = VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT,    //!< Debug Utility Messenger
    object_validation_cache_ext         = VK_OBJECT_TYPE_VALIDATION_CACHE_EXT,         //!< Validation Cache
	object_micromap_ext                 = VK_OBJECT_TYPE_MICROMAP_EXT,                 //!< Micro-Map
    object_shader_ext                   = VK_OBJECT_TYPE_SHADER_EXT,                   //!< Shader
    object_indirect_commands_layout_ext = VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_EXT, //!< Indirect Commands Layout
	object_indirect_execution_set_ext   = VK_OBJECT_TYPE_INDIRECT_EXECUTION_SET_EXT,   //!< Indirect Execution Set

	object_surface                  = VK_OBJECT_TYPE_SURFACE_KHR,       //!< Surface
	object_swapchain                = VK_OBJECT_TYPE_SWAPCHAIN_KHR,     //!< Swap-chain
	object_display                  = VK_OBJECT_TYPE_DISPLAY_KHR,       //!< Display
	object_display_mode             = VK_OBJECT_TYPE_DISPLAY_MODE_KHR,  //!< Display Mode
	object_video_session            = VK_OBJECT_TYPE_VIDEO_SESSION_KHR, //!< Video Session
	object_video_session_parameters = VK_OBJECT_TYPE_VIDEO_SESSION_PARAMETERS_KHR, //!< Video Session Parameters
    object_acceleration_structure   = VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR,   //!< Acceleration Structure
    object_deferred_operation       = VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR,       //!< Deferred Operation
    object_pipeline_binary          = VK_OBJECT_TYPE_PIPELINE_BINARY_KHR,          //!< Pipeline Binary

    object_acceleration_structure_NV   = VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV,   //!< NV Acceleration Structure
	object_indirect_commands_layout_NV = VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NV, //!< NV Indirect Commands Layout
    object_optical_flow_session_NV     = VK_OBJECT_TYPE_OPTICAL_FLOW_SESSION_NV,     //!< NV Optical Flow Session
	object_external_compute_queue_NV   = VK_OBJECT_TYPE_EXTERNAL_COMPUTE_QUEUE_NV,   //!< NV External Compute Queue

	object_cu_module_NVX = VK_OBJECT_TYPE_CU_MODULE_NVX,     //!< NVX CU Module
    object_cu_function_NVX = VK_OBJECT_TYPE_CU_FUNCTION_NVX, //!< NVX CU Function

    object_performance_configuration_INTEL = VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL, //!< Intel Performance Configuration

    object_buffer_collection_FUCHSIA = VK_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA, //!< Fuchsia Buffer Collection

	object_tensor_ARM = VK_OBJECT_TYPE_TENSOR_ARM,                                           //!< ARM Tensor
	object_tensor_view_ARM = VK_OBJECT_TYPE_TENSOR_VIEW_ARM,                                 //!< ARM Tensor View
	object_data_graph_pipeline_session_ARM = VK_OBJECT_TYPE_DATA_GRAPH_PIPELINE_SESSION_ARM, //!< ARM Data Graph Pipeline Session

	// Beta Extensions
#ifdef VK_ENABLE_BETA_EXTENSIONS
	object_cuda_module_NV   = VK_OBJECT_TYPE_CUDA_MODULE_NV,   //!< NV Cuda Module
	object_cuda_function_NV = VK_OBJECT_TYPE_CUDA_FUNCTION_NV, //!< NV Cuda Function
#endif
};

inline cstring object_string(uint32_t flag) {
	switch (flag) {
		default:
		case object_unknown:                      return "Unknown";
		case object_instance:                     return "Instance";
		case object_physical_device:              return "Physical Device";
		case object_logical_device:               return "Logical Device";
		case object_queue:                        return "Queue";
		case object_semaphore:                    return "Semaphore";
		case object_command_buffer:               return "Command Buffer";
		case object_fence:                        return "Fence";
		case object_device_memory:                return "Device Memory";
		case object_buffer:                       return "Buffer";
		case object_image:                        return "Image";
		case object_event:                        return "Event";
		case object_query_pool:                   return "Query Pool";
		case object_buffer_view:                  return "Buffer View";
		case object_image_view:                   return "Image View";
		case object_shader_module:                return "Shader Module";
		case object_pipeline_cache:               return "Pipeline Cache";
		case object_pipeline_layout:              return "Pipeline Layout";
		case object_render_pass:                  return "Render Pass";
		case object_pipeline:                     return "Pipeline";
		case object_descriptor_set_layout:        return "Descriptor Set Layout";
		case object_sampler:                      return "Sampler";
		case object_descriptor_pool:              return "Descriptor Pool";
		case object_descriptor_set:               return "Descriptor Set";
		case object_framebuffer:                  return "Framebuffer";
		case object_command_pool:                 return "Command Pool";
		case object_sampler_ycbcr_conversion:     return "YCBCR Conversion Sampler";
		case object_descriptor_update_template:   return "Descriptor Update Template";
		case object_private_data_slot:            return "Private Data Slot";
		case object_debug_report_callback_ext:    return "Report Callback";
		case object_debug_utils_messenger_ext:    return "Debug Messenger";
		case object_validation_cache_ext:         return "Validation Cache";
		case object_micromap_ext:                 return "Micro-Map";
		case object_shader_ext:                   return "Shader";
		case object_indirect_commands_layout_ext: return "Indirect Commands Layout";
		case object_indirect_execution_set_ext:   return "Indirect Execution Set";

		case object_surface:                  return "Surface";
		case object_swapchain:                return "Swap-Chain";
		case object_display:                  return "Display";
		case object_display_mode:             return "Display Mode";
		case object_video_session:            return "Video Session";
		case object_video_session_parameters: return "Video Session Parameters";
		case object_acceleration_structure:   return "Acceleration Structure";
		case object_deferred_operation:       return "Deferred Operation";
		case object_pipeline_binary:          return "Pipeline Binary";

		case object_acceleration_structure_NV:   return "NV Acceleration Structure";
		case object_indirect_commands_layout_NV: return "NV Indirect Commands Layout";
		case object_optical_flow_session_NV:     return "NV Optical Flow Session";
		case object_external_compute_queue_NV:   return "NV External Compute Queue";

		case object_cu_module_NVX:   return "NVX CU Module";
		case object_cu_function_NVX: return "NVX CU Function";

		case object_performance_configuration_INTEL: return "Intel Performance Configuration";

		case object_buffer_collection_FUCHSIA: return "Fuchsia Buffer Collection";

		case object_tensor_ARM:                      return "ARM Tensor";
		case object_tensor_view_ARM:                 return "ARM Tensor View";
		case object_data_graph_pipeline_session_ARM: return "ARM Data Graph Pipeline Session";

		// Beta Extensions
#ifdef VK_ENABLE_BETA_EXTENSIONS
		case object_cuda_module_NV:   return "NV CUDA Module",
		case object_cuda_function_NV: return "NV CUDA Function",
#endif
	}
}

// Physical Devices ====================================================================================================

///
/// \brief An enum representing the Vulkan physical device types
enum device_ : uint32_t {
	device_other      = VK_PHYSICAL_DEVICE_TYPE_OTHER,          //!< Other Type
	device_integrated = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU, //!< Integrated GPU
	device_discrete   = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,   //!< Discrete / Dedicated GPU
	device_virtual    = VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU,    //!< Virtualized / Software GPU
	device_cpu        = VK_PHYSICAL_DEVICE_TYPE_CPU,            //!< CPU
};

///
/// \brief Get a descriptor string for the provided device type.
/// \param type The device type.
/// \returns A cstring containing a short description.
inline cstring device_string(uint32_t type) {
	switch (type) {
		default:
		case device_other:      return "Other";
		case device_integrated: return "iGPU";
		case device_discrete:   return "dGPU";
		case device_virtual:    return "Virtual";
		case device_cpu:        return "CPU";
	}
}



// Instances ===========================================================================================================

///
/// \brief An enum representing the Vulkan instance creation flags
enum instance_flag_ : uint32_t {
	instance_flag_portability = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR, //!< Portability, allow non-conformant devices

	instance_flag_none = 0,                         //!< No flags
	instance_flag_all  = instance_flag_portability, //!< All flags
};


///
/// \brief Get a descriptor string for the provided device type.
/// \param flag The instance flag.
/// \returns A cstring containing a short description.
inline cstring instance_flag_string(uint32_t flag) {
	switch (flag) {
		default:
		case instance_flag_none:        return "None";
		case instance_flag_portability: return "Portability";

		// TODO: Multi-Flags

		//case instance_flag_all:         return cstring("All");
	}
}



// Debugging ===========================================================================================================

///
/// \brief An enum representing the Vulkan debug message severity flags
enum debug_message_severity_ : uint32_t {
	debug_message_severity_verbose = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT, //!< Verbose Message
	debug_message_severity_info    = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT,    //!< Info Message
	debug_message_severity_warning = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT, //!< Warning Message
	debug_message_severity_error   = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,   //!< Error Message

	debug_message_severity_none = 0, //!< No flags

	debug_message_severity_all = debug_message_severity_verbose
	                           | debug_message_severity_info
	                           | debug_message_severity_warning
	                           | debug_message_severity_error, //!< All flags
};

///
/// \brief Get a descriptor string for the provided message severity.
/// \param flag The severity flag.
/// \returns A cstring containing a short description.
inline cstring message_severity_string(uint32_t flag) {
	switch (flag) {
		default:
		case debug_message_severity_none:    return "None";
		case debug_message_severity_verbose: return "Verbose";
		case debug_message_severity_info:    return "Info";
		case debug_message_severity_warning: return "Warning";
		case debug_message_severity_error:   return "Error";

		// TODO: Multi-Flags

		case debug_message_severity_all: return "All";
	}
}



///
/// \brief An enum representing the Vulkan debug message type flags
enum debug_message_type_ : uint32_t {
	debug_message_type_general     = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,     //!< General Message
	debug_message_type_validation  = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,  //!< Validation Message
	debug_message_type_performance = VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, //!< Performance Message

	debug_message_type_none = 0, //!< No flags

	debug_message_type_all = debug_message_type_general
	                       | debug_message_type_validation
	                       | debug_message_type_performance, //!< All flags
};

///
/// \brief Get a descriptor string for the provided message type.
/// \param flag The type flag.
/// \returns A cstring containing a short description.
inline cstring message_type_string(uint32_t flag) {
	switch (flag) {
		default:
		case debug_message_type_none:        return "None";
		case debug_message_type_general:     return "General";
		case debug_message_type_validation:  return "Validation";
		case debug_message_type_performance: return "Performance";

		// TODO: Multi-Flags

		case debug_message_type_all: return "All";
	}
}


///
/// \brief An enum representing the Vulkan debug report flags
enum debug_report_ : uint32_t {
	debug_report_information = VK_DEBUG_REPORT_INFORMATION_BIT_EXT,         //!< Information Report
	debug_report_warning     = VK_DEBUG_REPORT_WARNING_BIT_EXT,             //!< Warning Report
	debug_report_performance = VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, //!< Performance Warning Report
	debug_report_error       = VK_DEBUG_REPORT_ERROR_BIT_EXT,               //!< Error Report
	debug_report_debug       = VK_DEBUG_REPORT_DEBUG_BIT_EXT,               //!< Debug Report

	debug_report_none = 0, //!< No flags
	debug_report_all  = debug_report_information
	                  | debug_report_warning
	                  | debug_report_performance
	                  | debug_report_error
	                  | debug_report_debug, //!< All flags
};

///
/// \brief Get a descriptor string for the provided report type.
/// \param flag The type flag.
/// \returns A cstring containing a short description.
inline cstring report_string(uint32_t flag) {
	switch (flag) {
		default:
		case debug_report_none:        return "None";
		case debug_report_information: return "Information";
		case debug_report_warning:     return "Warning";
		case debug_report_performance: return "Performance";
		case debug_report_error:       return "Error";
		case debug_report_debug:       return "Debug";

		// TODO: Multi-Flags

		case debug_report_all:         return "All";
	}
}

}

#endif // FENNEC_RENDERERS_VULKAN_LIB_ENUM_H