/*
SDL test. Daniel Edgecumbe 2011
*/

#include <stdio.h>
#include <stdlib.h>
#include <SDL/SDL.h>
#include <SDL/SDL_ttf.h>
#include <math.h>
#define PI 3.14159
#define SCREEN_W 480
#define SCREEN_H 272
int psi2[SCREEN_W]; // wavefunction probability psi^2

int main(int argc,char *argv[])
{
  if(SDL_Init(SDL_INIT_VIDEO) < 0) { return(1); }
  atexit(SDL_Quit);

	printf("================================================\n");
	printf("One-dimensional particle in a box simulation\n");
	printf("Dan Edgecumbe - Brasenose College, Oxford, 2012\n");
	printf("================================================\n");
	printf("Controls:\n");
	printf("[1]: Reset time to zero\n");
	printf("[2], [3], [...] : Increment time by 0.1, 0.01, ..\n");
	printf("[q], [e]: Vary number of superimposed modes 'w'\n");
	printf("[a]	, [d]: Vary std. dev of gaussian 'sd'\n");
	printf("[UP], [DOWN]: Vary central mode 'n'\n");
	printf("[LEFT], [RIGHT]: Vary speed of animation frequency 'f'\n");
	printf("[`]: Reset amplitude normalisation\n");
	printf("\n");
	printf("Running...\n");

  SDL_Surface *screen;
  screen = SDL_SetVideoMode(SCREEN_W, SCREEN_H, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
	SDL_WM_SetCaption("1D Particle in a box","1D Particle in a box");

  // setup SDL_TTF
  TTF_Init();
  TTF_Font *font = TTF_OpenFont("res/font/wendy.ttf", 20);
  SDL_Color clrFg = { 180, 180, 180, 0 };

  // create blank surface for screen refresh
  SDL_Surface *blank;
  blank = SDL_CreateRGBSurface(SDL_HWSURFACE, SCREEN_W, SCREEN_H, 32, 0, 0, 0, 0);
  SDL_Rect whole;
  whole.x = 0; whole.y = 0; whole.w = blank->w; whole.h = blank->h;

  // SDL variables
	Uint32 psi2_colour;  
	psi2_colour = SDL_MapRGB(screen->format,255,255,255);
	SDL_Event event;

	// user modifiable variables
	int n = 201;
	int width = 10;
	double gwidth = (width/2)*(width/2);
	double f = 0.00060;

	// program internal variables
	float A = 1;
	double t = 0;

	int running = 1;
	while(running) {
    SDL_BlitSurface(blank, NULL, screen, &whole); // blank screen

		int x;
		for (x=0;x<SCREEN_W;x++) {

			double re = 0, im = 0;
			int m; // currently enumerated mode
			float k, g; // wavevector, gaussian amplitude
			for (m=(n-width); m<=(n+width); m++) {
				k = m*PI / SCREEN_W;
				g = exp(-(float)((m-n)*(m-n))/(2*gwidth));
				re += A*g*sin(k*x)*cos(-m*m*2*PI*t);
				im += A*g*sin(k*x)*sin(-m*m*2*PI*t);
			}

			if ((re*re + im*im) < 1) { psi2[x] = (SCREEN_H)*(1 - (re*re + im*im)); }
			else {
				psi2[x] = 0;
				A = A/sqrt(re*re + im*im);
			}
			
			int y;
			for (y=SCREEN_H; y>psi2[x]; y--) {
				Uint32 *pixmem32;
				pixmem32 = (Uint32*) screen->pixels + (SCREEN_W)*y + x;
				*pixmem32 = psi2_colour;
			}

		}

		//render text
		char ostring[200];
		SDL_Rect rcDest;

		sprintf(ostring,"n: %d, w: %d, sd: %.2f", n, width, sqrt(gwidth));
		SDL_Surface *sText = TTF_RenderText_Solid(font, ostring, clrFg);
    rcDest.x = 4; rcDest.y = 0;
		rcDest.w = sText->w; rcDest.h = sText->h;
		SDL_BlitSurface(sText, NULL, screen, &rcDest);
    SDL_FreeSurface(sText);

		sprintf(ostring,"t: %.9f",t);
		sText = TTF_RenderText_Solid(font, ostring, clrFg);
    rcDest.x = 4; rcDest.y = 15;
		rcDest.w = sText->w; rcDest.h = sText->h;
		SDL_BlitSurface(sText, NULL, screen, &rcDest);
    SDL_FreeSurface(sText);

		sprintf(ostring,"f: %.9f",f);
		sText = TTF_RenderText_Solid(font, ostring, clrFg);
    rcDest.x = 4; rcDest.y = 30;
		rcDest.w = sText->w; rcDest.h = sText->h;
		SDL_BlitSurface(sText, NULL, screen, &rcDest);
    SDL_FreeSurface(sText);

    SDL_Flip(screen); // double buffering
    SDL_Delay(20); // frame delay

		while (SDL_PollEvent(&event)) {
			switch (event.type){
				case SDL_KEYDOWN:
					switch(event.key.keysym.sym){
						case SDLK_1:
							t = 0;
							break;
						case SDLK_2:
							t += 0.1;
							break;
						case SDLK_3:
							t += 0.01;
							break;
						case SDLK_4:
							t += 0.001;
							break;
						case SDLK_5:
							t += 0.0001;
							break;
						case SDLK_6:
							t += 0.00001;
							break;
						case SDLK_7:
							t += 0.000001;
							break;
						case SDLK_8:
							t += 0.0000001;
							break;
						case SDLK_BACKQUOTE:
							A = 1;
							break;
						case SDLK_a:
							if (gwidth > 0) { gwidth /= 1.1; }
							break;
						case SDLK_d:
							gwidth *= 1.1;
							break;
						case SDLK_q:
							if (width > 1) { width -= 1; }
							break;
						case SDLK_e:
							if (n > width+1) { width += 1; }
							break;
						case SDLK_UP:
							n += 10;
							break;
						case SDLK_DOWN:
							if ((n > 20) && (n > width+10)) { n -= 10; }
							break;
						case SDLK_LEFT:
							if (f > 0) { f /= 1.5;}
							break;
						case SDLK_RIGHT:
							f *= 1.5;
							break;
						case SDLK_ESCAPE:
							printf("Exit request detected.\n"); running = 0;
						default: break;
					}
				break;
				case SDL_QUIT:
					printf("Exit request detected.\n"); running = 0;
					break;
			}
		}
		t += f/60;
  }

  SDL_FreeSurface(blank);
  SDL_FreeSurface(screen);
  TTF_CloseFont(font);
  TTF_Quit();
  return(0);
}


