#pragma once

#include <stdint.h>

#ifdef __linux__
#include <sys/types.h>
#endif

typedef int8_t i8;
typedef int16_t i16;
typedef int32_t i32;
typedef int64_t i64;

typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;

typedef char c8;

typedef intptr_t intptr;
typedef uintptr_t uintptr;

typedef float f32;
typedef double f64;

typedef uint8_t b8;
typedef uint32_t b32;

typedef void * rawptr;

#ifdef __linux__

typedef ssize_t isize;
typedef size_t usize;

#elif _WIN32

#if defined ( _WIN64 )

typedef int64_t isize;
typedef uint64_t usize;

#elif defined ( _WIN32 )

typedef int32_t isize;
typedef uint32_t usize;

#endif

#elif __APPLE__ || __MACH__

#else // unix

#endif

typedef enum KeyboardInput_e
{
	KB_NONE,
	KB_A,
	KB_B,
	KB_C,
	KB_D,
	KB_E,
	KB_F,
	KB_G,
	KB_H,
	KB_I,
	KB_J,
	KB_K,
	KB_L,
	KB_M,
	KB_N,
	KB_O,
	KB_P,
	KB_Q,
	KB_R,
	KB_S,
	KB_T,
	KB_U,
	KB_V,
	KB_W,
	KB_X,
	KB_Y,
	KB_Z,
	KB_0,
	KB_1,
	KB_2,
	KB_3,
	KB_4,
	KB_5,
	KB_6,
	KB_7,
	KB_8,
	KB_9,
	KB_NUM_0,
	KB_NUM_1,
	KB_NUM_2,
	KB_NUM_3,
	KB_NUM_4,
	KB_NUM_5,
	KB_NUM_6,
	KB_NUM_7,
	KB_NUM_8,
	KB_NUM_9,
	KB_NUM_LOCK,
	KB_NUM_SLASH,
	KB_NUM_STAR,
	KB_NUM_MINUS,
	KB_NUM_PLUS,
	KB_NUM_ENTER,
	KB_NUM_PERIOD,
	KB_INSERT,
	KB_DELETE,
	KB_HOME,
	KB_END,
	KB_PAGE_UP,
	KB_PAGE_DOWN,
	KB_PRINT_SCREEN,
	KB_SCROLL_LOCK,
	KB_PAUSE,
	KB_COMMA,
	KB_PERIOD,
	KB_BACK_SLASH,
	KB_BACKSPACE,
	KB_FORWARD_SLASH,
	KB_MINUS,
	KB_PLUS,
	KB_F1,
	KB_F2,
	KB_F3,
	KB_F4,
	KB_F5,
	KB_F6,
	KB_F7,
	KB_F8,
	KB_F9,
	KB_F10,
	KB_F11,
	KB_F12,
	KB_UP,
	KB_DOWN,
	KB_LEFT,
	KB_RIGHT,
	KB_LEFT_CTRL,
	KB_LEFT_ALT,
	KB_LEFT_SHIFT,
	KB_TAB,
	KB_CAPS_LOCK,
	KB_LEFT_SUPER,
	KB_RIGHT_CTRL,
	KB_RIGHT_ALT,
	KB_RIGHT_SUPER,
	KB_RIGHT_SHIFT,
	KB_ENTER,
	KB_TILDE,
	KB_ESC,
	KB_SEMICOLON,
	KB_QUOTE,
	KB_LEFT_BRACE,
	KB_RIGHT_BRACE,
	KB_BACK_SPACE,
	KB_SPACE,

	KB_MAX
} KeyboardInput;

typedef enum MouseInput_e
{
	M_NONE,
	M_LEFT_CLICK,
	M_MIDDLE_CLICK,
	M_RIGHT_CLICK,
} MouseInput;

typedef enum GameInputType_e
{
	GI_KEYBOARD,
	GI_MOUSE,
	GI_MOTION,
	GI_GAMEPAD,
} GameInputType;

typedef union
{
	struct { f32 r, g; };
	struct { f32 x, y; };
} Vec2;

typedef union
{
	struct { f32 x, y, z; };
	struct { f32 r, g, b; };
} Vec3;

typedef union
{
	struct { f32 x, y, z, w; };
	struct { f32 r, g, b, a; };
} Vec4;

typedef union
{
	struct { i32 x, y; };
	struct { i32 r, g; };
} iVec2;

typedef union
{
	struct { i32 x, y, z; };
	struct { i32 r, g, b; };
} iVec3;

typedef union
{
	struct { i32 x, y, z, w; };
	struct { i32 r, g, b, a; };
} iVec4;

typedef f32 Mat2[4];
typedef f32 Mat3[9];
typedef f32 Mat4[16];

typedef f64 dMat2[4];
typedef f64 dMat3[9];
typedef f64 dMat4[16];

typedef struct MouseMotionEvent_t
{
	i16 x;
	i16 y;
} MouseMotionEvent;

typedef struct 
{
	union 
	{
		KeyboardInput kb_code;
		MouseInput m_code;
		MouseMotionEvent motion_ev;
	};
	b8 pressed;
	GameInputType type;
}	GameInput; // TODO: add gamepad input

typedef struct
{
	Vec2 p0;
	Vec2 p1;
	Vec4 col;
} GUIVertex;

typedef struct 
{
	GUIVertex *vertices;
	u32 vertices_len;
	u32 *indices;
	u32 indices_len;
	u32 instance_count;
	b8 	has_grabbed;
} GUIContext;
