/******************************************************************************
*                                                                             *
* Much of the code in this layer is inspired by, or even directly lifted from *
* the Raylib library with minor changes. The reason for doing this is
*                                                                             *
* https://www.raylib.com/                                                     *
*                                                                             *
* While the original license of the code does permit modifying and            *
* redistributing the code, if you use it in a project that you ship it would  *
* nice to give credit to Raylib and the original authors.                     *
*                                                                             *
******************************************************************************/

#ifndef MR4TH_PROTOTYPE_H
#define MR4TH_PROTOTYPE_H

////////////////////////////////
// Prototype Types

typedef U32 PR_WindowFlags;
enum {
  PR_WindowFlag_Fullscreen  = 0x00000001,
  PR_WindowFlag_Resiable    = 0x00000002,
  PR_WindowFlag_Undecorated = 0x00000004,
  PR_WindowFlag_Hidden      = 0x00000008,
  PR_WindowFlag_Minimized   = 0x00000010,
  PR_WindowFlag_Maximized   = 0x00000020,
  PR_WindowFlag_Unfocused   = 0x00000040,
  PR_WindowFlag_Topmost     = 0x00000080,
  PR_WindowFlag_Borderless  = 0x00000100,
};

typedef struct PR_Color{
  U8 r;
  U8 g;
  U8 b;
  U8 a;
} PR_Color;

typedef struct PR_Image{
  void *data;
  U32 width;
  U32 height;
  U32 mipmaps;
} PR_Image;

typedef struct PR_Texture{
  U32 id;
  U32 width;
  U32 height;
  U32 mipmaps;
} PR_Texture;

typedef struct PR_Surface{
  U32 id;
  PR_Texture texture;
  PR_Texture depth;
} PR_Surface;

typedef struct PR_GlyphInfo{
  U32 codepoint;
  S32 off_x;
  S32 off_y;
  S32 adv_x;
  PR_Image image;
} PR_GlyphInfo;

typedef struct PR_Font{
  S32 base_size;
  U32 glyph_count;
  S32 glyph_padding;
  PR_Texture texture;
  RectF32 *rects;
  PR_GlyphInfo *glyphs;
} PR_Font;

typedef struct PR_Camera2D{
  V2F32 offset;
  V2F32 target;
  F32 theta;
  F32 zoom;
} PR_Camera2D;



////////////////////////////////
// Prototype Constants

#define PR_LightGray  CLiteral(Color){ 200, 200, 200, 255 }
#define PR_Gray       CLiteral(Color){ 130, 130, 130, 255 }
#define PR_DarkGray   CLiteral(Color){  80,  80,  80, 255 }
#define PR_Yellow     CLiteral(Color){ 253, 249,   0, 255 }
#define PR_Gold       CLiteral(Color){ 255, 203,   0, 255 }
#define PR_Orange     CLiteral(Color){ 255, 161,   0, 255 }
#define PR_Pink       CLiteral(Color){ 255, 109, 194, 255 }
#define PR_Red        CLiteral(Color){ 230,  41,  55, 255 }
#define PR_Maroon     CLiteral(Color){ 190,  33,  55, 255 }
#define PR_Green      CLiteral(Color){   0, 228,  48, 255 }
#define PR_Lime       CLiteral(Color){   0, 158,  47, 255 }
#define PR_DarkGreen  CLiteral(Color){   0, 117,  44, 255 }
#define PR_SkyBlue    CLiteral(Color){ 102, 191, 255, 255 }
#define PR_Blue       CLiteral(Color){   0, 121, 241, 255 }
#define PR_DarkBlue   CLiteral(Color){   0,  82, 172, 255 }
#define PR_Purple     CLiteral(Color){ 200, 122, 255, 255 }
#define PR_Violet     CLiteral(Color){ 135,  60, 190, 255 }
#define PR_DarkPurple CLiteral(Color){ 112,  31, 126, 255 }
#define PR_Beige      CLiteral(Color){ 211, 176, 131, 255 }
#define PR_Brown      CLiteral(Color){ 127, 106,  79, 255 }
#define PR_DarkBrown  CLiteral(Color){  76,  63,  47, 255 }

#define PR_White      CLiteral(Color){ 255, 255, 255, 255 }
#define PR_Black      CLiteral(Color){   0,   0,   0, 255 }
#define PR_Blank      CLiteral(Color){   0,   0,   0,   0 }
#define PR_Magenta    CLiteral(Color){ 255,   0, 255, 255 }
#define PR_RayWhite   CLiteral(Color){ 245, 245, 245, 255 }

////////////////////////////////
// Prototype Functions

#define MR4TH_PR_SYMBOL MR4TH_SYMBOL

// window functions

MR4TH_PR_SYMBOL void     pr_init_window(S32 width, S32 height, String8 title);
MR4TH_PR_SYMBOL void     pr_close_window(void);
MR4TH_PR_SYMBOL B32      pr_window_should_close(void);
MR4TH_PR_SYMBOL B32      pr_is_window_ready(void);
MR4TH_PR_SYMBOL B32      pr_is_window_fullscreen(void);
MR4TH_PR_SYMBOL B32      pr_is_window_hidden(void);
MR4TH_PR_SYMBOL B32      pr_is_window_minimized(void);
MR4TH_PR_SYMBOL B32      pr_is_window_maximized(void);
MR4TH_PR_SYMBOL B32      pr_is_window_focused(void);
MR4TH_PR_SYMBOL B32      pr_is_window_resized(void);
MR4TH_PR_SYMBOL B32      pr_is_window_state(PR_WindowFlags flag);
MR4TH_PR_SYMBOL void     pr_set_window_state(PR_WindowFlags flags);
MR4TH_PR_SYMBOL void     pr_clear_window_state(PR_WindowFlags flags);
MR4TH_PR_SYMBOL void     pr_toggle_fullscreen(void);
MR4TH_PR_SYMBOL void     pr_toggle_borderless_windowed(void);
MR4TH_PR_SYMBOL void     pr_maximize_window(void);
MR4TH_PR_SYMBOL void     pr_minimize_window(void);
MR4TH_PR_SYMBOL void     pr_restore_window(void);
MR4TH_PR_SYMBOL void     pr_set_window_icon(PR_Image image);
MR4TH_PR_SYMBOL void     pr_set_window_icons(PR_Image *images, S32 count);
MR4TH_PR_SYMBOL void     pr_set_window_title(String8 title);
MR4TH_PR_SYMBOL void     pr_set_window_position(S32 x, S32 y);
MR4TH_PR_SYMBOL void     pr_set_window_monitor(S32 monitor);
MR4TH_PR_SYMBOL void     pr_set_window_min_size(S32 width, S32 height);
MR4TH_PR_SYMBOL void     pr_set_window_max_size(S32 width, S32 height);
MR4TH_PR_SYMBOL void     pr_set_window_size(S32 width, S32 height);
MR4TH_PR_SYMBOL void     pr_set_window_opacity(F32 opacity);
MR4TH_PR_SYMBOL void     pr_set_window_focused(void);
MR4TH_PR_SYMBOL void*    pr_get_window_handle(void);
MR4TH_PR_SYMBOL S32      pr_get_screen_width(void);
MR4TH_PR_SYMBOL S32      pr_get_screen_height(void);
MR4TH_PR_SYMBOL S32      pr_get_render_width(void);
MR4TH_PR_SYMBOL S32      pr_get_render_height(void);
MR4TH_PR_SYMBOL S32      pr_get_monitor_count(void);
MR4TH_PR_SYMBOL S32      pr_get_current_monitor(void);
MR4TH_PR_SYMBOL V2F32    pr_get_monitor_position(S32 monitor);
MR4TH_PR_SYMBOL S32      pr_get_monitor_width(S32 monitor);
MR4TH_PR_SYMBOL S32      pr_get_monitor_height(S32 monitor);
MR4TH_PR_SYMBOL S32      pr_get_monitor_physical_width(S32 monitor);
MR4TH_PR_SYMBOL S32      pr_get_monitor_physical_height(S32 monitor);
MR4TH_PR_SYMBOL S32      pr_get_monitor_refresh_rate(S32 monitor);
MR4TH_PR_SYMBOL V2F32    pr_get_window_position(void);
MR4TH_PR_SYMBOL V2F32    pr_get_window_scale_dpi(void);
MR4TH_PR_SYMBOL String8  pr_get_monitor_name(S32 monitor);
MR4TH_PR_SYMBOL void     pr_set_clipboard_text(String8 text);
MR4TH_PR_SYMBOL String8  pr_get_clipboard_text(void);
MR4TH_PR_SYMBOL PR_Image pr_get_clipboard_image(void);
MR4TH_PR_SYMBOL void     pr_enable_event_waiting(void);
MR4TH_PR_SYMBOL void     pr_disable_event_waiting(void);

// cursor functions

MR4TH_PR_SYMBOL void pr_show_cursor(void);
MR4TH_PR_SYMBOL void pr_hide_cursor(void);
MR4TH_PR_SYMBOL B32  pr_is_cursor_hidden(void);
MR4TH_PR_SYMBOL void pr_enable_cursor(void);
MR4TH_PR_SYMBOL void pr_disable_cursor(void);
MR4TH_PR_SYMBOL B32  pr_is_cursor_on_screen(void);

// drawing functions

MR4TH_PR_SYMBOL void pr_clear_background(PR_Color color);
MR4TH_PR_SYMBOL void pr_begin_drawing(void);
MR4TH_PR_SYMBOL void pr_end_drawing(void);
MR4TH_PR_SYMBOL void pr_begin_mode_2d(PR_Camera2D camera);
MR4TH_PR_SYMBOL void pr_end_mode_2d(void);
MR4TH_PR_SYMBOL void pr_begin_surface_mode(PR_Surface surface);
MR4TH_PR_SYMBOL void pr_end_surface_mode(void);
MR4TH_PR_SYMBOL void pr_begin_scissor_mode(S32 x, S32 y, S32 width, S32 height);
MR4TH_PR_SYMBOL void pr_end_scissor_mode(void);

// screen space functions

MR4TH_PR_SYMBOL V2F32 pr_get_world_to_screen_2d(V2F32 position, PR_Camera2D camera);
MR4TH_PR_SYMBOL V2F32 pr_get_screen_to_world_2d(V2F32 position, PR_Camera2D camera);
MR4TH_PR_SYMBOL void  pr_get_camera_matrix_2d(PR_Camera2D camera, F32 *out);

// timing functions

MR4TH_PR_SYMBOL void pr_set_target_fps(S32 fps);
MR4TH_PR_SYMBOL S32  pr_get_fps(void);
MR4TH_PR_SYMBOL F32  pr_get_frame_time(void);
MR4TH_PR_SYMBOL F64  pr_get_time(void);
MR4TH_PR_SYMBOL void pr_sleep(F64 seconds);

// keyboard functions

MR4TH_PR_SYMBOL B32     pr_is_key_pressed(GFX_Key key);
MR4TH_PR_SYMBOL B32     pr_is_key_repeat(GFX_Key key);
MR4TH_PR_SYMBOL B32     pr_is_key_down(GFX_Key key);
MR4TH_PR_SYMBOL B32     pr_is_key_released(GFX_Key key);
MR4TH_PR_SYMBOL B32     pr_is_key_up(GFX_Key key);
MR4TH_PR_SYMBOL GFX_Key pr_get_key_pressed(void);
MR4TH_PR_SYMBOL U32     pr_get_char_pressed(void);

// mouse functions

MR4TH_PR_SYMBOL B32   pr_is_mouse_button_pressed(GFX_MouseButton button);
MR4TH_PR_SYMBOL B32   pr_is_mouse_button_down(GFX_MouseButton button);
MR4TH_PR_SYMBOL B32   pr_is_mouse_button_released(S32 button);
MR4TH_PR_SYMBOL B32   pr_is_mouse_button_up(S32 button);
MR4TH_PR_SYMBOL V2F32 pr_get_mouse_position(void);
MR4TH_PR_SYMBOL V2F32 pr_get_mouse_delta(void);
MR4TH_PR_SYMBOL void  pr_set_mouse_position(S32 x, S32 y);
MR4TH_PR_SYMBOL void  pr_set_mouse_offset(S32 offset_x, S32 offset_y);
MR4TH_PR_SYMBOL void  pr_set_mouse_scale(F32 scale_x, F32 scale_y);
MR4TH_PR_SYMBOL V2F32 pr_get_mouse_wheel_move(void);
MR4TH_PR_SYMBOL void  pr_set_mouse_cursor(GFX_CursorAppearance cursor);

// TODO(allen): gamepad
// TODO(allen): midi

// draw basic shapes

MR4TH_PR_SYMBOL void pr_draw_pixel(S32 pos_x, S32 pos_y, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_pixel_v(V2F32 position, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_line(S32 start_pos_x, S32 start_pos_y, S32 end_pos_x, S32 end_pos_y, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_line_v(V2F32 start_pos, V2F32 end_pos, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_line_ex(V2F32 start_pos, V2F32 end_pos, F32 thick, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_line_strip(V2F32 *points, U32 point_count, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_line_bezier(V2F32 start_pos, V2F32 end_pos, F32 thick, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_circle(S32 centerX, S32 center_y, F32 radius, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_circle_sector(V2F32 center, F32 radius, F32 start_theta, F32 end_theta, S32 segments, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_circle_sector_lines(V2F32 center, F32 radius, F32 start_theta, F32 end_theta, S32 segments, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_circle_gradient(S32 center_x, S32 center_y, F32 radius, PR_Color inner, PR_Color outer);
MR4TH_PR_SYMBOL void pr_draw_circle_v(V2F32 center, F32 radius, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_circle_lines(S32 center_x, S32 center_y, F32 radius, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_circle_lines_v(V2F32 center, F32 radius, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_ellipse(S32 center_x, S32 center_y, F32 radiusH, F32 radiusV, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_ellipse_lines(S32 center_x, S32 center_y, F32 radius_h, F32 radius_v, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_ring(V2F32 center, F32 inner_radius, F32 outer_radius, F32 start_theta, F32 end_theta, S32 segments, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_ring_lines(V2F32 center, F32 inner_radius, F32 outer_radius, F32 start_theta, F32 end_theta, S32 segments, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_rectangle(S32 pos_x, S32 pos_y, S32 width, S32 height, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_rectangle_v(V2F32 position, V2F32 size, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_rectangle_rec(RectF32 rec, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_rectangle_pro(RectF32 rec, V2F32 origin, F32 rotation, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_rectangle_gradient_v(S32 pos_x, S32 pos_y, S32 width, S32 height, PR_Color top, PR_Color bottom);
MR4TH_PR_SYMBOL void pr_draw_rectangle_gradient_h(S32 pos_x, S32 pos_y, S32 width, S32 height, PR_Color left, PR_Color right);
MR4TH_PR_SYMBOL void pr_draw_rectangle_gradient_ex(RectF32 rec, PR_Color top_left, PR_Color bottom_left, PR_Color top_right, PR_Color bottom_right);
MR4TH_PR_SYMBOL void pr_draw_rectangle_lines(S32 pos_x, S32 pos_y, S32 width, S32 height, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_rectangle_lines_ex(RectF32 rec, F32 line_thick, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_rectangle_rounded(RectF32 rec, F32 roundness, S32 segments, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_rectangle_rounded_lines(RectF32 rec, F32 roundness, S32 segments, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_rectangle_rounded_lines_ex(RectF32 rec, F32 roundness, S32 segments, F32 line_thick, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_triangle(V2F32 v1, V2F32 v2, V2F32 v3, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_triangle_lines(V2F32 v1, V2F32 v2, V2F32 v3, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_triangle_fan(V2F32 *points, U32 point_count, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_triangle_strip(V2F32 *points, U32 point_count, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_poly(V2F32 center, S32 sides, F32 radius, F32 rotation, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_poly_lines(V2F32 center, S32 sides, F32 radius, F32 rotation, PR_Color color);
MR4TH_PR_SYMBOL void pr_draw_poly_lines_ex(V2F32 center, S32 sides, F32 radius, F32 rotation, F32 line_thick, PR_Color color);

// shape overlaps

MR4TH_PR_SYMBOL B32  pr_check_collision_recs(RectF32 rec1, RectF32 rec2);
MR4TH_PR_SYMBOL B32  pr_check_collision_circles(V2F32 center1, F32 radius1, V2F32 center2, F32 radius2);
MR4TH_PR_SYMBOL B32  pr_check_collision_circle_rec(V2F32 center, F32 radius, RectF32 rec);
MR4TH_PR_SYMBOL B32  pr_check_collision_circle_line(V2F32 center, F32 radius, V2F32 p1, V2F32 p2);
MR4TH_PR_SYMBOL B32  pr_check_collision_point_rec(V2F32 point, RectF32 rec);
MR4TH_PR_SYMBOL B32  pr_check_collision_point_circle(V2F32 point, V2F32 center, F32 radius);
MR4TH_PR_SYMBOL B32  pr_check_collision_point_triangle(V2F32 point, V2F32 p1, V2F32 p2, V2F32 p3);
MR4TH_PR_SYMBOL B32  pr_check_collision_point_line(V2F32 point, V2F32 p1, V2F32 p2, S32 threshold);
MR4TH_PR_SYMBOL B32  pr_check_collision_point_poly(V2F32 point, V2F32 *points, U32 point_count);
MR4TH_PR_SYMBOL B32  pr_check_collision_lines(V2F32 start_pos1, V2F32 end_pos1, V2F32 start_pos2, V2F32 end_pos2, V2F32 *collision_point);

// image loading functions

MR4TH_PR_SYMBOL PR_Image pr_load_image_from_memory(String8 file_data);
MR4TH_PR_SYMBOL PR_Image pr_load_image_from_file(Arena *arena, String8 file_name);
MR4TH_PR_SYMBOL PR_Image pr_load_image_anim_from_memory(String8 file_data, U32 *frames);
MR4TH_PR_SYMBOL PR_Image pr_load_image_anim_from_file(Arena *arena, String8 file_name, U32 *frames);
MR4TH_PR_SYMBOL PR_Image pr_load_image_from_texture(Arena *arena, PR_Texture texture);
MR4TH_PR_SYMBOL PR_Image pr_load_image_from_screen(Arena *arena);
MR4TH_PR_SYMBOL B32      pr_is_image_valid(PR_Image image);
MR4TH_PR_SYMBOL String8  pr_save_image_to_memory(Arena *arena, PR_Image image);
MR4TH_PR_SYMBOL B32      pr_save_image_to_file(PR_Image image, String8 file_name);

#endif //MR4TH_PROTOTYPE_H
