/** @file guifunc.cpp
    \brief This file contains the function that loads the GUI
    dynamic library.
    
    It tries to open the GUI dynamic library if it can establish a
    connection to a X server (on Linux only) and starts the GUI if
    everything goes right.
*/
#include <cstdlib> // for getenv

#include "dynload.h"


/**
   \brief This function returns a function that starts the GUI.

   The function that is returned takes the same arguments as main().
   It returns NULL on error.  It takes pointer to void * to return a
   handle to the dynamic library.
*/
int (* GetGuiFunc(LIBHANDLE* pGuiLibHandle))(int, char**)
{
#ifdef LINUX
  *pGuiLibHandle = NULL;

  // Check for environnement variable DISPLAY
  if (!getenv("DISPLAY"))
    {
      return NULL;
    }

  // Check for X11
  void *X11handle = LoadLibrary("libX11.so");
  if (!X11handle)
    {
      return NULL;
    }

  void* (*XOpenDisplayFunc)(char *) =
    (void* (*)(char *)) GetProcAddress(X11handle, "XOpenDisplay");
  void (*XCloseDisplayFunc)(void *) =
    (void (*)(void *)) GetProcAddress(X11handle, "XCloseDisplay");

  if (!XOpenDisplayFunc || !XCloseDisplayFunc)
    {
      FreeLibrary(X11handle);
      return NULL;
    }

  // Check for connection to X server
  void *pDisplay = XOpenDisplayFunc(NULL);
  if (!pDisplay)
    {
      FreeLibrary(X11handle);
      return NULL;
    }

  XCloseDisplayFunc(pDisplay);
  FreeLibrary(X11handle);

  char libstring[] = "./libraygui.so.1";

#elif defined WIN32

  char libstring[] = "./gui.dll";

#else
#error OS not supported
#endif

  // Try to load the GUI lib
  int (*guifunc)(int, char**);

  *pGuiLibHandle = LoadLibrary(libstring);
  if (!*pGuiLibHandle)
    {
      return NULL;
    }

  guifunc = (int (*)(int, char **)) GetProcAddress(*pGuiLibHandle, "StartGui");
  if (guifunc == NULL)
    {
      FreeLibrary(*pGuiLibHandle);
      *pGuiLibHandle = NULL;
    }

  return guifunc;
}
