//Set up the Raspberry/Linux systems
#include "Input.h"
#include <iostream>
#include <GLES3/gl3.h>
#include <GLES2/gl2ext.h>
#include "XWindow.h"
#include "RaspKeyboard.h"
#include "RaspMouse.h"
#include "RaspGraphics.h"
#include "IInput.h"
#include "Graphics.h"
#include "Invaders.h"

float lastTime{};
float deltaTime{ 0.2f };
int currentFrame = 0;
RaspGraphics* graphics;
Input* input;
App* game;
int main()
{
    graphics = new RaspGraphics();

    {
        // this strange mess of code, is some debug set up code to let the GPU report errors a little easier, most of the time you will never need to see it.

        PFNGLDEBUGMESSAGECALLBACKKHRPROC peglDebugMessageControlKHR = reinterpret_cast<PFNGLDEBUGMESSAGECALLBACKKHRPROC>(eglGetProcAddress("glDebugMessageCallback"));
        if (!(peglDebugMessageControlKHR != 0)) {
            printf("failed to eglGetProcAddress eglDebugMessageControlKHR\n");
        }
        else {
            GLDEBUGPROCKHR DebugFn = [](GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam)
                {
                    switch (severity)
                    {
                    case GL_DEBUG_SEVERITY_HIGH_KHR:
                    case GL_DEBUG_SEVERITY_MEDIUM_KHR:
                        std::cout << message << std::endl;
                    case GL_DEBUG_SEVERITY_LOW_KHR:
                    case GL_DEBUG_SEVERITY_NOTIFICATION_KHR:
                    default:
                        break; //Ignore.
                    }
                };
            peglDebugMessageControlKHR(DebugFn, nullptr);
            glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR);
        }
    }
    input = new Input(new RaspKeyboard(), new RaspMouse(graphics->Window().GetDisplay(), graphics->Window().GetWindow()));
   
 // now we fire up our game giving it access to the input systems and graphics which are different on each platform but abstracted away   
    game = new Invaders(input, graphics);
    game->Start();
    delete game; // will call the destructor to remove all objects and other new'd instances
    return 0;
}
