#include "spec.h"

typedef struct CELL {
	char * chr;
	enum COLOR clr;
} CELL;
CELL CANVAS[25][40];
void Stamp(char * chr,char col, char row, enum COLOR clr){
	if (col >= 40 || col < 0) return;
	if (row >= 25 || row < 0) return;
	CANVAS[row][col].chr = chr;
	if (clr) CANVAS[row][col].clr = clr;
}
void Paint(char col, char row, enum COLOR clr){
	if (col >= 40 || col < 0) return;
	if (row >= 25 || row < 0) return;
	CANVAS[row][col].clr = clr;
	CANVAS[row][col].chr = 0;
}

void Refresh(){
	//it should be considered for the dos version to not redraw constantly
	for (int row=0;row<25;row++)
	for (int col=0;col<40;col++){
		CELL cell = CANVAS[row][col];
		if (cell.chr == 0) Plt(col, row, cell.clr );
		else Prnt(cell.chr, col, row, cell.clr);
	}
}


void Tree(char x,char y,char h){
	int hy=y-h;
	Sqr(x,hy,1,h,Greenless+Red);
	Sqr(x-2,hy-3,5,4,Green);
}


void Street(char x, char y,char u, char r,char d, char l){
    if (u) Stamp("|",x+1,y,Yellow);
    if (r) Stamp("-",x+2,y+1,Yellow);
    if (d) Stamp("|",x+1,y+2,Yellow);
    if (l) Stamp("-",x,y+1,Yellow);
}

void Building(char x,char y,char h){
	if (h<2) h=2;
	int w=3;
	int d=3;
	y = y - h;
	//roof
	Sqr(x, y  ,w, d, Cyanless);
	//wall
	Sqr(x, y+d,w, h, Magenta);
	//windows
	int col=x+1;
	for(int row=y+d+h-1;row>y+d;row-=2)
	if (Dice() < 4) Paint(col,row,Yellowless);
	else Paint(col,row,Yellower);
}

void Pond(char x,char y) {
    for (int xx=0;xx<3;xx++)
    for (int yy=0;yy<3;yy++)
    if (Dice() > 3)	Paint(x+xx,y+yy,Blue);
    else Paint(x+xx,y+yy,Blueless);
}

void Lamp(char x, char y, enum COLOR clr){
	x = (x * 3)+1;
	y = (y * 3)+1;
	for(int col=0;col<3;col++)
	for(int row=0;row<3;row++){
		Paint(x+col-1,y+row-1,clr);
		
	}
	Stamp("*",x,y,clr);
	//Paint(x,y-1,clr);
	//Paint(x-1,y,clr);
	//Paint(x+1,y,clr);
}

char * _CITY [] = {
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
"~~~    #    #    #    #   ~~~",
"~~~  T #    #    #  t #   ~~~",
"~~~    #    #    #    #   ~~~",
"~~~3333#2222#2222#3333#222~~~",
"~~~3333#2222#2222#3333#222~~~",
"~~~3333#2222#2222#3333#222~~~",
"~~~    #    #    #    #   ~~~",
"~~~    #    #    #    #   ~~~",
"~~~  T #  t #  t #t  t# T ~~~",
"~~~    #    #    #    #   ~~~",
"~~~    #    #    #    #   ~~~",
"~~~#######################~~~",
"~~~    #    #    #    #   ~~~",
"~~~  * # *  # *  # *  #   ~~~",
"~~~    #    #    #    #   ~~~",
"~~~2222#2222#2222#1111#111~~~",
"~~~2222#2222#2222#1111#111~~~",
"~~~2222#2222#2222#1111#111~~~",
"~~~2222#2222#2222#1111#111~~~",
"~~~    #    #    #    #   ~~~",
"~~~    #    #    #    #   ~~~",
"~~~    #    #    #    #   ~~~",
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
0
};

void Gen(char b,int x, int y){
        //building
		if (b >= '0' && b <= '9'){
			int h = 3 * (b - '0');
			Building(x*3,y*3,h*1);	
		}
        //street
		else if (b == '#'){
			//char u = y < 1 ? 1 : CITY[y-1][x] == '#';
			//char d = y > 9 ? 1 : CITY[y+1][x] == '#';
			//char l = x < 1 ? 1 : CITY[y][x-1] == '#';
			//char r = x > 24 ? 1 : CITY[y][x+1] == '#';
            Street(x*3,y*3,1,1,1,1);//u,r,d,l);
		}
        //water
        else if (b == '~'){
            Pond(x*3,y*3);
        }
        //tree
        else if (b == 't'){
            Tree(x*3+1,y*3+1,4);
        }
        else if (b == 'T'){
            Tree(x*3+1,y*3+1,7);
        }
	else if (b == '*'){
		Lamp(x,y,Yellowless);
	}
	//}
	//}
}

#define bw 10
#define bh 10
void Map(char ** CITY, void (*fn)(char,int,int),int col,int row,int rotation){
	char buff[bh][bw];
	//clear
	for (int x=0;x<bw;x++)
	for (int y=0;y<bh;y++)
		buff[y][x]=0;
	//anti crash
	if (col < 0) col=0;
	if (row < 0) row=0;
	for (int y=0; y<=row ;y++){
		if (CITY[y] == 0) return;
		for (int x=0; x<=col ;x++)
		if (CITY[y][x] == 0) return;
	}
	//read
	for (int y=0; y<bh && CITY[y+row]!=0 ;y++)
	for (int x=0; x<bw && CITY[y+row][x+col]!=0 ;x++)
		buff[y][x]=CITY[y+row][x+col];
	//rotation
	rotation = rotation %4;
	if (rotation<0)	rotation = 4-rotation;
	//perfect rotation 56 loop for 15x15
	while(rotation>0){
		int bi = bw - 1;
		int bj = bi / 2;
		rotation--;
		for (int j=0;j<bj;j++)
		for (int i=j;i<bi-j;i++){
			char a = buff[j][i];
		/*nort*/buff[j][i] = buff[bi-i][j];
		/*west*/buff[bi-i][j] = buff[bi-j][bi-i];
			buff[bi-j][bi-i] = buff[i][bi-j];
		/*east*/buff[i][bi-j] = a;
		}
	}
	//render
	for (int x=0;x<bw;x++)
	for (int y=0;y<bh;y++)
		fn(buff[y][x],x,y);
}


void Droplet(int x, int y, int t){
	int h = 10;
	if (t % h == 9){
		Stamp("o",x,y,Blue);
	}
	else if (t % h == 0){
		Stamp("O",x,y,Blue);
	}
	else {
		Stamp("|",x,y-h+(t%h),0);
	}
}




void Wait(Co c){
    //Sqr(80,25,black);
    AnyKey(c,0);
}

int rotation = 0;
int x =0;
int y =0;
int droplet = 0;
void City(Co c){
	Map(_CITY,Gen,x,y,rotation);
	switch(rotation%4){
	case 0:Palette(72,0,1,1);break;
	case 1:Palette(72,42,1,1);break;
	case 2:Palette(0,42,1,1);break;
	case 3:Palette(0,0,1,1);break;
	}

	droplet = (++droplet) % 11;
	Droplet(10,28,droplet);
	Droplet(60,27,droplet-1);
	Droplet(30,29,droplet-2);
	Droplet(40,26,droplet-3);
	Droplet(20,26,droplet-4);
	Droplet(50,14,droplet-5);
	Droplet(15,14,droplet-6);
	Droplet(55,14,droplet-7);
	Droplet(35,14,droplet-8);
	Droplet(65,14,droplet-9);


	//AnyKey(c,0);
	Clr();
	if(Btn(Esc) ){
		c->routine = Wait;
	}
	if(Btn(Lt)){
		rotation++;
	}
	if(Btn(Rt)){
		rotation--;
	}
	if (Btn(Up)){
		switch(rotation % 4){
		case 0: y--; break;
		case 1: x--; break;
		case 2: y++; break;
		case 3: x++; break;
		}
	}
	if (Btn(Dn)){
		switch(rotation % 4){
		case 2: y--; break;
		case 3: x--; break;
		case 0: y++; break;
		case 1: x++; break;
		}
	}

	Tck();

	Refresh();
	Sqr(0,0,80,50,Black);
}



