/** @brief Obtain the system display and initialize EGL
 * @param width : desired pixel width of the window (not used by all platforms)
 * @param height : desired pixel height of the window (not used by all platforms)
 * @return : 0 if the function passed, else 1
 */
int8_t EGL_Open( uint16_t width, uint16_t height )
{
    EGLint eglMajorVer, eglMinorVer;
    EGLBoolean result;
    uint32_t configIndex = 0;
    const char* output;

    static const EGLint contextAttribs[] =
    {
#if defined(USE_GLES2)
          EGL_CONTEXT_CLIENT_VERSION,     2,
#endif
          EGL_NONE
    };

#if defined(DEBUG)
    printf( "EGLport Warning: DEBUG is enabled which may effect performance\n" );
#endif

    /* Check that system is not open */
    if (eglDisplay != NULL || eglContext != NULL || eglSurface != NULL)
    {
        printf( "EGLport ERROR: EGL system is already open!\n" );
        return 1;
    }

    /* Check for the cfg file to alternative settings */
    OpenCfg( "eglport.cfg" );

    /* Setup any platform specific bits */
    Platform_Open();

    printf( "EGLport: Opening EGL display\n" );
    if (GetNativeDisplay() != 0)
    {
        printf( "EGLport ERROR: Unable to obtain native display!\n" );
        return 1;
    }

    eglDisplay = peglGetDisplay( nativeDisplay );
    if (eglDisplay == EGL_NO_DISPLAY)
    {
        CheckEGLErrors( __FILE__, __LINE__ );
        printf( "EGLport ERROR: Unable to create EGL display.\n" );
        return 1;
    }

    printf( "EGLport: Initializing\n" );
    result = peglInitialize( eglDisplay, &eglMajorVer, &eglMinorVer );
    if (result != EGL_TRUE )
    {
        CheckEGLErrors( __FILE__, __LINE__ );
        printf( "EGLport ERROR: Unable to initialize EGL display.\n" );
        return 1;
    }

    /* Get EGL Library Information */
    printf( "EGL Implementation Version: Major %d Minor %d\n", eglMajorVer, eglMinorVer );
    output = peglQueryString( eglDisplay, EGL_VENDOR );
    printf( "EGL_VENDOR: %s\n", output );
    output = peglQueryString( eglDisplay, EGL_VERSION );
    printf( "EGL_VERSION: %s\n", output );
    output = peglQueryString( eglDisplay, EGL_EXTENSIONS );
    printf( "EGL_EXTENSIONS: %s\n", output );

    if (FindEGLConfigs() != 0)
    {
        printf( "EGLport ERROR: Unable to configure EGL. See previous error.\n" );
        return 1;
    }

    printf( "EGLport: Using Config %d\n", configIndex );
#if defined(EGL_VERSION_1_2)
    /* Bind GLES and create the context */
    printf( "EGLport: Binding API\n" );
    result = peglBindAPI( EGL_OPENGL_ES_API );
    if ( result == EGL_FALSE )
    {
        CheckEGLErrors( __FILE__, __LINE__ );
        printf( "EGLport ERROR: Could not bind EGL API.\n" );
        return 1;
    }
#endif /* EGL_VERSION_1_2 */

    printf( "EGLport: Creating Context\n" );
    eglContext = peglCreateContext( eglDisplay, eglConfigs[configIndex], NULL, contextAttribs );
    if (eglContext == EGL_NO_CONTEXT)
    {
        CheckEGLErrors( __FILE__, __LINE__ );
        printf( "EGLport ERROR: Unable to create GLES context!\n");
        return 1;
    }

    printf( "EGLport: Creating window surface\n" );
    if (GetNativeWindow( width, height ) != 0)
    {
        printf( "EGLport ERROR: Unable to obtain native window!\n" );
        return 1;
    }

    eglSurface = peglCreateWindowSurface( eglDisplay, eglConfigs[configIndex], nativeWindow, 0 );
    if (eglSurface == EGL_NO_SURFACE)
    {
        CheckEGLErrors( __FILE__, __LINE__ );
        printf( "EGLport ERROR: Unable to create EGL surface!\n" );
        return 1;
    }

    printf( "EGLport: Making Current\n" );
    result = peglMakeCurrent( eglDisplay,  eglSurface,  eglSurface, eglContext );
    if (result != EGL_TRUE)
    {
        CheckEGLErrors( __FILE__, __LINE__ );
        printf( "EGLport ERROR: Unable to make GLES context current\n" );
        return 1;
    }

	{
	  EGLint color, depth, stencil;
	  eglGetConfigAttrib(eglDisplay, eglConfigs[configIndex], EGL_BUFFER_SIZE, &color);
	  eglGetConfigAttrib(eglDisplay, eglConfigs[configIndex], EGL_DEPTH_SIZE, &depth);
	  eglGetConfigAttrib(eglDisplay, eglConfigs[configIndex], EGL_STENCIL_SIZE, &stencil);
	  eglColorbits = (color==16)?5:8; //quick hack
	  eglDepthbits = depth;
	  eglStencilbits = stencil;
	}

    printf( "EGLport: Setting swap interval\n" );
    peglSwapInterval( eglDisplay, (eglSettings[CFG_VSYNC] > 0) ? 1 : 0 );

    printf( "EGLport: Complete\n" );

    CheckEGLErrors( __FILE__, __LINE__ );
	
    return 0;
}
/*===========================================================
Initialise OpenGL settings
===========================================================*/
int8_t ConfigureEGL(EGLConfig config)
{
    EGLBoolean result;

#if defined(USE_GLES1)
    static const EGLint s_contextAttribs = NULL;
#elif defined(USE_GLES2)
    static const EGLint s_contextAttribs[] =
    {
          EGL_CONTEXT_CLIENT_VERSION,     2,
          EGL_NONE
    };
#else
    #error Incorrect Opengl-ES Configuration for s_contextAttribs
#endif /* defined(USE_GLES1) */

    // Cleanup in case of a reset
    if (g_eglDisplay != NULL)
    {
        peglMakeCurrent( g_eglDisplay, NULL, NULL, EGL_NO_CONTEXT );
        if (g_eglContext != NULL) {
            peglDestroyContext( g_eglDisplay, g_eglContext );
        }
        if (g_eglSurface != NULL) {
            peglDestroySurface( g_eglDisplay, g_eglSurface );
        }
    }

#if defined(EGL_VERSION_1_2)
    // Bind GLES and create the context
    printf( "EGL Binding API\n" );
    peglBindAPI( EGL_OPENGL_ES_API );

    if ( CheckEGLErrors( __FILE__, __LINE__ ) !=  0 )
    {
        printf( "EGL ERROR: Could not bind EGL API.\n" );
        return 1;
    }
#endif /* defined(USE_EGL_SDL) */

    printf( "EGL Creating Context\n" );
    g_eglContext = peglCreateContext( g_eglDisplay, config, NULL, s_contextAttribs );

    if (g_eglContext == EGL_NO_CONTEXT)
    {
        CheckEGLErrors( __FILE__, __LINE__ );
        printf( "EGL ERROR: Unable to create GLES context!\n");
        return 1;
    }

#if defined(USE_EGL_RAW)
    if (g_Window == NULL) {
        g_Window = (NativeWindowType)malloc(16*1024);

        if(g_Window == NULL) {
            printf( "EGL ERROR: Memory for window Failed\n" );
            return 1;
        }
    }
    else
    {
        printf( "EGL Info: Memory for window already allocated\n" );
    }
#elif defined(USE_EGL_SDL)
    // Get the SDL window handle
    SDL_SysWMinfo sysInfo; //Will hold our Window information
    SDL_VERSION(&sysInfo.version); //Set SDL version

    if(SDL_GetWMInfo(&sysInfo) <= 0)
    {
        printf( "EGL ERROR: Unable to get SDL window handle: %s\n", SDL_GetError() );
        return 1;
    }
    g_Window = (NativeWindowType)sysInfo.info.x11.window;
#else
    #error Incorrect EGL Configuration for g_Window
#endif /* defined(USE_EGL_RAW) */

    printf( "EGL Creating window surface\n" );
    g_eglSurface = peglCreateWindowSurface( g_eglDisplay, config, g_Window, 0 );

    if (g_eglSurface == EGL_NO_SURFACE)
    {
        CheckEGLErrors( __FILE__, __LINE__ );
        printf( "EGL ERROR: Unable to create EGL surface!\n" );
        return 1;
    }

    printf( "EGL Making Current\n" );
    result = peglMakeCurrent( g_eglDisplay,  g_eglSurface,  g_eglSurface, g_eglContext );

    if (result != EGL_TRUE)
    {
        CheckEGLErrors( __FILE__, __LINE__ );
        printf( "EGL ERROR: Unable to make GLES context current\n" );
        return 1;
    }

    CheckEGLErrors( __FILE__, __LINE__ );
    printf( "EGL Complete\n" );
    return 0;
}