#include <SDL/SDL.h>
#include <SDL/SDL_audio.h>

#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#include <emscripten/html5.h>
#endif
#include "spiel.hpp"
#include "meanbot15x15.xpm"
template<unsigned short SCRNW, unsigned short SCRNH, unsigned short FPS>
class Shit : public Api
{
	SDL_Surface* screen;

	Gen sndgen;
	Gen * sndgenQe;
	Uint16 sndgenQeIndex;


	int ScrW()
	{
		// detect screen resize and scale accordingly
		return SCRNW*3;
	}

	int ScrH()
	{
		return SCRNH*3;
	}

	static void audio_callback(void *userdata, Uint8 *_stream, int len) {
        /*
		Shit * shit = (Shit*) userdata;
		time_t nowms = time(NULL);
		time_t nowfq = (nowms*_RATE)/1000;
		for (int i = 0; i < len; i++)
		_stream[i] = shit->sndgen(nowfq+i);
		shit->NextSndGen();
        */
	}

	void NextSndGen()
	{
        /*
		if (this->sndgenQe == 0) return;
		unsigned i = this->sndgenQeIndex;

		if (this->sndgenQe[i] == 0) i = 0;
		this->sndgen = this->sndgenQe[i];
		i++;

		this->sndgenQeIndex = i;
        */
	}
	public:
	Shit()
	{

		//this->sndgenQe = GammeSineWave<_RATE>();
		this->sndgenQe = RickRoll<_RATE>();
		this->sndgenQeIndex = 0;
		this->sndgen = Mute<_RATE>;
		SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO);

		SDL_Surface *screen = SDL_SetVideoMode(this->ScrW(), this->ScrH(), 32, SDL_SWSURFACE);
		this->screen = screen;

		SDL_AudioSpec spec;
		spec.freq = _RATE;
		spec.format = AUDIO_U8;
		spec.channels = 1;
		spec.samples = 8192;
		spec.callback = Shit::audio_callback;
		spec.userdata = this;
		SDL_AudioSpec obtainedSpec;
		SDL_OpenAudio(&spec, &obtainedSpec);
		SDL_PauseAudio(0);

	}
	~Shit()
	{
		this->Gtfo();
	}

	void Delay(int delay)
	{
		#ifdef __EMSCRIPTEN__
		emscripten_sleep(delay);
		#else
		SDL_Delay(delay);
		#endif
	}

	bool Quit()
	{
		SDL_Event e;
		while( SDL_PollEvent( &e ) != 0 )
		{
		    //User requests quit
		    if( e.type == SDL_QUIT )
		    {
			    return true;
		    }
		}
		return false;
	}


	void Gtfo()
	{
		SDL_CloseAudio();
		#ifdef __EMSCRIPTEN__
		emscripten_cancel_main_loop();
		#else
		SDL_Quit();
		#endif
	}
	void Lock()
	{
		if (SDL_MUSTLOCK(this->screen)) SDL_LockSurface(this->screen);
	}
	void Unlock()
	{
		if (SDL_MUSTLOCK(this->screen)) SDL_UnlockSurface(this->screen);
	}
	void Refresh()
	{
		SDL_Flip(this->screen);
	}
	Uint32 Color(Uint8 R, Uint8 G, Uint8 B)
	{
		return SDL_MapRGBA(this->screen->format, R, G, B, 255);
	}

	void Plot(Uint16 x, Uint16 y, Uint32 color)
	{
		Uint16 xx = x*3,
		       yy = y*3;
		for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++)
		if (i == 2 || j == 2) *((Uint32*)this->screen->pixels + ((xx+i) * this->ScrW()) + (yy+j)) = 0;
		else *((Uint32*)this->screen->pixels + ((xx+i) * this->ScrW()) + (yy+j)) = color;
	}
	void SetSeq(Gen * seq)
	{
		SDL_LockAudio();

		this->sndgenQe = seq;
		this->sndgenQeIndex = 0;

		SDL_UnlockAudio();
	}
};



extern "C" int main(int argc, char** argv) {
	printf("hello, world!\n");

	Gen gens [] = {
		SquareWave<440,_RATE>,
		SineWave<440,_RATE>,
		0
	};

	Api * shit = new Shit<_SCRNW,_SCRNH,_FPS>();
	//shit->sndgenQe = gens;
	printf("B==D\n");

	Cunt * cunts[] = {
		new MapRGB(),
		new DrawShit(),
		new EveryFrame(),
		new AudioFrame()
	};
	Cunt * frm = new Cos<Api*>(cunts);

        while( 1 ) frm->Routine(shit);

	return 0;
}

