#ifndef RA_WRAPPER_H
#define RA_WRAPPER_H

#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

/* ============================================================================
 * Return Codes
 * ========================================================================= */

typedef enum {
    RA_OK = 0,
    RA_ERROR_INIT = -1,
    RA_ERROR_CORE_LOAD = -2,
    RA_ERROR_GAME_LOAD = -3,
    RA_ERROR_NO_CORE = -4,
    RA_ERROR_NO_GAME = -5,
    RA_ERROR_INVALID_PORT = -6,
    RA_ERROR_INVALID_PARAM = -7,
    RA_ERROR_ALREADY_INIT = -8,
    RA_ERROR_NOT_INIT = -9
} ra_result_t;

/* ============================================================================
 * Data Structures
 * ========================================================================= */

/* Pixel format */
typedef enum {
    RA_PIXEL_FORMAT_0RGB1555 = 0,  /* 16-bit */
    RA_PIXEL_FORMAT_XRGB8888 = 1,  /* 32-bit */
    RA_PIXEL_FORMAT_RGB565 = 2     /* 16-bit */
} ra_pixel_format_t;

/* Video frame */
typedef struct {
    const void *data;           /* Frame buffer (read-only) */
    size_t width;               /* Width in pixels */
    size_t height;              /* Height in pixels */
    size_t pitch;               /* Bytes per row */
    ra_pixel_format_t format;   /* Pixel format */
} ra_video_frame_t;

/* Audio frame */
typedef struct {
    const int16_t *data;        /* Interleaved stereo samples (L, R, L, R, ...) */
    size_t frames;              /* Number of stereo frames */
    double sample_rate;         /* Sample rate in Hz */
} ra_audio_frame_t;

/* System info */
typedef struct {
    const char *library_name;
    const char *library_version;
    const char *valid_extensions;
    bool need_fullpath;
} ra_system_info_t;

/* AV timing info */
typedef struct {
    double fps;                 /* Target frames per second */
    double sample_rate;         /* Audio sample rate */
    size_t base_width;          /* Base video width */
    size_t base_height;         /* Base video height */
    size_t max_width;           /* Maximum video width */
    size_t max_height;          /* Maximum video height */
    double aspect_ratio;        /* Pixel aspect ratio (0 = use base dimensions) */
} ra_av_info_t;

/* ============================================================================
 * Core Management
 * ========================================================================= */

/**
 * Initialize a libretro core.
 *
 * @param core_path Path to libretro core (.so/.dll/.dylib)
 * @return RA_OK on success
 */
ra_result_t ra_init_core(const char *core_path);

/**
 * Get system information from the core.
 *
 * @param info Structure to fill
 * @return RA_OK on success
 */
ra_result_t ra_get_system_info(ra_system_info_t *info);

/**
 * Get AV timing information (call after loading a game).
 *
 * @param info Structure to fill
 * @return RA_OK on success
 */
ra_result_t ra_get_av_info(ra_av_info_t *info);

/**
 * Shutdown the core and free resources.
 *
 * @return RA_OK on success
 */
ra_result_t ra_shutdown(void);

/* ============================================================================
 * Game Management
 * ========================================================================= */

/**
 * Load a game ROM.
 *
 * @param rom_path Path to ROM file
 * @return RA_OK on success
 */
ra_result_t ra_load_game(const char *rom_path);

/**
 * Unload the current game.
 *
 * @return RA_OK on success
 */
ra_result_t ra_unload_game(void);

/**
 * Reset the game to initial state.
 *
 * @return RA_OK on success
 */
ra_result_t ra_reset(void);

/* ============================================================================
 * Emulation
 * ========================================================================= */

/**
 * Advance emulation by one frame.
 *
 * @return RA_OK on success
 */
ra_result_t ra_step(void);

/**
 * Get the latest video frame (valid until next ra_step).
 *
 * @param frame Structure to fill
 * @return RA_OK on success
 */
ra_result_t ra_get_video_frame(ra_video_frame_t *frame);

/**
 * Get the latest audio samples (valid until next ra_step).
 *
 * @param audio Structure to fill
 * @return RA_OK on success
 */
ra_result_t ra_get_audio_frame(ra_audio_frame_t *audio);

/* ============================================================================
 * Input - Buttons
 * ========================================================================= */

/* Standard button IDs (matches libretro RETRO_DEVICE_ID_JOYPAD_*) */
typedef enum {
    RA_BUTTON_B = 0,
    RA_BUTTON_Y = 1,
    RA_BUTTON_SELECT = 2,
    RA_BUTTON_START = 3,
    RA_BUTTON_UP = 4,
    RA_BUTTON_DOWN = 5,
    RA_BUTTON_LEFT = 6,
    RA_BUTTON_RIGHT = 7,
    RA_BUTTON_A = 8,
    RA_BUTTON_X = 9,
    RA_BUTTON_L = 10,
    RA_BUTTON_R = 11,
    RA_BUTTON_L2 = 12,
    RA_BUTTON_R2 = 13,
    RA_BUTTON_L3 = 14,
    RA_BUTTON_R3 = 15
} ra_button_t;

/**
 * Set button state.
 *
 * @param port Controller port (0-3)
 * @param button Button ID
 * @param pressed True if pressed, false if released
 * @return RA_OK on success
 */
ra_result_t ra_set_button(uint32_t port, ra_button_t button, bool pressed);

/* ============================================================================
 * Input - Analog Sticks
 * ========================================================================= */

/* Analog stick selection */
typedef enum {
    RA_ANALOG_LEFT = 0,
    RA_ANALOG_RIGHT = 1
} ra_analog_stick_t;

/* Analog axis selection */
typedef enum {
    RA_ANALOG_X = 0,
    RA_ANALOG_Y = 1
} ra_analog_axis_t;

/**
 * Set analog stick axis value.
 *
 * @param port Controller port (0-3)
 * @param stick Which stick (left or right)
 * @param axis Which axis (X or Y)
 * @param value Analog value (-32768 to 32767, 0 is center)
 * @return RA_OK on success
 */
ra_result_t ra_set_analog(uint32_t port, ra_analog_stick_t stick,
                          ra_analog_axis_t axis, int16_t value);

/**
 * Clear all input state (release all buttons, center all sticks).
 *
 * @return RA_OK on success
 */
ra_result_t ra_clear_input(void);

/* ============================================================================
 * Save States
 * ========================================================================= */

/**
 * Get save state size in bytes.
 *
 * @return Size in bytes, or 0 if not supported
 */
size_t ra_get_state_size(void);

/**
 * Save state to buffer.
 *
 * @param data Buffer (must be at least ra_get_state_size() bytes)
 * @param size Size of buffer
 * @return RA_OK on success
 */
ra_result_t ra_serialize_state(void *data, size_t size);

/**
 * Load state from buffer.
 *
 * @param data Buffer containing state
 * @param size Size of buffer
 * @return RA_OK on success
 */
ra_result_t ra_unserialize_state(const void *data, size_t size);

/* ============================================================================
 * Utilities
 * ========================================================================= */

/**
 * Get error message for a result code.
 *
 * @param result Result code
 * @return Error message string
 */
const char *ra_get_error_string(ra_result_t result);

/**
 * Get wrapper version string.
 *
 * @return Version string "major.minor.patch"
 */
const char *ra_get_version(void);

#ifdef __cplusplus
}
#endif

#endif /* RA_WRAPPER_H */