#pragma once

#include <pthread.h>
#include <signal.h>
#include <limits.h>
#include <stdint.h>
#include <stdbool.h>
#include <xcb/xcb.h>
#include <X11/XKBlib.h>
#include <X11/Xlib-xcb.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <nmmintrin.h>
#include <immintrin.h>

#ifndef STG_NO_WINDOW

#endif

#include <sched.h>

// syscall defines
#define SYS_ERR -1

// syscall write defines
#define _STDIN 0
#define _STDOUT 1
#define _STDERR 2

// xcb defines
#define XCB_CHECK_CURRENT_ERROR(window, error, message) do {				\
	error = xcb_request_check(window->connection, cookie);						\
	if (error != NULL) {																							\
		EPrintf("%s ERROR CODE: %d\n", message, error->error_code);	\
		free(error);																										\
		return false;																										\
	}																																	\
} while (0) 

#define XCB_CHECK_ERROR(window, cookie, error, message) do {				\
	error = xcb_request_check(window->connection, cookie);						\
	XCB_CHECK_CURRENT_ERROR(window, error, message);									\
} while (0) 

typedef struct {
	Display *display;
	xcb_connection_t *connection;
	xcb_window_t window;
	xcb_atom_t close_event;
	xcb_atom_t minimize_event;
	u16 w, h;
} PlatformWindow;

// ::Platform::Linux::Functions::Header::

// Print Functions
i32 _EPrint(void const *str);
i32 _Printf(const char *fmt, va_list arg);
i32 _Printfln(const char *fmt, va_list arg);
i32 _EPrintf(const char *fmt, va_list arg);

// Window Functions
void GetWindowEvents(GameInput *inputs, u32 *i_count);
b32 WaitForWindowEvent(GameInput *input);
void HandleWindowEvent(GameInput *inputs, u32 *input_count, b32 wait_for_event);
KeyboardInput ConvertInputEvent(u32 x_key);
void RepaintWindow();

// Platform API END

// General Utils
b32 CheckSyscallErr(void *ptr);

// Write Utils
i32 Write(int fd, void const *str, isize count);

