/**
 * MVGAL WoW64 Thunk Layer - Enhanced Implementation
 *
 * Bridges 32-bit Windows applications running under Wine/Proton to the 64-bit MVGAL runtime.
 * Handles:
 *   - Structure repacking (32-bit pointers to 64-bit)
 *   - Calling convention translation (stdcall to System V)
 *   - Handle mapping (32-bit to 64-bit)
 *   - Registry/INI emulation for GPU configuration
 *   - Gaming workload optimization for Steam/Proton integration
 *
 * SPDX-License-Identifier: MIT
 */

#ifndef MVGAL_WOW64_THUNK_H
#define MVGAL_WOW64_THUNK_H

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "mvgal_types.h"
#include "mvgal_gpu.h"
#include "mvgal_scheduler.h"

#ifdef __cplusplus
extern "C" {
#endif

/* ============================================================================
 * Enhanced WoW64 Handle Management
 * ============================================================================ */

/**
 * @brief Opaque handle types for WoW64 layer
 */
typedef struct mvgal_wow64_instance mvgal_wow64_instance_t;
typedef struct mvgal_wow64_device mvgal_wow64_device_t;
typedef struct mvgal_wow64_buffer mvgal_wow64_buffer_t;
typedef struct mvgal_wow64_queue mvgal_wow64_queue_t;

/**
 * @brief WoW64 fence structure
 */
struct mvgal_wow64_fence {
    bool signaled;                    ///< Fence signaled state
    uint32_t reserved;                ///< Reserved for alignment
};

typedef struct mvgal_wow64_fence mvgal_wow64_fence_t;
typedef struct mvgal_wow64_semaphore mvgal_wow64_semaphore_t;

/* ============================================================================
 * WoW64 Configuration for Gaming/Rendering
 * ============================================================================ */

typedef enum {
    MVGAL_WOW64_CONTEXT_UNKNOWN = 0,
    MVGAL_WOW64_CONTEXT_GAMING = 1,
    MVGAL_WOW64_CONTEXT_RENDERING = 2,
    MVGAL_WOW64_CONTEXT_COMPUTE = 3,
    MVGAL_WOW64_CONTEXT_BENCHMARK = 4
} mvgal_wow64_context_type_t;

typedef struct {
    mvgal_wow64_context_type_t context_type;
    bool enable_frame_pacing;     /* Enable frame pacing for gaming */
    bool enable_afr;              /* Enable alternate frame rendering */
    uint32_t gpu_mask;            /* Which GPUs to use (bitmask) */
    uint32_t strategy;            /* Scheduling strategy */
    float power_limit_scale;      /* Power limit scale (0.5-1.0) */
    bool enable_nvlink_sharing;   /* Prefer NVLink memory sharing */
    bool enable_p2p_transfers;    /* Enable peer-to-peer transfers */
} mvgal_wow64_config_t;

/* ============================================================================
 * WoW64 Instance Management
 * ============================================================================ */

/**
 * @brief Create a WoW64 instance
 * @return Instance handle or NULL on failure
 */
mvgal_wow64_instance_t* mvgal_wow64_create_instance(void);

/**
 * @brief Destroy a WoW64 instance
 * @param instance Instance to destroy
 */
void mvgal_wow64_destroy_instance(mvgal_wow64_instance_t* instance);

/* ============================================================================
 * WoW64 Device Management
 * ============================================================================ */

/**
 * @brief Create a WoW64 device
 * @param instance Parent instance
 * @param device_idx Device index (0-based)
 * @return Device handle or NULL on failure
 */
mvgal_wow64_device_t* mvgal_wow64_create_device(mvgal_wow64_instance_t* instance, uint32_t device_idx);

/**
 * @brief Destroy a WoW64 device
 * @param device Device to destroy
 */
void mvgal_wow64_destroy_device(mvgal_wow64_device_t* device);

/* ============================================================================
 * WoW64 Buffer Management
 * ============================================================================ */

/**
 * @brief Create a buffer in WoW64 address space
 * @param device Target device
 * @param size Buffer size
 * @param flags Buffer flags
 * @return Buffer handle or NULL on failure
 */
mvgal_wow64_buffer_t* mvgal_wow64_create_buffer(mvgal_wow64_device_t* device,
                                                 uint64_t size,
                                                 uint32_t flags);

/**
 * @brief Destroy a WoW64 buffer
 * @param buffer Buffer to destroy
 */
void mvgal_wow64_destroy_buffer(mvgal_wow64_buffer_t* buffer);

/**
 * @brief Map buffer to 32-bit address space
 * @param buffer Buffer to map
 * @param offset Offset in buffer
 * @param size Size to map
 * @param ptr Output pointer (32-bit address)
 * @return 0 on success, error code on failure
 */
int mvgal_wow64_map_buffer(mvgal_wow64_buffer_t* buffer,
                          uint64_t offset,
                          uint64_t size,
                          uint32_t* ptr);

/* ============================================================================
 * WoW64 Vulkan Thunk Functions
 * ============================================================================ */

/* These are designed to be called via __attribute__((stdcall)) from 32-bit code */

#ifndef MVGAL_WOW64_NO_STDAPI
#define MVGAL_WOW64_STDCALL __attribute__((stdcall))
#else
#define MVGAL_WOW64_STDCALL
#endif

/**
 * @brief 32-bit VkInstanceCreateInfo for thunking
 */
typedef struct {
    uint32_t sType;
    uint32_t pNext;
    uint32_t flags;
    uint32_t applicationInfo;
    uint32_t enabledLayerCount;
    uint32_t ppEnabledLayerNames;
    uint32_t enabledExtensionCount;
    uint32_t ppEnabledExtensionNames;
} VkInstanceCreateInfo32;

/**
 * @brief 32-bit VkApplicationInfo for thunking
 */
typedef struct {
    uint32_t sType;
    uint32_t pNext;
    uint32_t applicationName;
    uint32_t applicationVersion;
    uint32_t engineName;
    uint32_t engineVersion;
    uint32_t apiVersion;
} VkApplicationInfo32;

/**
 * @brief Thunk vkCreateInstance for 32-bit Wine applications
 * @param pCreateInfo32 32-bit instance create info
 * @param pAllocator32 32-bit allocator (optional)
 * @param pInstance Output instance handle
 * @return VK_SUCCESS on success, error code on failure
 */
int MVGAL_WOW64_STDCALL mvgal_wow64_vkCreateInstance(
    const VkInstanceCreateInfo32* pCreateInfo32,
    const VkInstanceCreateInfo32* pAllocator32,
    uint32_t* pInstance);

/**
 * @brief Thunk vkDestroyInstance for 32-bit Wine applications
 * @param instance Instance to destroy
 * @param pAllocator32 32-bit allocator (optional)
 */
void MVGAL_WOW64_STDCALL mvgal_wow64_vkDestroyInstance(
    uint32_t instance,
    const VkInstanceCreateInfo32* pAllocator32);

/**
 * @brief Thunk vkCreateDevice for 32-bit Wine applications
 * @param physicalDevice Physical device (physical device index in 32-bit space)
 * @param pCreateInfo32 32-bit device create info
 * @param pAllocator32 32-bit allocator (optional)
 * @param pDevice Output device handle
 * @return VK_SUCCESS on success, error code on failure
 */
int MVGAL_WOW64_STDCALL mvgal_wow64_vkCreateDevice(
    uint32_t physicalDevice,
    const VkInstanceCreateInfo32* pCreateInfo32,
    const VkInstanceCreateInfo32* pAllocator32,
    uint32_t* pDevice);

/**
 * @brief Thunk vkDestroyDevice for 32-bit Wine applications
 * @param device Device to destroy
 * @param pAllocator32 32-bit allocator (optional)
 */
void MVGAL_WOW64_STDCALL mvgal_wow64_vkDestroyDevice(
    uint32_t device,
    const VkInstanceCreateInfo32* pAllocator32);

/**
 * @brief Thunk vkAllocateMemory for 32-bit Wine applications
 * @param device Device handle
 * @param pAllocateInfo32 32-bit allocation info
 * @param pAllocator32 32-bit allocator (optional)
 * @param pMemory Output memory handle
 * @return VK_SUCCESS on success, error code on failure
 */
int MVGAL_WOW64_STDCALL mvgal_wow64_vkAllocateMemory(
    uint32_t device,
    const VkInstanceCreateInfo32* pAllocateInfo32,
    const VkInstanceCreateInfo32* pAllocator32,
    uint32_t* pMemory);

/**
 * @brief Thunk vkFreeMemory for 32-bit Wine applications
 * @param device Device handle
 * @param memory Memory to free
 * @param pAllocator32 32-bit allocator (optional)
 */
int MVGAL_WOW64_STDCALL mvgal_wow64_vkFreeMemory(
    uint32_t device,
    uint32_t memory,
    const VkInstanceCreateInfo32* pAllocator32);

/**
 * @brief Thunk vkGetDeviceQueue for 32-bit Wine applications
 * @param device Device handle
 * @param queueFamilyIndex Queue family index
 * @param queueIndex Queue index
 * @param pQueue Output queue handle
 */
void MVGAL_WOW64_STDCALL mvgal_wow64_vkGetDeviceQueue(
    uint32_t device,
    uint32_t queueFamilyIndex,
    uint32_t queueIndex,
    uint32_t* pQueue);

/**
 * @brief Thunk vkQueueSubmit for 32-bit Wine applications
 * @param queue Queue handle
 * @param submitCount Number of submits
 * @param pSubmits Submit info (32-bit pointers need repacking)
 * @param fence Fence to signal
 * @return VK_SUCCESS on success, error code on failure
 */
int MVGAL_WOW64_STDCALL mvgal_wow64_vkQueueSubmit(
    uint32_t queue,
    uint32_t submitCount,
    uint32_t pSubmits,
    uint32_t fence);

/* ============================================================================
 * WoW64 Utility Functions
 * ============================================================================ */

/**
 * @brief Convert 32-bit pointer to 64-bit
 * @param ptr32 32-bit pointer value
 * @return 64-bit pointer (zero-extended)
 */
static inline void* mvgal_wow64_ptr32_to_ptr64(uint32_t ptr32) {
    return (void*)(uintptr_t)ptr32;
}

/**
 * @brief Convert 64-bit pointer to 32-bit (for Wine address space)
 * @param ptr64 64-bit pointer value
 * @return 32-bit pointer (truncated - may lose bits!)
 */
static inline uint32_t mvgal_wow64_ptr64_to_ptr32(void* ptr64) {
    return (uint32_t)(uintptr_t)ptr64;
}

/**
 * @brief Check if running under WoW64 (32-bit app on 64-bit host)
 * @return true if WoW64 mode detected
 */
bool mvgal_wow64_is_active(void);

/**
 * @brief Initialize WoW64 layer (called automatically on first thunk)
 * @return true on success
 */
bool mvgal_wow64_init(void);

/**
 * @brief Shutdown WoW64 layer
 */
void mvgal_wow64_shutdown(void);

/* ============================================================================
 * WoW64 Configuration API (Enhanced)
 * ============================================================================ */

/**
 * @brief Initialize WoW64 layer with configuration
 * @param config Configuration for gaming/rendering workloads
 * @return true on success
 */
bool mvgal_wow64_init_with_config(const mvgal_wow64_config_t *config);

/**
 * @brief Set WoW64 configuration
 * @param config Configuration to apply
 * @return MVGAL_SUCCESS on success
 */
mvgal_error_t mvgal_wow64_set_config(const mvgal_wow64_config_t *config);

/**
 * @brief Get current WoW64 configuration
 * @param config Output: current configuration
 * @return MVGAL_SUCCESS on success
 */
mvgal_error_t mvgal_wow64_get_config(mvgal_wow64_config_t *config);

/* ============================================================================
 * Gaming-Specific Optimizations
 * ============================================================================ */

/**
 * @brief Frame pacing configuration
 */
typedef struct {
    bool enabled;              /* Enable frame pacing */
    uint64_t max_latency_ns;   /* Maximum frame latency in ns */
    uint32_t target_fps;       /* Target framerate */
} mvgal_frame_pacing_config_t;

/**
 * @brief Enable frame pacing for gaming workloads
 * @param enable true to enable frame pacing
 */
void mvgal_wow64_enable_frame_pacing(bool enable);

/**
 * @brief Enable frame pacing with configuration
 * @param config Frame pacing configuration
 * @return true on success
 */
bool mvgal_wow64_enable_frame_pacing_with_config(const mvgal_frame_pacing_config_t *config);

/**
 * @brief Set GPU mask for WoW64 workloads
 * @param mask Bitmask of GPUs to use
 */
void MVGAL_WOW64_STDCALL mvgal_wow64_set_gpu_mask(uint32_t mask);

/**
 * @brief Get optimal GPU count for the workload
 * @return Number of GPUs in bitmask
 */
uint32_t MVGAL_WOW64_STDCALL mvgal_wow64_get_gpu_count(void);

/**
 * @brief Detect Steam App ID for the current process
 * @return Steam App ID or 0 if not detected
 */
uint32_t mvgal_wow64_detect_steam_app_id(void);

/**
 * @brief Get game profile based on Steam App ID
 * @param app_id Steam App ID (0 for auto-detect)
 * @param workload_type Output workload type to use
 * @return Recommended distribution strategy
 */
mvgal_distribution_strategy_t mvgal_wow64_get_game_profile(
    uint32_t app_id,
    mvgal_workload_type_t *workload_type
);

/**
 * @brief Check if frame pacing is available
 * @return true if frame pacing can be enabled
 */
bool mvgal_wow64_can_frame_pace(void);

/**
 * @brief Update WoW64 configuration
 * @param config New configuration
 * @return true on success
 */
bool mvgal_wow64_update_config(const mvgal_wow64_config_t *config);

/**
 * @brief Get current GPU mask
 * @return GPU bitmask
 */
uint64_t mvgal_wow64_get_gpu_mask(void);

/**
 * @brief Estimate frame time for gaming workload
 * @param gpu0_time_ns GPU 0 frame time
 * @param gpu1_time_ns GPU 1 frame time
 * @return Estimated total frame time in ns
 */
uint64_t mvgal_wow64_estimate_frame_time_ns(uint64_t gpu0_time_ns, uint64_t gpu1_time_ns);

/* ============================================================================
 * WoW64 Fence and Semaphore Support
 * ============================================================================ */

int MVGAL_WOW64_STDCALL mvgal_wow64_vkCreateFence(
    uint32_t device,
    uint32_t pCreateInfo32,
    uint32_t pAllocator32,
    uint32_t pFence);

int MVGAL_WOW64_STDCALL mvgal_wow64_vkWaitForFences(
    uint32_t device,
    uint32_t fenceCount,
    uint32_t pFences,
    uint32_t waitAll,
    uint32_t timeout_ns);

void MVGAL_WOW64_STDCALL mvgal_wow64_vkDestroyFence(
    uint32_t device,
    uint32_t fence,
    uint32_t pAllocator32);

/* ============================================================================
 * Steam/Proton Integration Hooks
 * ============================================================================ */

/**
 * @brief Get Steam app ID from Wine registry (for optimization)
 * @return Steam App ID or 0 if not a Steam game
 */
uint32_t mvgal_wow64_get_steam_app_id(void);

/**
 * @brief Apply Steam app profile for optimized scheduling
 * @param app_id Steam App ID
 */
void mvgal_wow64_apply_steam_profile(uint32_t app_id);

#ifdef __cplusplus
}
#endif

#endif /* MVGAL_WOW64_THUNK_H */