/* Bob */

#include <string.h>

#include "ripples.h"
#include "tilemap.h"
#include "texture.h"
#include "tile.h"
#include "log.h"


/* If x < 0, these functions will use the border texture. */

TILE_COLOUR_PROC tile_colour_proc[2][N_TILE_TYPES] = {
 {&tile_s_colour, &tile_s_colour, &tile_s_colour},
 {&tile_w_colour, &tile_w_colour, &tile_w_colour}
};


int tile_use_ripples[N_TILE_TYPES] = {0, 0, 1};


/* create_tilemap() does not initialise the tiles. It only allocates memory
   for them. All tile maps should be destroyed with destroy_tilemap() when
   you no longer need them. Do not count on the values in the tilemap returned
   by this function (appart from w and h). They are garbage.
*/
TILEMAP *create_tilemap(int w, int h) {

	TILEMAP *ret = malloc(sizeof(TILEMAP));
	int i;

	if (!ret) {
		LOG(ERROR "Tilemap::create_tilemap: Ran out of memory while trying to allocate %i bytes!\n", sizeof(TILEMAP));
		return NULL;
	}

	memset(ret, 0, sizeof(TILEMAP));

	ret->w = w;
	ret->h = h;

	ret->tile = malloc(sizeof(TILE*) * h);
	if (!ret->tile) {
		free(ret);
		LOG(ERROR "Tilemap::create_tilemap: Ran out of memory while trying to allocate %i bytes!\n", sizeof(TILE*) * h);
		return NULL;
	}

	for (i = 0; i < h; i++) {
		ret->tile[i] = malloc(sizeof(TILE) * w);

		/* No memory? */
		if (!ret->tile[i]) {
			int j;

			/* get rid of everything */
			for (j = 0; j < i; j++)
				free(ret->tile[j]);
			free(ret->tile);
			free(ret);

			LOG(ERROR "Tilemap::create_tilemap: Ran out of memory while trying to allocate %i bytes!\n", sizeof(TILE) * w);
			return NULL;
		}

		memset(ret->tile[i], 0, sizeof(TILE) * w);
	}

	return ret;
}


void destroy_tile(TILE *tile) {

	if (!tile)
		return;

	if (tile->ripples)
		destroy_ripples(tile->ripples);

	free(tile);

	return;
}



void destroy_tilemap(TILEMAP *map) {

	int i;

	if (!map)
		return;

    if (map->ripple_info) destroy_ripple_info(map->ripple_info);

	if (map->tile) {
		for (i = 0; i < map->h; i++)
			if (map->tile[i])
				destroy_tile(map->tile[i]);
		free(map->tile);
	}
	free(map);

	return;
}




void update_tilemap(TILEMAP *map) {
	int x, y;

	for (y = 0; y < map->h; y++) {
		for (x = 0; x < map->w; x++) {

			if (map->tile[y][x].ripples == 0 || map->tile[y][x].ripples->frame != map->ripple_info->frame) 
				continue;

			propagate_ripples(map->ripple_info,
				map->tile[y][x].ripples,
				x > 0        ? map->tile[y][x-1].ripples : 0,
				x < map->w-1 ? map->tile[y][x+1].ripples : 0,
				y > 0        ? map->tile[y-1][x].ripples : 0,
				y < map->h-1 ? map->tile[y+1][x].ripples : 0);
		}
	}

	finalise_ripples(map->ripple_info);
}
