//
//  M03.cpp
//  MetarealEngine
//
//  Created by David Van Brink on 12/24/14.
//  Copyright (c) 2014 David Van Brink. All rights reserved.
//

#include <stdio.h>
#include <SDL2/SDL.h>

#include "Screens.h"

// TODO make SDLUtils.cpp

/* A simple function that prints a message, the error code returned by SDL,
 * and quits the application */
void sdldie(const char *msg)
{
    meLogError("%s: %s\n", msg, SDL_GetError());
    SDL_Quit();
    exit(1);
}


bool checkSDLError(int line = -1)
{
#ifndef NDEBUG
    const char *error = SDL_GetError();
    if (*error != '\0')
    {
        meLogError("SDL Error: %s %i\n", error, line);
        SDL_ClearError();
        return true;
    }
    return false;
#endif
}

typedef struct Globals
{
    SDL_GLContext maincontext; /* Our opengl context handle */
    SDL_Window *mainwindow;
    int windowWidth;
    int windowHeight;
    Screens *screens;
} Globals;

Globals g = {0};

static void buildSdlWindow()
{
    
    if (SDL_Init(SDL_INIT_VIDEO) < 0) /* Initialize SDL's Video subsystem */
        sdldie("Unable to initialize SDL"); /* Or die on error */
    
    /* Request opengl 3.2 context.
     * SDL doesn't have the ability to choose which profile at this time of writing,
     * but it should default to the core profile */
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
    
    // next line as per: http://stackoverflow.com/questions/11961116/opengl-3-x-context-creation-using-sdl2-on-osx-macbook-air-2012
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    
    
    /* Turn on double buffering with a 24bit Z buffer.
     * You may need to change this to 16 or 32 for your system */
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 32);
    
    /* Create our window centered at 512x512 resolution */
    
    g.windowWidth = 1024;
    g.windowHeight = 1024;
    g.mainwindow = SDL_CreateWindow("M03", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
                                  g.windowWidth, g.windowHeight, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
    if (!g.mainwindow) /* Die if creation failed */
        sdldie("Unable to create window");
    
    checkSDLError(__LINE__);
    
    /* Create our opengl context and attach it to our window */
    g.maincontext = SDL_GL_CreateContext(g.mainwindow);
    if(checkSDLError(__LINE__))
        return;
    
    /* This makes our buffer swap syncronized with the monitor's vertical refresh */
//    SDL_GL_SetSwapInterval(1);
}

static void eventLoop()
{
    bool quit = false;
    SDL_Event e;
    
    g.screens = new Screens(g.windowWidth, g.windowHeight, SDL_GetBasePath());
    
    double time = meGetTime();
    double minTime = 1.0 / 62;
    
    while (!quit)
    {
        {
            double timeNew = meGetTime();
            double timeDelta = timeNew - time;
            double timePadding = minTime - timeDelta;
            
            meSleep(timePadding);
            
            time = timeNew;
        }

        SDL_GL_SwapWindow(g.mainwindow);
        
        
        while (SDL_PollEvent(&e))
        {
            switch(e.type)
            {
                case SDL_QUIT:
                    quit = true;
                    break;
                    
                case SDL_KEYDOWN:
                {
                    int k = e.key.keysym.sym;
                    meLogInfo("key:0x%08x mod:%d", e.key.keysym.sym, e.key.keysym.mod);
                    if(e.key.repeat == 0)
                    {
                        g.screens->keyDown(k, e.key.keysym.mod);
                    }
                    break;
                }

                case SDL_KEYUP:
                {
                    int k = e.key.keysym.sym;
                    g.screens->keyUp(k);
                    break;
                }

                case SDL_MOUSEMOTION:
                {
                    break;
                }
                    
                case SDL_MOUSEBUTTONDOWN:
                {
                    g.screens->mouseDown(e.button.x, e.button.y);
//                    meLogInfo("mouse %d %d\n", e.button.x, e.button.y);
                    break;
                }
                case SDL_MOUSEBUTTONUP:
                    break;
                    
                case SDL_WINDOWEVENT:
                {
                    switch(e.window.event)
                    {
                        case SDL_WINDOWEVENT_ENTER:
                        case SDL_WINDOWEVENT_LEAVE:
                        case SDL_WINDOWEVENT_FOCUS_GAINED:
                        case SDL_WINDOWEVENT_FOCUS_LOST:
                            break;
                        case SDL_WINDOWEVENT_RESIZED:
                            g.windowWidth = e.window.data1;
                            g.windowHeight = e.window.data2;
                            SDL_SetWindowSize(g.mainwindow, g.windowWidth, g.windowHeight);
                            g.screens->setSize(g.windowWidth, g.windowHeight);
                            
                            break;
                    }
                    break;
                }
            } /* switch */
        } /* while event */
        g.screens->tick();
        g.screens->draw();
    }
    
    /* Delete our opengl context, destroy our window, and shutdown SDL */
    SDL_GL_DeleteContext(g.maincontext);
    SDL_DestroyWindow(g.mainwindow);
    SDL_Quit();
    
}

#include <unistd.h>

void chdirToResources(const char *appPath)
{
    // correct for Mac App right now...
    char s[2222];
    strcpy(s, appPath);
    char *w = s + strlen(s);
    w--;
    while(*w != '/')
    {
        *w = 0;
        w--;
    }
    chdir(s);
    chdir("../Resources");
}


int main(int argc, char *argv[])
{
//    meLogEnable(false); // TESTING
    
    printf("argv0 %s\n", argv[0]);

    char x[2222];
    getcwd(x,2222);
    printf("cwd = %s", x);
    chdirToResources(argv[0]);
    getcwd(x,2222);
    printf("cwd = %s", x);
    

    
    
    
    buildSdlWindow();
    eventLoop();
}
