#include "XWindow.h"

#include <cstring>
#include <EGL/eglplatform.h>
#include <EGL/egl.h>
#include <X11/Xutil.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <cstring>
#include <GLES3/gl31.h>
#include "App.h"



// The windows build does not make use of this since GLFW does all the cool stuff 
static const EGLint context_attributes[] =
{
	EGL_CONTEXT_MAJOR_VERSION_KHR,
	3, // you can change this to different version of OpenGLES
	EGL_CONTEXT_MINOR_VERSION_KHR,
	1, // 
	EGL_NONE,
	EGL_NONE
};

const EGLint attribute_list[] =
{
	EGL_RED_SIZE,
	8,
	EGL_GREEN_SIZE,
	8,
	EGL_BLUE_SIZE,
	8,
	EGL_ALPHA_SIZE,
	8,
	EGL_DEPTH_SIZE,
	8,
	//	EGL_SAMPLE_BUFFERS,1, // these tend to kill performance on a Pi its your call to leave them in
	//	EGL_SAMPLES,4,
		EGL_SURFACE_TYPE,
		EGL_WINDOW_BIT,
	#ifdef GLES3	
		EGL_CONFORMANT,
		EGL_OPENGL_ES3_BIT_KHR,
	#endif	
		EGL_NONE
};



XWindow::XWindow()
{
}

// new create window which centers the window
void XWindow::CreateWindow()
{
	display = XOpenDisplay(nullptr);
	root = RootWindowOfScreen(DefaultScreenOfDisplay(display));

	// Get the screen dimensions
	int screen_num = DefaultScreen(display);
	int screen_width = DisplayWidth(display, screen_num);
	int screen_height = DisplayHeight(display, screen_num);

	// Calculate the position to center the window
	int x_position = (screen_width - WINDOW_WIDTH) / 2;
	int y_position = (screen_height - WINDOW_HEIGHT) / 2;

	XSetWindowAttributes swa;
	XWMHints hints;
	EGLint numConfigs;
	EGLint majorVersion;
	EGLint minorVersion;

	swa.event_mask = ExposureMask | PointerMotionMask | KeyPressMask | KeyReleaseMask;
	swa.background_pixmap = None;
	swa.background_pixel = 0;
	swa.border_pixel = 0;
	swa.override_redirect = false;

	window = XCreateWindow(
		display,
		root,
		x_position,  // Centered x position
		y_position,  // Centered y position
		WINDOW_WIDTH,
		WINDOW_HEIGHT,
		0,
		CopyFromParent,
		InputOutput,
		CopyFromParent,
		CWEventMask | CWBackPixmap | CWBorderPixel | CWBackPixel,
		&swa);

	XSelectInput(display, window, KeyPressMask | KeyReleaseMask);

	// Set window manager hints for position
	XSizeHints sizeHints;
	sizeHints.flags = PPosition | PSize;
	sizeHints.x = x_position;
	sizeHints.y = y_position;
	sizeHints.width = WINDOW_WIDTH;
	sizeHints.height = WINDOW_HEIGHT;
	XSetWMNormalHints(display, window, &sizeHints);

	// Set input hints
	hints.input = true;
	hints.flags = InputHint;
	XSetWMHints(display, window, &hints);

	// Set the window name
	XStoreName(display, window, PROJECT_NAME);

	// Clear and map the window
	XClearWindow(display, window);
	XMapWindow(display, window);

	// Set up other window properties
	Atom wm_state = XInternAtom(display, "_NET_WM_STATE", false);

	XEvent xev;
	memset(&xev, 0, sizeof(xev));
	xev.type = ClientMessage;
	xev.xclient.window = window;
	xev.xclient.message_type = wm_state;
	xev.xclient.format = 32;
	xev.xclient.data.l[0] = 1;
	xev.xclient.data.l[1] = false;
	XSendEvent(
		display,
		DefaultRootWindow(display),
		false,
		SubstructureNotifyMask,
		&xev);

	// EGL setup 
	state.display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
	eglInitialize(state.display, &majorVersion, &minorVersion);
	eglGetConfigs(state.display, nullptr, 0, &numConfigs);
	eglChooseConfig(state.display, attribute_list, &state.config, 1, &numConfigs);

	// OpenGL setup.
	state.context = eglCreateContext(state.display, state.config, nullptr, context_attributes);

	state.surface = eglCreateWindowSurface(state.display, state.config, window, nullptr);
	eglMakeCurrent(state.display, state.surface, state.surface, state.context);

	eglSurfaceAttrib(display, state.surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
	eglSwapInterval(state.display, 1);


	// HIDE CURSOR if you don't want to see it.
	/*Cursor invisibleCursor;
	Pixmap bitmapNoData;
	XColor black;
	static char noData[] = {0, 0, 0, 0, 0, 0, 0, 0};
	black.red = black.green = black.blue = 0;
	bitmapNoData = XCreateBitmapFromData(display, window, noData, 8, 8);
	invisibleCursor = XCreatePixmapCursor(display, bitmapNoData, bitmapNoData, &black, &black, 0, 0);
	XDefineCursor(display, window, invisibleCursor);
	XFreeCursor(display, invisibleCursor);
	XFreePixmap(display, bitmapNoData);*/
}


const EGLState& XWindow::GetState() const
{
	return state;
}

Display& XWindow::GetDisplay()
{
	return *display;
}

Window& XWindow::GetWindow()
{
	return window;
}
