#ifndef _OPEN_WINDOW_H_
#define _OPEN_WINDOW_H_

#define WINDOW_DEFAULT_FPS 60

#define WINDOW_KEY_COUNT 256

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

int gladLoadGL(void);

#include "GL/gl.h"

#ifndef _WIN32

#define Window X11Window
#include <GL/glx.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#undef  Window

typedef struct {
    GLXFBConfig config;
    GLXContext context;
} GLX;

typedef struct {
    Display * display;
    X11Window window;
    Colormap cmap;
    long eventMask;
} X11;

typedef struct {    
    char current[WINDOW_KEY_COUNT];
    char last[WINDOW_KEY_COUNT];
} WindowIOState;

typedef struct Window Window;

typedef struct Window {
    WindowIOState io;
    GLX glx;
    X11 x;         
    uint32_t fps;
} Window;

#define WINDOW_KEY_Q ("q")
#define WINDOW_KEY_W ("w")
#define WINDOW_KEY_E ("e")
#define WINDOW_KEY_R ("r")
#define WINDOW_KEY_T ("t")
#define WINDOW_KEY_Y ("y")
#define WINDOW_KEY_U ("u")
#define WINDOW_KEY_I ("i")
#define WINDOW_KEY_O ("o")
#define WINDOW_KEY_P ("p")
#define WINDOW_KEY_A ("a")
#define WINDOW_KEY_S ("s")
#define WINDOW_KEY_D ("d")
#define WINDOW_KEY_F ("f")
#define WINDOW_KEY_G ("g")
#define WINDOW_KEY_H ("h")
#define WINDOW_KEY_J ("j")
#define WINDOW_KEY_K ("k")
#define WINDOW_KEY_L ("l")
#define WINDOW_KEY_Z ("z")
#define WINDOW_KEY_X ("x")
#define WINDOW_KEY_C ("c")
#define WINDOW_KEY_V ("v")
#define WINDOW_KEY_B ("b")
#define WINDOW_KEY_N ("n")
#define WINDOW_KEY_M ("m")

#define WINDOW_KEY_1 ("1")
#define WINDOW_KEY_2 ("2")
#define WINDOW_KEY_3 ("3")
#define WINDOW_KEY_4 ("4")
#define WINDOW_KEY_5 ("5")
#define WINDOW_KEY_6 ("6")
#define WINDOW_KEY_7 ("7")
#define WINDOW_KEY_8 ("8")
#define WINDOW_KEY_9 ("9")
#define WINDOW_KEY_0 ("0")

#define WINDOW_KEY_ESC ("Escape")
#define WINDOW_KEY_SPACE ("space")

bool windowKeyPressed(Window * window, char * key);
bool windowKeyReleased(Window * window, char * key);
bool windowKeyHeld(Window * window, char * key);

#else

#include <windows.h>

typedef struct {
    HINSTANCE instance;
    HDC  display;
    HWND window;
    HGLRC context;
} WGL;

typedef struct {    
    BYTE current[WINDOW_KEY_COUNT];
    BYTE last[WINDOW_KEY_COUNT];
} WindowIOState;

typedef struct Window Window;

typedef struct Window {
    WindowIOState io;
    WGL wgl;
    uint32_t fps;
} Window;

#define WINDOW_KEY_Q ('Q')
#define WINDOW_KEY_W ('W')
#define WINDOW_KEY_E ('E')
#define WINDOW_KEY_R ('R')
#define WINDOW_KEY_T ('T')
#define WINDOW_KEY_Y ('Y')
#define WINDOW_KEY_U ('U')
#define WINDOW_KEY_I ('I')
#define WINDOW_KEY_O ('O')
#define WINDOW_KEY_P ('P')
#define WINDOW_KEY_A ('A')
#define WINDOW_KEY_S ('S')
#define WINDOW_KEY_D ('D')
#define WINDOW_KEY_F ('F')
#define WINDOW_KEY_G ('G')
#define WINDOW_KEY_H ('H')
#define WINDOW_KEY_J ('J')
#define WINDOW_KEY_K ('K')
#define WINDOW_KEY_L ('L')
#define WINDOW_KEY_Z ('Z')
#define WINDOW_KEY_X ('X')
#define WINDOW_KEY_C ('C')
#define WINDOW_KEY_V ('V')
#define WINDOW_KEY_B ('B')
#define WINDOW_KEY_N ('N')
#define WINDOW_KEY_M ('M')

#define WINDOW_KEY_1 ('1')
#define WINDOW_KEY_2 ('2')
#define WINDOW_KEY_3 ('3')
#define WINDOW_KEY_4 ('4')
#define WINDOW_KEY_5 ('5')
#define WINDOW_KEY_6 ('6')
#define WINDOW_KEY_7 ('7')
#define WINDOW_KEY_8 ('8')
#define WINDOW_KEY_9 ('9')
#define WINDOW_KEY_0 ('0')

#define WINDOW_KEY_ESC (VK_ESCAPE)
#define WINDOW_KEY_SPACE (VK_SPACE)

bool windowKeyPressed(Window * window, int key);
bool windowKeyReleased(Window * window, int key);
bool windowKeyHeld(Window * window, int key);


#endif // _WIN32

Window * openWindow(const char * name, size_t width, size_t height);
void windowSetFps(Window * window, uint32_t fps);
void windowDraw(Window * window);
void windowHandleEvents(Window * window);
void closeWindow(Window * window);

int getOpenGLProcs(void);

#endif  // _OPEN_WINDOW_H_
