#ifndef RT_LAUNCHER_GAME_API_H
#define RT_LAUNCHER_GAME_API_H

#include <runtime/runtime.h>
#include <runtime/timing.h>

/* Functions offered by the launcher */

struct GLFWwindow;

typedef enum {
    RT_WINDOW_TYPE_GLFW,
} rt_window_type;

typedef struct {
    rt_window_type type;
    union {
        GLFWwindow *glfw;
    };
} rt_window;

typedef rt_window rt_launcher_get_window_fn(void);
typedef void *rt_launcher_alloc_game_object_fn(size_t sz);
typedef void *rt_launcher_get_game_object_fn(void);

typedef struct {
    /* Returns the window used by the game */
    rt_launcher_get_window_fn *GetWindow;

    /* Allocates storage for the "game" object passed to the game functions. */
    rt_launcher_alloc_game_object_fn *AllocGameObject;

    /* Returns the object allocated via AllocGameObject */
    rt_launcher_get_game_object_fn *GetGameObject;
} rt_launcher_api;

/* Functions called by the launcher */

typedef void rt_game_register_cvars_fn(rt_launcher_api *api);
typedef rt_result rt_game_initialize_fn(rt_launcher_api *api);
typedef void rt_game_shutdown_fn(rt_launcher_api *api, void *game_obj);
typedef void rt_game_update_fn(rt_launcher_api *api, rt_time_delta delta, void *game_obj);
typedef void rt_game_render_fn(rt_launcher_api *api, void *game_obj);
typedef void rt_game_on_game_object_free_fn(rt_launcher_api *api, void *game_obj);
typedef void rt_game_on_reload_fn(rt_launcher_api *api, void *game_obj);
typedef void rt_game_on_unload_fn(rt_launcher_api *api, void *game_obj);

typedef struct {
    /* Called before initialization and before configs are read */
    rt_game_register_cvars_fn *RegisterCVARs;

    /* Called before entering the game-loop.
     * It is expected that this is where the game object is created. */
    rt_game_initialize_fn *Init;

    /* Called after exiting the game-loop. */
    rt_game_shutdown_fn *Shutdown;

    /* Update game state */
    rt_game_update_fn *Update;

    /* Render the game */
    rt_game_render_fn *Render;

    /* These are optional and may be NULL */

    /* Called by rt_laucher_api::AllocGameObject, if an old object is freed. */
    rt_game_on_game_object_free_fn *OnGameObjectFree;
} rt_game_api;


/* This is the function retrieved from the game library to get the
 * game_api struct used by the launcher. */
typedef rt_game_api rt_load_game_api_fn(void);

#ifdef __cplusplus
#define LOAD_GAME_API_FUNC extern "C" RT_DLLEXPORT rt_game_api rtLoadGameAPI()
#else
#define LOAD_GAME_API_FUNC RT_DLLEXPORT rt_game_api rtLoadGameAPI()
#endif

#endif
