/src/KickMan.cpp
/* KickMan - a simple pocket drum machine
 * Copyright (C) 2011 The Dominion of Awesome
 */
#include <stdio.h>
#include <math.h>

#include <GLES2/gl2.h>
#include <SDL.h>
#include <PDL.h>
#include <SDL_mixer.h>
#include <list>

#include "Pads.h"
#include "FileSelector.h"

typedef std::list<Scene*> SceneStack;

GLfloat Projection[4][4];
SDL_Surface* screen;
SceneStack sceneStack;

#ifdef WIN32
extern "C" 
#endif
GL_API int GL_APIENTRY _dgles_load_library(void *, void *(*)(void *, const char *));

static void *proc_loader(void *h, const char *name) {
    (void) h;
    return SDL_GL_GetProcAddress(name);
}

void InitProjection() {
	// Create an orthographic projection with screen coordinates
	/*
	GLfloat Projection[] = {
		2.0 / (GLfloat)screen->w, 0.0, 0.0, -1.0,
		0.0, -2.0 / (GLfloat)screen->h, 0.0, 1.0,
		0.0, 0.0, 1.0, 0.0,
		0.0, 0.0, 0.0, 1.0
	};
	*/

	// Lord knows why this works and the above fails.
    memset(Projection, 0, sizeof(Projection));

    Projection[0][0] = 2.0f / (GLfloat)screen->w;
	Projection[3][0] = -1.0f;
    Projection[1][1] = -2.0f / (GLfloat)screen->h;
    Projection[3][1] = 1.0f;
	Projection[2][2] = 1.0f;
    Projection[3][3] = 1.0f;
}

void pushScene(Scene* s) {
	sceneStack.push_back(s);
}

int main(int argc, char** argv) {
    // Initialize the SDL library with the Video subsystem
    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE);
    atexit(SDL_Quit);
    
    // start the PDL library
    PDL_Init(0);
    atexit(PDL_Quit);
    
    // Tell it to use OpenGL version 2.0
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);

    // Set the video mode to full screen with OpenGL-ES support
    screen = SDL_SetVideoMode(320, 480, 0, SDL_OPENGL);

#if WIN32
    // Load the desktop OpenGL-ES emulation library
    _dgles_load_library(NULL, proc_loader);
#endif

	// Set up event filtering
	//SDL_SetEventFilter(event_filter);

	InitProjection();

	if (Mix_OpenAudio(44100, AUDIO_S16SYS, 1, 1024) == -1) {
		printf("Could not initialize audio\n");
		exit(1);
	}
	int channels = Mix_AllocateChannels(9);
	//printf("Allocated %d channels\n", channels);

	pushScene(new Pads(screen));

    // Event descriptor
    SDL_Event Event;
	Uint32 lastEvent;
	bool paused = false;
	int t;
	int last_t = 0;

    while (1) {
        bool gotEvent;
        if (paused) {
            SDL_WaitEvent(&Event);
            gotEvent = true;
        }
        else {
            gotEvent = SDL_PollEvent(&Event);
			t = SDL_GetTicks();
        }
        
        while (gotEvent) {
			if (Event.type == SDL_ACTIVEEVENT) {
				if (Event.active.state == SDL_APPACTIVE) {
					paused = !Event.active.gain;
				}
			}

			sceneStack.back()->handleEvents(t, Event);
            gotEvent = SDL_PollEvent(&Event);
			t = SDL_GetTicks();
        }

		for (SceneStack::iterator it = sceneStack.begin(); it != sceneStack.end(); it++)
			(*it)->update(t);

		// Skip drawing if we drew less than 50ms ago
		if (t - last_t < 50)
			continue;
		last_t = t;

		for (SceneStack::iterator it = sceneStack.begin(); it != sceneStack.end(); it++)
			(*it)->draw(t);

	    SDL_GL_SwapBuffers();
    }

    return 0;
}