#include <stdio.h>
#include "main.h"
#include "level.h"


LINKED_LEVEL *load_levels(const char *filename, int *n)
{
	LINKED_LEVEL *first = NULL, **currp = &first, *curr, *prev = NULL;
	FILE *f = fopen(filename, "rt");
	*n = 0;
	if (!f) return NULL;

	for (;;) {
		int x, y;

		curr = malloc(sizeof(*curr));
		if (!curr) {
			fclose(f);
			return first;
		}

		for (y = 0; y < LEVEL_H; y++) {
			char row[21];
			if (fscanf(f, "%20s", row) < 1) goto finished;
			for (x = 0; x < LEVEL_W; x++) {
				switch (row[x]) {
					case '.' : curr->level.map[y][x] = TILE_BLANK;                break;
					case '#' : curr->level.map[y][x] = TILE_WALL;                 break;
					case '%' : curr->level.map[y][x] = TILE_WEAK_WALL;            break;
					case '/' : curr->level.map[y][x] = TILE_DEFLECTOR_UP_RIGHT;   break;
					case '\\': curr->level.map[y][x] = TILE_DEFLECTOR_DOWN_RIGHT; break;
					case '*' : curr->level.map[y][x] = TILE_BOMB;                 break;
					case '^' : curr->level.map[y][x] = TILE_MOUND;                break;
					case 'x' : curr->level.map[y][x] = TILE_PIT;                  break;
					case 'o' : curr->level.map[y][x] = TILE_GOAL;                 break;
					case 'l' : curr->level.map[y][x] = TILE_BALL_LEFT;            break;
					case 'r' : curr->level.map[y][x] = TILE_BALL_RIGHT;           break;
					case 'u' : curr->level.map[y][x] = TILE_BALL_UP;              break;
					case 'd' : curr->level.map[y][x] = TILE_BALL_DOWN;            break;
					default: goto finished;
				}
			}
		}

		for (y = 0; y < TILE_N_PLACEABLE; y++) {
			if (fscanf(f, " %*c%d", &curr->n_to_place[y]) < 1)
				goto finished;
		}

		for (y = 0; y < LEVEL_H; y++)
			curr->level.map[y][0] = curr->level.map[y][LEVEL_W-1] = TILE_WALL;
		for (x = 0; x < LEVEL_W; x++)
			curr->level.map[0][x] = curr->level.map[LEVEL_H-1][x] = TILE_WALL;

		curr->prev = prev;
		curr->next = NULL;
		*currp = prev = curr;
		currp = &curr->next;
		(*n)++;
	}

	finished:
	free(curr);
	fclose(f);
	return first;
}


void unload_levels(LINKED_LEVEL *ll)
{
	if (ll) {
		LINKED_LEVEL *l = ll->prev;
		while (l) {
			LINKED_LEVEL *prev = l->prev;
			free(l);
			l = prev;
		}
		l = ll;
		while (l) {
			LINKED_LEVEL *next = l->next;
			free(l);
			l = next;
		}
	}
}
