#include "Jtk.h"

#ifdef JTK_X

#include <GL/glx.h>
#include "Jtk_internal.h"
#include <stdio.h>
#include <X11/Xatom.h>
#include <cstring>

static Bool WaitForNotify(Display * display, XEvent * event, XPointer arg)
{
    return (event->type == MapNotify) && (event->xmap.window == (Window)arg);
}

void * Jtk_CreateWindow()
{
    XEvent event;
    Window window = XCreateWindow(g_display,
            RootWindow(g_display, g_vi->screen),
            0, 0, 800, 800, 0, g_vi->depth, InputOutput, g_vi->visual,
            CWBorderPixel | CWColormap | CWEventMask, &g_swa);
    XMapWindow(g_display, window);
    XIfEvent(g_display, &event, WaitForNotify, (XPointer)window);
    if (glXMakeCurrent(g_display, window, g_context) == False)
    {
        fprintf(stderr, "glXMakeCurrent() failure\n");
        XDestroyWindow(g_display, window);
        return nullptr;
    }

    /* Disable the window close button. */
    Atom wm_delete_window_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", False);
    XSetWMProtocols(g_display, window, &wm_delete_window_atom, 1);

    return (void *)window;
}

void Jtk_SwapBuffers(void * window)
{
    glXSwapBuffers(g_display, (Window)window);
}

void Jtk_CloseWindow(void * window)
{
    XDestroyWindow(g_display, (Window)window);
}

void Jtk_SetWindowTitle(void * window, const char * title)
{
    XTextProperty title_property;
    if (XStringListToTextProperty((char **)&title, 1, &title_property) != 0)
    {
        XSetTextProperty(g_display, (Window)window, &title_property, XA_WM_NAME);
        XFree(title_property.value);
    }
}

/**
 * Set the window icon.
 *
 * @param window
 *   The window to operate on.
 * @param data
 *   The format of data must be 32 bits per pixel in BGRA format (e.g. data[0]
 *   is blue value, data[3] is alpha value of first pixel).
 * @param width
 *   Icon width.
 * @param height
 *   Icon height.
 */
void Jtk_SetWindowIcon(void * window, const uint8_t * data,
        size_t width, size_t height)
{
    Atom net_wm_icon_atom = XInternAtom(g_display, "_NET_WM_ICON", False);
    size_t property_size = (2u + width * height) * sizeof(long);
    unsigned long * property_data = (unsigned long *)malloc(property_size);
    property_data[0] = width;
    property_data[1] = height;
    unsigned long * dest = &property_data[2];
    const uint32_t * src = (const uint32_t *)data;
    for (size_t row = 0u; row < height; row++)
    {
        for (size_t col = 0u; col < width; col++)
        {
            *dest++ = *src++;
        }
    }
    XChangeProperty(g_display, (Window)window, net_wm_icon_atom, XA_CARDINAL,
            32, PropModeReplace, (uint8_t *)property_data, property_size);
    XFlush(g_display);
    free(property_data);
}

#endif
