#include "level.h"
#include <stdio.h>
#include <string.h>
#include "utils.h"
#include "printer.h"

Level *load_level_map(char *filename){
	int i, nchars;
	FILE *fin=open_file(filename,"r");
	Level *level=dmalloc(sizeof(Level));

	/* Read n cols and n rows from file */
	fscanf(fin,"%d\n%d\n", &(level->rows), &(level->cols));
	level->map=dmalloc(sizeof(char *)*level->rows);
	
	for(i=0; i<level->rows; i++){
		level->map[i]=dmalloc(sizeof(char *)*level->cols);
		nchars=fscanf(fin,"%s\n", level->map[i]);
		if(nchars<1 || strlen(level->map[i])<level->cols) {
			fprintf(stderr,"Read error at line %d (rows: %d, cols: %d): %s\n", i, 
							level->rows, level->cols, level->map[i]);
			fprintf(stderr,"Items read: %d; string length: %d\n", nchars, 
							(int)strlen(level->map[i]));
			return NULL;		
		}
	}
	return level;
}

Level *load_level(char *filename){
	int i, depth, end=1;
	char buf1[128];
	char buf2[128];
	Level *level=NULL;
	FILE *fin=open_file(filename, "r");

	fscanf(fin,"name:%s\n",buf1);
	fscanf(fin,"depth:%d\n",&depth);
	fscanf(fin,"map:%s\n", buf2);
	level=load_level_map(buf2);
	
	level->depth=depth;
	level->objs=dmalloc(sizeof(content)*MAXITEMS);
	reset(level->objs,sizeof(content)*MAXITEMS);
	
	for(i=0; end!=EOF && i<MAXITEMS; i++){
		int x, y, n, m, s;
		char sym;
		unsigned itype;
		end=fscanf(fin,"[%d,%d]:%c ", &x, &y, &sym);
		if (end<3) continue;
		debug("reading symbol %c", sym);
		itype=get_item_type_from_symbol(sym);
		if (itype!=NOITEM) {
			end=fscanf(fin,"%d %d %d\n", &n, &m, &s);
			add_item_to_level(level, x, y, itype, n, m, NULL, s);
		} else {
			level->objs[i].stash=NULL;
		}
		itype=get_monster_type_from_symbol(sym);
		if (itype!=NOITEM) {
			end=fscanf(fin,"\n");
			add_monster_to_level(level, x, y, itype);
		} else {
			level->objs[i].npc=NULL;
		}
		level->objs[i].special=0;
	}
	level->objs[i].valid=0;
	
	return level;
}

void print_level(Level *level, int row, int col, char pcsymbol){
	char **map;
	int i;
	/*! Create memory for the map and copy the base map from level */
	map=dmalloc(sizeof(char *)*level->rows);
	for(i=0; i<level->rows; i++){
		map[i]=strdup(level->map[i]);
	}
	/*! Add symbols for objects and monsters 
	 * \todo Monsters should be added after items, actually.
	 */
	for(i=0; level->objs[i].valid!=0 && i<MAXITEMS; i++){
		int x, y;
		x=level->objs[i].row;
		y=level->objs[i].col;
		if (level->objs[i].valid==VALID) {
			if (level->objs[i].stash) map[x][y]=get_item_symbol(level->objs[i].stash);
			if (level->objs[i].npc) map[x][y]=level->objs[i].npc->species->symbol;
		}
	}
	/*! Add the symbol corresponding to the PC */
	map[row][col]=pcsymbol;
	
	/*! Print out the map using the printer.h facilities */
	print_map(map, level->rows);
	
	/*! Deallocate the memory used for the map */
	for(i=0; i<level->rows; i++){
		dfree(map[i]);
	}
	dfree(map);
}

int count_objs_in_level(Level *level){
	int i;
	for(i=0; level->objs[i].valid!=INVALID && i<MAXITEMS; i++);
	return i;
}

void add_item_to_level(Level *level, int row, int col, item_types itype,
											 int quantity, int magic, char *text, int special){
		int i = count_objs_in_level(level);
		level->objs[i].row=row;
		level->objs[i].col=col;
		level->objs[i].stash=create_item(itype, quantity, magic, text, special);
		level->objs[i].valid=VALID;
}

void *remove_item_from_level(Level *level, int i) {
	void *res=NULL;
	level->objs[i].valid=REMOVED;
	if (level->objs[i].stash) res=level->objs[i].stash;
	if (level->objs[i].npc) res=level->objs[i].npc;
	level->objs[i].npc=NULL;
	level->objs[i].stash=NULL;
	return res;
}

monster *find_monster_at(Level *level, int row, int col){
	int i;
	for(i=0; i<count_objs_in_level(level); i++)
		if (level->objs[i].valid==VALID && level->objs[i].row==row && 
		    level->objs[i].col==col && level->objs[i].npc!=NULL)
			return level->objs[i].npc;
	return NULL;
}

void remove_monster_from_level(Level *level, monster *npc){
	int i;
	for(i=0; i<count_objs_in_level(level); i++)
		if (level->objs[i].npc == npc) {
			destroy_monster(level->objs[i].npc);
			level->objs[i].valid=REMOVED;
		}		 
}

void add_monster_to_level(Level *level, int row, int col, monsters type){
	int i = count_objs_in_level(level);
	level->objs[i].row=row;
	level->objs[i].col=col;
	level->objs[i].npc=create_monster(type);
	level->objs[i].valid=VALID;
}

occupation can_move_to(Level *level, int row, int col){
	if (level->map[row][col]!='.') return BUSY;
	if (find_monster_at(level, row, col)) return ATCK;
	return FREE;
}




#ifdef TEST_LEVEL
void print_end(char *s) {
	#ifdef CURSES
		refresh();
		napms(1000);
		mvprintw(LINES-1, COLS-11,s); 
		refresh();
		napms(1000);
	#endif /* CURSES */
}

int main(int argc, char **argv){
	Level *level;
	
	screen_init();
	level=load_level(argv[1]);
	print_level(level,8,2,'@');
	print_end("Curses Test");
	add_item_to_level(level, 7, 4, SCROLL, 1, 1, 0, 0);
	print_level(level,8,2,'@');
	print_end("%% Added    "); 
	screen_close();
	
	#ifdef CURSES
		printf("Test finished with curses\n");
	#else
		printf("Test finished without curses\n");
	#endif /* CURSES */
}
#endif /* TEST_LEVEL */
