// Author : Jovian HERSEMEULE
#include <iostream>
#include <SDL/SDL.h>

#define BLOC_SIZE 16
#define WIDTH 100
#define HEIGHT 50
#define BLOC_TOTAL 4

enum blocType {WATER, MOUNTAIN, GRASS, DESERT};

void drawWorld(float world[HEIGHT][WIDTH][BLOC_TOTAL], SDL_Surface* tileSet[], SDL_Surface* out) {
	SDL_Rect pos({0, 0, 0, 0});
	SDL_Surface* select; // Current surface selected ! DO NOT FREE !

	for (int y(0); y < HEIGHT; y++)
		for (int x(0); x < WIDTH; x++) {
			select = tileSet[0];
			pos.x = x * BLOC_SIZE;
			pos.y = y * BLOC_SIZE;

			// Select the tile with highest level
			for (int k(1); k < BLOC_TOTAL; k++)
				if (world[y][x][k] > world[y][x][k - 1])
					select = tileSet[k];

			SDL_BlitSurface(select, NULL, out, &pos);
		}

}

int main()
{
	/// [1] Start
	// [1.1] Start SDL
	if ( SDL_Init( SDL_INIT_VIDEO ) < 0)
	{
		std::cout << "Can't initialize SDL: " << SDL_GetError() << std::endl;
		return 1;
	}

	// [1.2] Anticipate quit
	atexit(SDL_Quit);

	// [1.3] Set title
	SDL_WM_SetCaption("Application SDL", 0);

	/// [2] Create components
	// [2.1] Create window
	SDL_Surface* screen = SDL_SetVideoMode(WIDTH * BLOC_SIZE, HEIGHT * BLOC_SIZE, 32, SDL_HWSURFACE|SDL_DOUBLEBUF);
	if ( !screen )
	{
		std::cout << "Unable to set " << WIDTH << "x" << HEIGHT << " video: " << SDL_GetError() << std::endl;
		return 1;
	}

	// [2.2] Load textures
	SDL_Surface* grass = SDL_LoadBMP("textures/grass.bmp");
	SDL_Surface* water = SDL_LoadBMP("textures/water.bmp");
	SDL_Surface* desert = SDL_LoadBMP("textures/desert.bmp");
	SDL_Surface* mountain = SDL_LoadBMP("textures/mountain.bmp");
	SDL_Surface* pawn = SDL_LoadBMP("textures/pawn.bmp");

	// [2.3] Create variables
	SDL_Rect pawnPos({0, 0, 0, 0});

	// [2.4] Create world
	float world[HEIGHT][WIDTH][BLOC_TOTAL];

	// Clear world
	for (int j(0); j < HEIGHT; j++)
		for (int i(0); i < WIDTH; i++)
			for (int t(0); t < BLOC_TOTAL; t++)
				world[j][i][t] = 0.0f;

	// Basic water
	const int waterLevel = 0.01f;
	for (int j(0); j < HEIGHT; j++)
		for (int i(0); i < WIDTH; i++)
			world[j][i][WATER] = waterLevel;

	// Top mountain line
	const int mountainLevel = 10.0f;
	for (int j(0); j < HEIGHT; j++)
		for (int i(0); i < WIDTH; i++)
			world[j][i][MOUNTAIN] = mountainLevel / (1 + j);

	// [2.5] Surface containers
	SDL_Surface* tileSet[BLOC_TOTAL] = {water, mountain, grass, desert};
	SDL_Surface* map = SDL_CreateRGBSurface(SDL_HWSURFACE, WIDTH * BLOC_SIZE, HEIGHT * BLOC_SIZE, 32, 0x0, 0x0, 0x0, 0x0);

	// [2.6] First map render
	drawWorld(world, tileSet, map);

	/// [3] Main loop
	bool done(false);
	while (!done)
	{
		// [3.1] Events
		SDL_Event event;
		while (SDL_PollEvent(&event))
		{
			switch (event.type)
			{
				case SDL_QUIT:
					done = true;
					break;
				case SDL_KEYDOWN:
					if (event.key.keysym.sym == SDLK_ESCAPE)
						done = true;
					break;
				case SDL_MOUSEMOTION:
					pawnPos.x = (event.motion.x / pawn->w) * pawn->w;
					pawnPos.y = (event.motion.y / pawn->h) * pawn->h;
					break;
			} // end switch event type
		} // end of message processing

		// [3.2] Compute
		// Nothing for now

		// [3.3] Draw phase
		SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 0, 255, 255));

		SDL_BlitSurface(map, NULL, screen, NULL);

		SDL_BlitSurface(pawn, NULL, screen, &pawnPos);

		SDL_Flip(screen);

		SDL_Delay(16);
	} // end of main loop

	///[4] Free components
	SDL_FreeSurface(grass);
	SDL_FreeSurface(water);
	SDL_FreeSurface(desert);
	SDL_FreeSurface(mountain);
	SDL_FreeSurface(pawn);

	SDL_FreeSurface(screen);

	std::cout << "No error caught." << std::endl;
	return 0;
}