#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>
#include <sched.h>
#include <unistd.h>
#include <dirent.h>
#include <x86intrin.h>
#include <sys/time.h>

// ::Platform::Linux::Defines::Header::

#define SYS_ERR -1

#define STDIN 0
#define STDOUT 1
#define STDERR 2

// ::Platform::Linux::Macros::Header::

#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) 

// ::Platform::Linux::Types::Header

typedef struct pThread
{
	pthread_t			  handle;
	pthread_cond_t  cond;
	pthread_mutex_t mut;
} pThread;

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

typedef struct pLibrary
{
	void *lib;
} pLibrary;

typedef struct pFunction
{
	void *fn;
} pFunction;

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

i32 pWrite(int fd, void const *str, isize count);

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

void pWindowEventsGet(pGameInput *inputs, u32 *i_count);
b32 pWindowEventWaitFor(pGameInput *input);
void pWindowEventHandle(pGameInput *inputs, u32 *input_count, b32 wait_for_event);
pKeyboardInput pInputEventConvert(u32 x_key);

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

b32 pSyscallErrCheck(void *ptr);

