#include <allegro.h>

#include <string.h> // strlen

#include <ctype.h> // isalnum

#include <stdio.h>

#include "menu.h"

#include "main.h"

#include "net.h"

#include "game.h"

Menu *menu = 0;

static BITMAP *button = 0;
static BITMAP *buttonl = 0;
static BITMAP *buttonp = 0;
static BITMAP *buttonlp = 0;
static BITMAP *bigball = 0;

static char *keynames[] = 
{
   "(none)",     "A",          "B",          "C",
   "D",          "E",          "F",          "G",
   "H",          "I",          "J",          "K",
   "L",          "M",          "N",          "O",
   "P",          "Q",          "R",          "S",
   "T",          "U",          "V",          "W",
   "X",          "Y",          "Z",          "0",
   "1",          "2",          "3",          "4",
   "5",          "6",          "7",          "8",
   "9",          "0_PAD",      "1_PAD",      "2_PAD",
   "3_PAD",      "4_PAD",      "5_PAD",      "6_PAD",
   "7_PAD",      "8_PAD",      "9_PAD",      "F1",
   "F2",         "F3",         "F4",         "F5",
   "F6",         "F7",         "F8",         "F9",
   "F10",        "F11",        "F12",        "ESC",
   "TILDE",      "MINUS",      "EQUALS",     "BACKSP",
   "TAB",        "OPENBR",     "CLOSEBR",    "ENTER",
   "COLON",      "QUOTE",      "BACKSL",     "BACKSL2",
   "COMMA",      "STOP",       "SLASH",      "SPACE",
   "INSERT",     "DEL",        "HOME",       "END",
   "PGUP",       "PGDN",       "LEFT",       "RIGHT",
   "UP",         "DOWN",       "SLASH_2",    "ASTER",
   "MINUS_2",    "PLUS_2",     "DEL_2",      "ENTER_2",
   "PRTSCR",     "PAUSE",      "ABNT_C1",    "YEN",
   "KANA",       "CONVERT",    "NOCONV",     "AT",
   "CFLEX",      "COLON2",     "KANJI",
   "LSHIFT",     "RSHIFT",     "LCTRL",      "RCTRL",
   "ALT",        "ALTGR",      "LWIN",       "RWIN",
   "MENU",       "SCRLOCK",    "NUMLOCK",    "CAPSLK",
   "MAX"
};

void Entry::set(int x_, int y_, int w_, int h_, char *name_) {
	x = x_;
	y = y_;
	w = w_;
	h = h_;
	can_edit = false;
	name = name_;
	is_active = false;	
	is_sel = false;
	can_change = false;
	is_editing = false;
	editpos = strlen(name);	
	editlen = editpos;
	row_next = 0;
	column_next = 0;
	is_sliding = false;
	val = 0;
}

void Entry::restore() {
	if(can_change) blit(background, page, x, y, x, y, w, h);			
			
}

void Entry::draw() {
	
	int c = 0;	
	
	
	
	if(can_change) {
		
		if(is_active) {
			set_palette((RGB *)(numberfont[2].dat));
			c = 2;
		} else {
			set_palette((RGB *)(numberfont[1].dat));
		}
		
		if(is_sel) {
			c += 1;
		} 
		
	
	
		int dx = x - 4;
		int dy = y - 3;
		
		if(&menu->entries[menu->AI_left] == this) {
			dx -= 192 - 40;
		}
					
		if(c == 0) draw_sprite(page, button, dx, dy);
		if(c == 1) draw_sprite(page, buttonl, dx, dy);
		if(c == 2) draw_sprite(page, buttonp, dx, dy);
		if(c == 3) draw_sprite(page, buttonlp, dx, dy);		
	
	} else {
	
		set_palette((RGB *)(numberfont[2].dat));
		rectfill(page, x, y, x + w - 1, y + h - 1, c);
	
	}
	
	if(is_sliding) {
		//circlefill(page, x + h / 2 + val * ((w - h) - 1) / 100, y + h / 2, h / 2 - 2, makecol(255, 255, 255));
		draw_sprite(page, bigball, x + val * ((w - h) - 1) / 100, y);	
		textprintf_centre(page, font,  x + h / 2 + val * ((w - h) - 1) / 100, y + h / 2,
			makecol(255, 0, 255), "%d", val);
	} else {
		text_mode(-1);
		
		textout(page, (FONT *)(numberfont[0].dat), name, x + 1, y + 1, -1);	
		if(is_key) {
			textprintf(page, (FONT *)(numberfont[0].dat), x + 31, y + 1, -1, "%s", keynames[val]);
		}
	}	
}

void Entry::addchar(char ch) {
	
	if(ch == 8) {			
		if(editpos > 0) editpos--;
		name[editpos] = 0;
	} else {
		if(editpos < editlen) {
			name[editpos] = ch;			
			editpos++;
			name[editpos] = 0;
			
			if(text_length((FONT *)(numberfont[0].dat), name) > w) {
				editpos--;
				name[editpos] = 0;
			}
			
		}
	}
}

int Menu::add_entry(int x, int y, int w, int h, char *name) {
	entries[num].set(x, y, w, h, name);
	num++;
	return num - 1;
}

Menu::Menu() {
	num = 0;
	sel = 0;	
	
	side = 0;	
	forceside = false;	
			
	windowed = 0;			
	strcpy(enter_name_str, "unknown");
	strcpy(enter_address_str, "0.0.0.0");
	
	loadconfig();
	
	int x = 25, y = 5;
	int w = 192;
	int h = 40;
			
	add_entry(x, y, w, h, "IdeaHack");
			
	y += h + 5;
	
	go = add_entry(x, y, w, h, "Deathmatch");
	
	add_entry(x + 200, y, w, h, "Name");
	int enter_name = add_entry(x + 400, y, w, h, enter_name_str);
	
	y += h + 5;


	#ifndef NO_LIBNET
				
		go_internet = add_entry(x, y, w, h, "Internet");
	
	#else
	
		go_internet = add_entry(x, y, w, h, "NO_NET");
	
	#endif
		
	
	add_entry(x + 200, y, w, h, "Address");
	int enter_address = add_entry(x + 400, y, w, h, enter_address_str);		
	
	y += h + 5;	
			
	add_entry(x + 200, y, w, h, "Send Rate");
	
	slide_net = add_entry(x + 400, y, w, h, "slider");
	entries[slide_net].val = netrate - 1;
	
	y += h + 5;		
	
	AI_left = add_entry(x + 200, y + 22, 40, h, "AI");
	add_entry(x + 200 + w / 2 - 40, y + 22, 80, h, "Keys");	
	AI_right = add_entry(x + 200 + w - 40, y + 22, 40, h, "AI");
	
	rec_left1 = add_entry(x, y, w, h, "{");	
	rec_left2 = add_entry(x + 400, y, w, h, "{");
	
	y += h + 5;
	
	
	rec_right1 = add_entry(x, y, w, h, "}");
	rec_right2 = add_entry(x + 400, y, w, h, "}");
		
	y += h + 5;
	
	go_fullscreen = add_entry(x, y, w, h, (char *)(windowed?"Fullscreen":"Windowed"));
	
	y += h + 5;
	
	add_entry(x + 200, y, w, h, "Sound Vol");	
	
	slide_sound = add_entry(x + 400, y, w, h, "slider");		
	entries[slide_sound].val = soundvol;
	
	y += h + 5;
	
	add_entry(x + 200, y, w, h, "Music Vol");	
	
	slide_music = add_entry(x + 400, y, w, h, "slider");
	entries[slide_music].val = musicvol;
	
	y += h + 5;					
					
	go_out = add_entry(x, y, w, h, "Exit");	
	
	go_story = add_entry(x + 400, y, w, h, "Story");			
	
	entries[rec_left1].val = t[0];
	entries[rec_right1].val = t[1];
	entries[rec_left2].val = t[2];
	entries[rec_right2].val = t[3];
	entries[rec_left1].is_key = true;
	entries[rec_right1].is_key = true;
	entries[rec_left2].is_key = true;
	entries[rec_right2].is_key = true;
	
	entries[AI_left].can_change = true;	
	entries[AI_right].can_change = true;	
		
	entries[enter_name].can_change = true;	
	entries[enter_name].can_edit = true;
	entries[enter_name].editlen = 40;		
	
	entries[enter_address].can_change = true;	
	entries[enter_address].can_edit = true;
	entries[enter_address].editlen = 40;
	
	entries[slide_music].can_change = true;	
	entries[slide_sound].can_change = true;	
	entries[slide_net].can_change = true;	
	
	entries[slide_music].is_sliding = true;	
	entries[slide_sound].is_sliding = true;	
	entries[slide_net].is_sliding = true;	
	
	entries[go_fullscreen].can_change = true;		
	
	entries[go_out].can_change = true;
	
	entries[go].can_change = true;
	
	entries[go_story].can_change = true;			
	
	entries[rec_left1].can_change = true;
	entries[rec_right1].can_change = true;
	entries[rec_left2].can_change = true;
	entries[rec_right2].can_change = true;
	
	sel = go;
	
	#ifndef NO_LIBNET
	
	if(network && network->channel) {		
		entries[go_internet].can_change = true;			
	}
	
	#endif
	
	entries[go].row_next = go_internet;
	entries[go_internet].row_next = rec_left1;					
	entries[rec_left1].row_next = AI_left;	
	entries[AI_left].row_next = rec_right1;	
	entries[rec_right1].row_next = go_fullscreen;	
	entries[go_fullscreen].row_next = go_out;	
					
	entries[enter_name].row_next = enter_address;
	entries[enter_address].row_next = slide_net;
	entries[slide_net].row_next = rec_left2;
	entries[rec_left2].row_next = AI_right;	
	entries[AI_right].row_next = rec_right2;	
	entries[rec_right2].row_next = slide_sound;
	entries[slide_sound].row_next = slide_music;
	entries[slide_music].row_next = go_story;						
		
	entries[AI_left].column_next = AI_right;	
		
	entries[go].column_next = enter_name;		
	
	entries[go_internet].column_next = enter_address;		
	
	entries[rec_left1].column_next = rec_left2;		
	
	entries[rec_right1].column_next = rec_right2;		
	
	entries[go_out].column_next = go_story;							
	
	time = 0;
		
}

void Menu::enter() {
	
	button = load_bitmap("dat.dat#button.bmp", NULL);
	buttonl = load_bitmap("dat.dat#buttonl.bmp", NULL);
	buttonp = load_bitmap("dat.dat#buttonp.bmp", NULL);
	buttonlp = load_bitmap("dat.dat#buttonlp.bmp", NULL);
	bigball = load_bitmap("dat.dat#bigball.bmp", NULL);
		
	background = load_bitmap("dat.dat#main.bmp", NULL);
	redraw_background();
	
	game->keyleft1 = entries[rec_left1].val;
	game->keyleft2 = entries[rec_left2].val;
	game->keyright1 = entries[rec_right1].val;
	game->keyright2 = entries[rec_right2].val;
}
void Menu::leave() {	
	destroy_bitmap(button);
	destroy_bitmap(buttonl);
	destroy_bitmap(buttonp);
	destroy_bitmap(buttonlp);
	destroy_bitmap(bigball);
	destroy_bitmap(background);	
}

int Menu::process(float d) {
	static float sendtime;
	static bool start = false;	
	
	if(recording == 2) {
		recordingflashtime -= d;
		if(recordingflashtime < 0) {
			recordingflashtime = 0.25;
			entries[sel].is_active = !entries[sel].is_active;
		}
	}
	
	#ifndef NO_LIBNET
	
	if(network && (connecting || acknowledging > time)) {
		
		if(net_query(network->channel))	{
			char buffer[256];
			int l = net_receive(network->channel, buffer, 256, NULL);		
			if(connecting && (l == 18) && !strncmp(buffer, "doitdoitdoitdamnit", 18)) {
				connecting = false;
				entries[go_internet].is_active = true;
				acknowledging = time + 5;
				start = true;
				if(side == 0) side = -1;
			}
		}
				
		
		if(sendtime <= 0) {
			if(side == 0) side = 1;
			net_send(network->channel, "doitdoitdoitdamnit", 18);					
			sendtime += 0.25;
			if(connecting) entries[go_internet].is_active = !entries[go_internet].is_active;
		} else {
			sendtime -= d;
		}
	} else {	
		if(start) {
			start = false;	
			game->netrate = 1.0 / float(netrate);			
			game->time2send = 0.0;
			game->side = side;			
			game->AI_left = false;
			game->AI_right = false;
			return 1;
		}
	}
	
	#endif
	
	if(recording == 1) {
		
		int k;
		
		for(k = 0; k < KEY_MAX; k++) {
			if(key[k]) break;
		}
		
		if(k == KEY_MAX) recording = 2;
		
	}
		
	if(recording == 2) {	
		
		for(int k = 0; k < KEY_MAX; k++) {
			if(key[k]) {
				recording = 3;
				entries[sel].is_active = false;
				entries[sel].val = k;
				
				game->keyleft1 = entries[rec_left1].val;
				game->keyleft2 = entries[rec_left2].val;
				game->keyright1 = entries[rec_right1].val;
				game->keyright2 = entries[rec_right2].val;
								
				break;
			}
		}
		
	}
	
	if(recording == 3) {
		
		int k;
		
		for(k = 0; k < KEY_MAX; k++) {
			if(key[k]) break;
		}
		
		if(k == KEY_MAX) recording = 0;
		
		while(keypressed()) readkey();
		
	}
				
	if(!recording)	
	while(keypressed()) {
		int ch = readkey();
		int k = ch >> 8;
		ch &= 255;
						
		if(k == KEY_ESC) {
			saveconfig();
			return 2;
		}
		
		if(k == KEY_DOWN) {
			do {
				if(entries[sel].row_next) {
					sel = entries[sel].row_next;				
					play_sample(biong, 200, 128, 1000, 0);
				}
			} while(entries[sel].can_change == false);
		}
		
		if(k == KEY_UP) {
									
			do {				
				for(int next = 0; next < num; next++) {
					if(entries[next].row_next == sel) {
						play_sample(biong, 200, 128, 1000, 0);
						sel = next;
						break;
					}
				}				
			} while(entries[sel].can_change == false);
		}
		
		if(k == KEY_RIGHT) {
			
			if(entries[sel].is_sliding) {
				if(entries[sel].val < 100) entries[sel].val++;
												
				netrate = 1 + entries[slide_net].val;
				musicvol = entries[slide_music].val;
				soundvol = entries[slide_sound].val;
				
				set_volume(255 * soundvol / 100, 255 * musicvol / 100);
				
				if(sel == slide_music) play_midi(music2, 0);
				else play_sample(boing, 200, 128, 1000, 0);
			}
			
			
			do {
				if(entries[sel].column_next) {
					sel = entries[sel].column_next;				
					play_sample(biong, 200, 128, 1000, 0);
				}
			} while(entries[sel].can_change == false);
		}
		
		if(k == KEY_LEFT) {
			
			if(entries[sel].is_sliding) {
				if(entries[sel].val > 0) entries[sel].val--;
												
				netrate = 1 + entries[slide_net].val;
				musicvol = entries[slide_music].val;
				soundvol = entries[slide_sound].val;
				
				set_volume(255 * soundvol / 100, 255 * musicvol / 100);				
				
				if(sel == slide_music) play_midi(music2, 0);
				else play_sample(boing, 200, 128, 1000, 0);
			}
			
			do {				
				for(int next = 0; next < num; next++) {
					if(entries[next].column_next == sel) {
						sel = next;
						play_sample(biong, 200, 128, 1000, 0);
						break;
					}
				}				
			} while(entries[sel].can_change == false);
		}
		
		if(k == KEY_ENTER || k == KEY_SPACE) {
			
			saveconfig();
			
			if(sel == go_fullscreen) {
				leave();
				if(windowed) {
					windowed = false;
					setgfx(0);
					entries[sel].name = "Windowed";
				} else {				
					windowed = true;
					setgfx(1);
					entries[sel].name = "Fullscreen";
				}
				enter();				
			}
			
			if(sel == AI_left || sel == AI_right) {
				entries[sel].is_active ^= 1;
			}
									
			if(sel == go) {
				game->netrate = 0;						
				game->time2send = 0.0;
				game->side = 0;				
				if(entries[AI_left].is_active)
					game->AI_left = true;
				else
					game->AI_left = false;
				if(entries[AI_right].is_active)
					game->AI_right = true;
				else
					game->AI_right = false;
				
				return 1;
			}
						
			if(sel == go_out) {				
				return 2;
			}	
			
			if(sel == go_story) {				
				return 3;
			}					
			
			#ifndef NO_LIBNET
			
			if(network && sel == go_internet) {
				char addr[1024];				
				sprintf(addr, "%s:7777", enter_address_str);
				int s = network->connect(addr);
				if(s == 0) {
					sendtime = 0;
					connecting = true;	
					acknowledging = false;				
					entries[go_internet].is_active = true;			
				} else {
					entries[go_internet].is_active = false;		
				}				
			}
			
			#endif
			
			if(entries[sel].is_key) {
				recording = 1;
				recordingflashtime = 0;
			}
			
		}
						
		if(entries[sel].can_edit) {
			if(isalnum(ch) || ispunct(ch)) entries[sel].addchar(ch);
					
			if(k == KEY_BACKSPACE) {
				entries[sel].addchar(8);
			}
		}				
		
	}
	
	time += d;
	
	return 0;
}

void Menu::redraw() {
	int n;
	for(n = 0; n < num; n++) {
		entries[n].restore();		
	}
	for(n = 0; n < num; n++) {
		if(n == sel) entries[n].is_sel = true;
		else entries[n].is_sel = false;
		
		entries[n].draw();
		entries[n].is_sel = false;
	}
}

void Menu::loadconfig() {
	set_config_file("battle.cfg");
	
	strcpy(enter_name_str,
		get_config_string("player", "name", "unknown"));	
	
	strcpy(enter_address_str,
		get_config_string("network", "address", "0.0.0.0"));
		
	netrate = get_config_int("network", "rate", 10);		
		
	windowed = (bool)get_config_int("settings", "windowed", 0);
	musicvol = get_config_int("settings", "musicvol", 50);
	soundvol = get_config_int("settings", "soundvol", 80);
	
	t[0] = get_config_int("controls", "keyleftleft", KEY_Z);	              
	t[1] = get_config_int("controls", "keyrightleft", KEY_X);              
	t[2] = get_config_int("controls", "keyleftright", KEY_0_PAD);	           
	t[3] = get_config_int("controls", "keyrightright", KEY_DEL_PAD);    
	
	for(int n = 0; n < 5; n++) {
		char str[256];
		sprintf(str, "place%d", n);
		strcpy(highscore_names[n], get_config_string("highscore", str, "unknown"));
		sprintf(str, "place%dpoints", n);
		highscores[n] = get_config_int("highscore", str, 0);		
	}        	
	
	set_volume(255 * soundvol / 100, 255 * musicvol / 100);					
}  

void Menu::saveconfig() {
	set_config_file("battle.cfg");
	
	set_config_string("player", "name", enter_name_str);	
	
	set_config_string("network", "address", enter_address_str);
	
	set_config_int("network", "rate", netrate);		
		
	set_config_int("settings", "windowed", windowed);	
	set_config_int("settings", "musicvol", musicvol);	
	set_config_int("settings", "soundvol", soundvol);	
	
	set_config_int("controls", "keyleftleft", entries[rec_left1].val);	
	set_config_int("controls", "keyrightleft", entries[rec_right1].val);   
	set_config_int("controls", "keyleftright", entries[rec_left2].val);	     
	set_config_int("controls", "keyrightright", entries[rec_right2].val);
	
	for(int n = 0; n < 5; n++) {
		char str[256];
		sprintf(str, "place%d", n);
		set_config_string("highscore", str, highscore_names[n]);
		sprintf(str, "place%dpoints", n);
		set_config_int("highscore", str, highscores[n]);
	}
}
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   