#include <conio.h>
#include <stdio.h>

#include "geo.h"
#include "bgraphic.h"
#include "util.h"

#define CTRL(x)		(x-64)


void getstr(int attr, int x, int y, char *buf, int siz)
{
	char * p;
	int k,len=0;

	p = buf;

	for (;;)
	{
		k = getch();
		switch(k)
		{
			case 27:
				*buf=0;
				return;

			case '\r':
				*p=0;
				return;

			case '\b':
				if (p>buf)
				{
					p--;
					len--;
					GraphicsHandler->clreol(x+len*10,y);
				}
				break;

			default:
				if (k >= 32 && k <= 126)
				{
					if (len<siz)
					{
						*p++ = k;
						GraphicsHandler->printf(attr,x+len*10,y,"%c",k);
						len++;
					}
				}
				break;
		}
	}
}

void save()
{
	char fn[41];
	FILE * f;
	int x,y,x1,y1;
	int size,size2;
	int mode,c;

	int step = pow(2,GEO_LEVEL-LEVEL);


	GraphicsHandler->clreol(0,420);
	GraphicsHandler->printf(LIGHTGRAY,0,420,"Save as (A) ASCII or (E) elevation data?");
	for(;;)
	{
		mode = getch();
		if (mode == 27)
		{
			GraphicsHandler->clreol(0,420);
			return;
		}
		else if (mode == 'a')
		{
			if (LEVEL<6)
			{
				GraphicsHandler->clreol(0,420);
				GraphicsHandler->printf(LIGHTGRAY,0,420,"Map too small");
				return;
			}
			size2 = SIZE2 / 64;
			size  = SIZE  / 32;
			break;
		}
		else if (mode == 'e')
			break;
	}

	GraphicsHandler->clreol(0,420);
	GraphicsHandler->printf(LIGHTGRAY,0,420,"Save filename:");
	getstr(LIGHTGREEN,150,420,fn,40);
	if (*fn==0)
	{
		GraphicsHandler->clreol(0,420);
		return;
	}

	f = fopen(fn,"wb");
	if (f == 0)
	{
		GraphicsHandler->clreol(0,420);
		GraphicsHandler->printf(LIGHTGRAY,0,420,"Cannot open '%s'",fn);
		return;
	}

	GraphicsHandler->clreol(0,420);
	GraphicsHandler->printf(LIGHTRED,0,420,"Saving        as %s",
		(mode=='e'?"elevation data":"ascii 64x32"));

	if (mode == 'e')
	{
		fputc(LEVEL,f);
		for (x=0; x<SIZE2; x+=step)
		{
			if ((x & 15) == 0)
				GraphicsHandler->printf(LIGHTRED,0,420,"Saving %3d%%",
					int((long(x)*100)/SIZE2));

			for (y=0; y<SIZE; y+=step)

#if sizeof(CELL)==1
				fputc(cell[x][y].elev, f);
#else
				putw(cell[x][y].elev, f);
#endif
		}
	}
	else if (mode == 'a')
	{
		int count;
		CELL2 sum;

		for (y=0; y<SIZE-1; y+=size)
		{
			if ((y & 0x000F) == 0)
				GraphicsHandler->printf(LIGHTRED,0,420,"Saving %3d%%",
					int((long(y)*100)/SIZE));

			for (x=0; x<SIZE2-1; x+=size2)
			{
				sum = 0;
				count = 0;

				for (y1 = 0; y1 < size; y1+=step)
					for (x1 = 0; x1 < size2;  x1+=step)
					{
						sum += cell[x+x1][y+y1].elev;
						count++;
					}
				sum /= count; // calculate average height
				sum -= sea;

#if sizeof(CELL)==1
				sum >>= 4;
#else
				sum /= 2000;
#endif

				if (sum <= 0)      c = '-';
				else if (sum <= 1) c = '0';
				else if (sum <= 2) c = '1';
				else if (sum <= 3) c = '2';
				else if (sum <= 4) c = '3';
				else if (sum <= 5) c = '4';
				else if (sum <= 6) c = '5';
				else if (sum <= 7) c = '6';
				else if (sum <= 8) c = '7';
				else if (sum <= 9) c = '8';
				else               c = '9';

				fputc(c,f);
			}
			fputc('\n',f);
		}
	}

	fclose(f);
	GraphicsHandler->clreol(0,420);
}

void load()
{
	char fn[41];
	FILE * f;
	int x,y;

	GraphicsHandler->clreol(0,420);
	GraphicsHandler->printf(LIGHTGRAY,0,420,"Load filename:");
	getstr(LIGHTGREEN,150,420,fn,40);
	if (*fn==0)
	{
		GraphicsHandler->clreol(0,420);
		return;
	}

	f = fopen(fn,"rb");
	if (f == 0)
	{
		GraphicsHandler->clreol(0,420);
		GraphicsHandler->printf(LIGHTGRAY,0,420,"Cannot open '%s'",fn);
		return;
	}

	GraphicsHandler->clreol(0,420);
	GraphicsHandler->printf(LIGHTRED,0,420,"Loading");

	LEVEL=fgetc(f);
	if (LEVEL>GEO_LEVEL)
		LEVEL=GEO_LEVEL;

	int step = pow(2,GEO_LEVEL-LEVEL);

	for (x=0; x<SIZE2; x+=step)
	{
		if ((x & 15) == 0)
			GraphicsHandler->printf(LIGHTRED,0,420,"Loading %3d%%",
				int((long(x)*100)/SIZE2));

		for (y=0; y<SIZE; y+=step)

#if sizeof(CELL)==1
			cell[x][y].elev = fgetc(f);
#else
			cell[x][y].elev = getw(f);
#endif
	}

	fclose(f);
	GraphicsHandler->clreol(0,420);
}


#if sizeof(CELL)==1
#define INC1 1
#define INC2 4
#else
#define INC1 50
#define INC2 250
#endif

void geo_menu()
{
	char query,nodraw=0,proj=0;

	if (LEVEL<1)
		LEVEL=1;
	else if (LEVEL>GEO_LEVEL)
		LEVEL=GEO_LEVEL;

	SIZE2 = GEO_SIZE2;
	SIZE  = GEO_SIZE;

	new_map();

	for(;;)
	{
		if (!nodraw)
			map_draw(proj);

		GraphicsHandler->clreol (0,360);
		GraphicsHandler->hprintf (LIGHTGRAY, YELLOW, 0,360,
			"^new  ^smooth s^quare s^Qrt sc^ale ^erode ^E^S^C quit");

		GraphicsHandler->clreol (0,370);
		GraphicsHandler->hprintf (LIGHTGRAY, YELLOW, 0,370,
			"^Level %d  ^roughness %-3d  ^Sea %-6d  ^drainage  pro^j: %s",
				LEVEL, R, sea,
				(proj==0?"flat":
					(proj==1?"globe":
						(proj==2?"hemi":"quad"))));

		GraphicsHandler->clreol (0,380);
		GraphicsHandler->hprintf (LIGHTGRAY, YELLOW, 0,380,
			"^overlap %-3s  ^wrap %-3s  ^hide  CTL-^Save  CTL-^Load",
				(overlap?"ON":"OFF"),
				(wrap?"ON":"OFF"));

		GraphicsHandler->clreol (0,390);
		GraphicsHandler->hprintf (LIGHTGRAY, YELLOW, 0,390,
			"^Rivers %-3s  con^tours %-4d  ^color %s  ^zoom  un^Zoom  ^CLS",
				(rivers?"ON":"OFF"),
				contours,
				(colors==1?"normal":
					(colors==2?"alternate":
						(colors==3?"brown":
							(colors==4?"red":
								"black & white")))));

		query = getch();

		nodraw=1;

		switch(query)
		{
			case CTRL('S'): save(); break;
			case CTRL('L'): load(); break;

			case 'a':	rescale(); break;
			case 'C':	map_erase(); break;
			case 'c':	colors++;
						if (colors == 5) colors = 0;
						break;
//			case 'd':	calc_runoff(); break;
			case 'e':	map_erode(); break;
			case 'h':  	GraphicsHandler->clreol (0,360);
						GraphicsHandler->clreol (0,370);
						GraphicsHandler->clreol (0,380);
						GraphicsHandler->clreol (0,390);
						getch();
						break;

			case 'j':	proj++;
						if (proj>3) proj=0;
						map_erase();
						break;

			case 'l':

				GraphicsHandler->clreol (0,400);
				GraphicsHandler->printf (LIGHTGRAY,0,400,
							"Level (1-%d) ?",GEO_LEVEL);
				query = getch();
				if (query>='1' && query<=('0'+GEO_LEVEL))
					LEVEL = query - 48;
				GraphicsHandler->clreol (0,400);

				if (LEVEL<1)
					LEVEL=1;
				else if (LEVEL>GEO_LEVEL)
					LEVEL=GEO_LEVEL;

				break;

			case 'n':	new_map();			// generate new
						GraphicsHandler->clreol (0,420);
						map_erase();
						nodraw = 0;
						break;

			case 'o':	if (overlap == 1) // toggle
							overlap = 0;
						else
							overlap = 1;
						map_erase();
						break;

			case 'q':	square_filter(); break;
			case 'Q':	sqrt_filter(); break;
			case 'r':

				GraphicsHandler->clreol(0,370);
				GraphicsHandler->PutString (LIGHTGRAY,0,370,
					"Roughness (1=10, A=100; F=150; +/-) ?");
				query = getch();
				switch (query)
				{
					case '1':				R =  10;	break;
					case '2':				R =  20;	break;
					case '3':				R =  30;	break;
					case '4':				R =  40;	break;
					case '5':				R =  50;	break;
					case '6':				R =  60;	break;
					case '7':				R =  70;	break;
					case '8':				R =  80;	break;
					case '9':				R =  90;	break;
					case 'a':	case 'A':	R = 100;	break;
					case 'b':	case 'B':	R = 110;	break;
					case 'c':	case 'C':	R = 120;	break;
					case 'd':	case 'D':	R = 130;	break;
					case 'e':	case 'E':	R = 140;	break;
					case 'f':	case 'F':	R = 150;	break;
					case '+':				R += 1;		break;
					case '-':				R -= 1;		break;
				}
				if (R<10) R=10; else if (R>150) R=150;

				GraphicsHandler->clreol (0,370);
				nodraw = 1;
				break;

			case 'R':	if (rivers == 1) // toggle
							rivers = 0;
						else
							rivers = 1;
						break;

			case 's':	map_smooth(); break;

			case 'S':

				GraphicsHandler->clreol (0,400);
				GraphicsHandler->hprintf (LIGHTGRAY,YELLOW,0,400,
#if sizeof(CELL)==1
					"[^+^-] %d  [^<^>] %d  [^0] 0  "
					"[^2] 32  [^4] 64  [^6] 96  [^8] 128"
#else
					"[^+^-] %d  [^<^>] %d  [^1] 2000  "
					"[^3] 6000  [^5] 10000  [^7] 14000  [^9] 18000"
#endif
						,INC1,INC2);
				query = getch();
				break;

			case '+':	sea += INC1; break;
			case '-':	sea -= INC1; break;
			case ',':
			case '<':	sea -= INC2; break;
			case '.':
			case '>':	sea += INC2; break;

#if sizeof(CELL)==1
			case '0':	sea =     0; break;
			case '1':	sea =    16; break;
			case '2':	sea =    32; break;
			case '3':	sea =    48; break;
			case '4':   sea =    64; break;
			case '5':	sea =    80; break;
			case '6':	sea =    96; break;
			case '7':	sea =   112; break;
			case '8':	sea =   128; break;
			case '9':	sea =   144; break;
#else
			case '0':	sea =     0; break;
			case '1':	sea =  2000; break;
			case '2':	sea =  4000; break;
			case '3':	sea =  6000; break;
			case '4':   sea =  8000; break;
			case '5':	sea = 10000; break;
			case '6':	sea = 12000; break;
			case '7':	sea = 14000; break;
			case '8':	sea = 16000; break;
			case '9':	sea = 18000; break;
#endif


			case 'x':
			case 't':	if (contours > 0) // toggle
							contours = 0;
						else
							contours = (INC2*4);
						break;

			case 'w':	if (wrap == 1)
							wrap = 0;
						else
							wrap = 1;
						break;


			case 'z':	if (LEVEL<GEO_LEVEL)
						{
							LEVEL++;
							map_calc(LEVEL);
							nodraw=0;
						}
						break;
			case 'Z':	if (LEVEL>1)
						{
							if (LEVEL==4) map_erase();
							LEVEL--;
							nodraw=0;
						}
						break;
			case '[':	contours -= INC2; break;
			case ']':	contours += INC2; break;

			case ' ':	nodraw = 0;			// redraw
						break;
			case 27:	return;
			default:	nodraw = 1;	break;
		}
	}
}
