/**
 * @file mvgal_barrier_translate.h
 * @brief Cross-Vendor Barrier Translation - Phase 2
 *
 * Normalizes Vulkan pipeline barriers to a canonical form and emits
 * vendor-specific barrier commands.
 */

#ifndef MVGAL_BARRIER_TRANSLATE_H
#define MVGAL_BARRIER_TRANSLATE_H

#include <stdbool.h>
#include <stdint.h>
#include <vulkan/vulkan.h>
#include <mvgal/mvgal_types.h>

#ifdef __cplusplus
extern "C" {
#endif

/* ------------------------------------------------------------------ */
/*  Normalized Barrier Types                                             */
/* ------------------------------------------------------------------ */

typedef enum {
    MVGAL_BARRIER_MEMORY = 0,
    MVGAL_BARRIER_IMAGE = 1,
    MVGAL_BARRIER_BUFFER = 2,
    MVGAL_BARRIER_EVENT = 3,
} mvgal_barrier_type_t;

/* Normalized pipeline stage mask */
typedef enum {
    MVGAL_STAGE_TOP_OF_PIPE = 0x0001,
    MVGAL_STAGE_DRAW_INDIRECT = 0x0002,
    MVGAL_STAGE_VERTEX_INPUT = 0x0004,
    MVGAL_STAGE_VERTEX_SHADER = 0x0008,
    MVGAL_STAGE_TESS_CONTROL = 0x0010,
    MVGAL_STAGE_TESS_EVALUATION = 0x0020,
    MVGAL_STAGE_GEOMETRY_SHADER = 0x0040,
    MVGAL_STAGE_FRAGMENT_SHADER = 0x0080,
    MVGAL_STAGE_COMPUTE_SHADER = 0x0100,
    MVGAL_STAGE_TRANSFER = 0x0200,
    MVGAL_STAGE_BOTTOM_OF_PIPE = 0x0400,
    MVGAL_STAGE_HOST = 0x0800,
    MVGAL_STAGE_ALL_GRAPHICS = 0x1000,
    MVGAL_STAGE_ALL_COMMANDS = 0x2000,
} mvgal_stage_t;

/* Normalized access flags */
typedef enum {
    MVGAL_ACCESS_INDIRECT_COMMAND = 0x0001,
    MVGAL_ACCESS_INDEX_READ = 0x0002,
    MVGAL_ACCESS_VERTEX_ATTRIBUTE = 0x0004,
    MVGAL_ACCESS_UNIFORM_READ = 0x0008,
    MVGAL_ACCESS_SHADER_READ = 0x0010,
    MVGAL_ACCESS_SHADER_WRITE = 0x0020,
    MVGAL_ACCESS_COLOR_WRITE = 0x0040,
    MVGAL_ACCESS_DEPTH_STENCIL_WRITE = 0x0080,
    MVGAL_ACCESS_TRANSFER_READ = 0x0100,
    MVGAL_ACCESS_TRANSFER_WRITE = 0x0200,
    MVGAL_ACCESS_MEMORY_READ = 0x0400,
    MVGAL_ACCESS_MEMORY_WRITE = 0x0800,
} mvgal_access_t;

/* Normalized image layout */
typedef enum {
    MVGAL_LAYOUT_UNDEFINED = 0,
    MVGAL_LAYOUT_GENERAL = 1,
    MVGAL_LAYOUT_COLOR_ATTACHMENT = 2,
    MVGAL_LAYOUT_DEPTH_STENCIL_ATTACHMENT = 3,
    MVGAL_LAYOUT_DEPTH_STENCIL_READ_ONLY = 4,
    MVGAL_LAYOUT_SHADER_READ_ONLY = 5,
    MVGAL_LAYOUT_TRANSFER_SRC = 6,
    MVGAL_LAYOUT_TRANSFER_DST = 7,
    MVGAL_LAYOUT_PREINITIALIZED = 8,
} mvgal_layout_t;

/* ------------------------------------------------------------------ */
/*  Normalized Barrier Structure                                         */
/* ------------------------------------------------------------------ */

typedef struct {
    mvgal_barrier_type_t type;
    mvgal_stage_t src_stage;
    mvgal_stage_t dst_stage;
    mvgal_access_t src_access;
    mvgal_access_t dst_access;
    VkImageLayout src_layout;
    VkImageLayout dst_layout;
    VkImage image;
    uint32_t src_queue_family;
    uint32_t dst_queue_family;
    mvgal_vendor_t target_vendor;
} mvgal_normalized_barrier_t;

/* ------------------------------------------------------------------ */
/*  Stage/Access Normalization (inline for testing)                      */
/* ------------------------------------------------------------------ */

static inline mvgal_stage_t mvgal_normalize_stage(VkPipelineStageFlags stage)
{
    mvgal_stage_t result = 0;
    
    if (stage & VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT)
        result |= MVGAL_STAGE_TOP_OF_PIPE;
    if (stage & VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT)
        result |= MVGAL_STAGE_DRAW_INDIRECT;
    if (stage & VK_PIPELINE_STAGE_VERTEX_INPUT_BIT)
        result |= MVGAL_STAGE_VERTEX_INPUT;
    if (stage & VK_PIPELINE_STAGE_VERTEX_SHADER_BIT)
        result |= MVGAL_STAGE_VERTEX_SHADER;
    if (stage & VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT)
        result |= MVGAL_STAGE_TESS_CONTROL;
    if (stage & VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT)
        result |= MVGAL_STAGE_TESS_EVALUATION;
    if (stage & VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT)
        result |= MVGAL_STAGE_GEOMETRY_SHADER;
    if (stage & VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT)
        result |= MVGAL_STAGE_FRAGMENT_SHADER;
    if (stage & VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT)
        result |= MVGAL_STAGE_COMPUTE_SHADER;
    if (stage & VK_PIPELINE_STAGE_TRANSFER_BIT)
        result |= MVGAL_STAGE_TRANSFER;
    if (stage & VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT)
        result |= MVGAL_STAGE_BOTTOM_OF_PIPE;
    if (stage & VK_PIPELINE_STAGE_HOST_BIT)
        result |= MVGAL_STAGE_HOST;
    if (stage & VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT)
        result |= MVGAL_STAGE_ALL_GRAPHICS;
    if (stage & VK_PIPELINE_STAGE_ALL_COMMANDS_BIT)
        result |= MVGAL_STAGE_ALL_COMMANDS;
    
    return result;
}

static inline mvgal_access_t mvgal_normalize_access(VkAccessFlags access)
{
    mvgal_access_t result = 0;
    
    if (access & VK_ACCESS_INDIRECT_COMMAND_READ_BIT)
        result |= MVGAL_ACCESS_INDIRECT_COMMAND;
    if (access & VK_ACCESS_INDEX_READ_BIT)
        result |= MVGAL_ACCESS_INDEX_READ;
    if (access & VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT)
        result |= MVGAL_ACCESS_VERTEX_ATTRIBUTE;
    if (access & VK_ACCESS_UNIFORM_READ_BIT)
        result |= MVGAL_ACCESS_UNIFORM_READ;
    if (access & VK_ACCESS_SHADER_READ_BIT)
        result |= MVGAL_ACCESS_SHADER_READ;
    if (access & VK_ACCESS_SHADER_WRITE_BIT)
        result |= MVGAL_ACCESS_SHADER_WRITE;
    if (access & VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT)
        result |= MVGAL_ACCESS_COLOR_WRITE;
    if (access & VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT)
        result |= MVGAL_ACCESS_DEPTH_STENCIL_WRITE;
    if (access & VK_ACCESS_TRANSFER_READ_BIT)
        result |= MVGAL_ACCESS_TRANSFER_READ;
    if (access & VK_ACCESS_TRANSFER_WRITE_BIT)
        result |= MVGAL_ACCESS_TRANSFER_WRITE;
    if (access & VK_ACCESS_MEMORY_READ_BIT)
        result |= MVGAL_ACCESS_MEMORY_READ;
    if (access & VK_ACCESS_MEMORY_WRITE_BIT)
        result |= MVGAL_ACCESS_MEMORY_WRITE;
    
    return result;
}

/**
 * @brief Normalize a Vulkan memory barrier to canonical form
 * @param barrier Vulkan memory barrier (VkMemoryBarrier or VkMemoryBarrier2)
 * @param src_stage Source pipeline stage
 * @param dst_stage Destination pipeline stage
 * @param src_access Source access mask
 * @param dst_access Destination access mask
 * @param out Normalized barrier (out)
 */
void mvgal_normalize_memory_barrier(
    const VkMemoryBarrier *barrier,
    VkPipelineStageFlags src_stage,
    VkPipelineStageFlags dst_stage,
    VkAccessFlags src_access,
    VkAccessFlags dst_access,
    mvgal_normalized_barrier_t *out);

/**
 * @brief Normalize a Vulkan image barrier to canonical form
 * @param barrier Vulkan image barrier
 * @param src_stage Source pipeline stage mask
 * @param dst_stage Destination pipeline stage mask
 * @param out Normalized barrier (out)
 */
void mvgal_normalize_image_barrier(
    const VkImageMemoryBarrier *barrier,
    VkPipelineStageFlags src_stage,
    VkPipelineStageFlags dst_stage,
    mvgal_normalized_barrier_t *out);

/**
 * @brief Normalize a Vulkan buffer barrier to canonical form
 * @param barrier Vulkan buffer barrier
 * @param src_stage Source pipeline stage mask
 * @param dst_stage Destination pipeline stage mask
 * @param out Normalized barrier (out)
 */
void mvgal_normalize_buffer_barrier(
    const VkBufferMemoryBarrier *barrier,
    VkPipelineStageFlags src_stage,
    VkPipelineStageFlags dst_stage,
    mvgal_normalized_barrier_t *out);

/* ------------------------------------------------------------------ */
/*  Vendor-Specific Barrier Emission                                     */
/* ------------------------------------------------------------------ */

/**
 * @brief Emit a normalized barrier for AMD GPU
 * @param barrier Normalized barrier
 * @param cmd_buf Target command buffer
 * @return 0 on success, -1 on unsupported
 */
int mvgal_emit_amd_barrier(
    const mvgal_normalized_barrier_t *barrier,
    VkCommandBuffer cmd_buf);

/**
 * @brief Emit a normalized barrier for NVIDIA GPU
 * @param barrier Normalized barrier
 * @param cmd_buf Target command buffer
 * @return 0 on success, -1 on unsupported
 */
int mvgal_emit_nvidia_barrier(
    const mvgal_normalized_barrier_t *barrier,
    VkCommandBuffer cmd_buf);

/**
 * @brief Emit a normalized barrier for Intel GPU
 * @param barrier Normalized barrier
 * @param cmd_buf Target command buffer
 * @return 0 on success, -1 on unsupported
 */
int mvgal_emit_intel_barrier(
    const mvgal_normalized_barrier_t *barrier,
    VkCommandBuffer cmd_buf);

/**
 * @brief Emit a normalized barrier for MTT GPU
 * @param barrier Normalized barrier
 * @param cmd_buf Target command buffer
 * @return 0 on success, -1 on unsupported
 */
int mvgal_emit_mtt_barrier(
    const mvgal_normalized_barrier_t *barrier,
    VkCommandBuffer cmd_buf);

/**
 * @brief Dispatch barrier to appropriate vendor emitter
 * @param barrier Normalized barrier
 * @param cmd_buf Target command buffer
 * @return 0 on success, -1 on unsupported
 */
int mvgal_emit_barrier(
    const mvgal_normalized_barrier_t *barrier,
    VkCommandBuffer cmd_buf);

#ifdef __cplusplus
}
#endif

#endif /* MVGAL_BARRIER_TRANSLATE_H */