#include "empire.h"
#include "logic.h"

void avoid_map_gaps();
int money_producing_buildings_owned(int plyr);

extern int SIDEBAR_WIDTH, BOTTOMBAR_HEIGHT;

void do_sidebar(int p, _unit *u, bool drawonly, bool reset)
{
	const short land = 1;
	const short air  = 2;
	const short sea  = 4;
	const int leftx = global.screen_width - SIDEBAR_WIDTH;
	const int bottomy = global.screen_height - BOTTOMBAR_HEIGHT;
	const int minimapy = 8;
	static bool first = true, spacefirst, spacesecond, stat_display;
	static _button endturn, option, unittab[2], unload[2], tele, standby, cap, cap2, deploy, talk, stats;
	static _unit *lastunit = NULL;
	static short tab = 0, spacedelay, spacedelay2 = 0, income_updatedelay = 0;
	static int income[4], currentplayer;
	bool cancap2 = false;
	int mm_mousex, mm_mousey, i, j, k, x, y;
	char c[40];
	DyBytes data;
	
	if (reset)
	{
		first = true;
		return;
	}
	
	if (first)
	{
		lastunit = NULL;
		tab = 0;
		unittab[0].init(leftx + 140, 170, 18, 80, "");
		unittab[1].init(leftx + 140, 270, 18, 80, "");
		endturn.init(leftx + 5, global.screen_height - 20, 73, 15, "End Turn");
		option.init(leftx + 82, global.screen_height - 20, 73, 15, "Options");
		standby.init(leftx + 5, 390, 150, 15, "Standby");
		cap.init(leftx + 5, 410, 150, 15, "Capture");
		tele.init(leftx + 5, 430, 150, 15, "Teleport");
		deploy.init(leftx + 5, 450, 150, 15, "Deploy");
		cap2.init(leftx + 5, 470, 150, 15, "Capture Unit");
		talk.init(leftx - 60, bottomy, 60, 24, "", 6);
		stats.init(leftx - statbmp.bmp(2)->Width(), bottomy, 60, 24, "", 6);
		first = false;
		spacefirst = false;
		spacesecond = false;
		stat_display = false;
		spacedelay = 0;  //spacedelay2 isn't reset here, on purpose
		income_updatedelay = 0;
		currentplayer = -1;
	}

	//draw the sidebar's background
	for (int y = 0; y < global.screen_height; y += statbmp.bmp(0)->Height())
		sidebarbmp.draw(p * 4, leftx, y);
	
	statbmp.draw(9 + tab, leftx, 0);  //draw whatever tab the sidebar is on
	
	sidebarbmp.draw((p * 4) + 1, leftx, global.screen_height - 30);  //draw a separator above the buttons
	
	//draw the bottom bar
	sidebarbmp.draw((p * 4) + 2, leftx - sidebarbmp.bmp(2)->Width(), bottomy);
	
	//draw the highlights on the bottom bar buttons
	if (global.netgame) statbmp.draw(11, leftx - statbmp.bmp(11)->Width(), bottomy);
	else statbmp.draw(12, leftx - statbmp.bmp(12)->Width(), bottomy);
	
	//extend the bottom bar if the horizontal screen resolution has been increased
	for (int x = leftx - sidebarbmp.bmp(2)->Width() - sidebarbmp.bmp(3)->Width(); x > -sidebarbmp.bmp(3)->Width(); x -= sidebarbmp.bmp(3)->Width())
		sidebarbmp.draw((p * 4) + 3, x, bottomy);
	
	{
		const int texty = (BOTTOMBAR_HEIGHT - normal.Height("Player")) / 2;
		
		sprintf(c, "Player %d", p + 1);
		buffer_textout_ex(normal, c, 15, bottomy + texty, WHITE);
		sprintf(c, "Funds: $%d", player[p].cash);
		buffer_textout_ex(normal, c, leftx - 350, bottomy + texty, WHITE);
		sprintf(c, "Income: $%d", income[p]);
		buffer_textout_right_ex(normal, c, leftx - 80, bottomy + texty, WHITE);
	}
	
	
	
	if (currentplayer != p)
	{
		currentplayer = p;
		i = 0;
		while (i < 4)
		{
			if (player[i].playing == 1) income[i] = money_producing_buildings_owned(i) * gameoptions.funding;
			else income[i] = 0;
			i++;
		}
		income_updatedelay = 40;
	}
	if (income_updatedelay <= 0)
	{
		i = 0;
		while (i < 4)
		{
			if (player[i].playing == 1) income[i] = money_producing_buildings_owned(i) * gameoptions.funding;
			else income[i] = 0;
			i++;
		}
		income_updatedelay = 40;
	} else income_updatedelay--;
	
	minimap.draw(false, leftx + 5, minimapy);
	
	if (u != 0)
	{
		if (lastunit != u)
		{
			lastunit = u;
			i = 0;
			while (i < 2)
			{
				if (u->load[i].loaded == 1)
				{
					sprintf(c, "Unload %s", unitstats[u->load[i].type].name.c_str());
					unload[i].init(leftx + 5, 450 + 20 * i, 150, 15, c);
				}
				else
				{
					unload[i].init(-10, -10, 1, 1, "");
				}
				i++;
			}
		}
		
		if (game->state == UNIT_SELECTED)
		{
			standby.check();
			if (standby.clicked())
			{
				if (global.netgame)
				{
					if (net.server)
					{
						data.clear();
						data.appendByte(NET_STANDBY);
						data.appendByte(game->pturn);
						data.appendByte(u->number);
						net.engine->broadcastTCP(data);
					}
					else
					{
						data.clear();
						data.appendByte(NET_CLIENT_STANDBY);
						data.appendByte(game->pturn);
						data.appendByte(u->number);
						net.engine->sendTCP(net.thread, data);
					}
				}
				u->ready = 0;  //usually the client should wait for a server response, but standby doesn't really do anything, so why bother?
				game->unitselected = NULL;
				game->state = NOTHING_HAPPENING;
			}
			
			if (unitstats[u->type].name == "Deployable Portal")
			{
				_tile *tile = worldmap.get_tile(u->tilex, u->tiley);
				if (tile->get_set() == 0)
				{  //if it's a land tile
					i = get_ltype(u->tilex, u->tiley);
					if ((i == 1) || (i == 6))
					{  //if it's grass or a road
						deploy.check();
						if (deploy.clicked())
						{
							if (!global.netgame)
							{
								u->exists = 0;
								u->health = 0;
								tile->set_unit(-1, -1);
								tile->change_type(6, 0);
								game->unitselected = NULL;
								game->state = NOTHING_HAPPENING;
								create_particle(u->tilex * MAP_TILE_SIZE + MAP_TILE_SIZE / 2, u->tiley * MAP_TILE_SIZE + MAP_TILE_SIZE / 2, P_SHOCKWAVE);
							}
							else
							{
								if (net.server)
								{
									u->exists = 0;
									u->health = 0;
									tile->set_unit(-1, -1);
									tile->change_type(6, 0);
									create_particle(u->tilex * MAP_TILE_SIZE + MAP_TILE_SIZE / 2, u->tiley * MAP_TILE_SIZE + MAP_TILE_SIZE / 2, P_SHOCKWAVE);
									
									game->unitselected = NULL;
									game->state = NOTHING_HAPPENING;
									
									data.clear();
									data.appendByte(NET_DEPLOYPORTAL);
									data.appendByte(game->pturn);
									data.appendByte(u->number);
									net.engine->broadcastTCP(data);
								}
								else
								{
									data.clear();
									data.appendByte(NET_CLIENT_DEPLOY);
									data.appendByte(u->number);
									net.engine->sendTCP(net.thread, data);
									
									game->unitselected = NULL;
									game->state = NET_WAITING_FOR_RESPONSE;
								}
							}
						}
					}
				}
			}
			
			if (unitstats[u->type].name == "Mechanic")
			{
				i = 0;
				while (i < 4)
				{
					x = u->tilex;
					y = u->tiley;
					if (i == 0) x++;
					if (i == 1) x--;
					if (i == 2) y++;
					if (i == 3) y--;
					
					if ((x > 0) && (x < worldmap.get_length()) && (y > 0) && (y < worldmap.get_height()))
					{
						j = any_unit_here(x, y);
						if ((j != -1) && (player[j / 100].team != player[game->pturn].team))
						{
							k = player[j / 100].unit[j % 100].type;
							if ((unitstats[k].movetype != M_INFANTRY) && (unitstats[k].movetype != M_MECH) && (unitstats[k].basetype != AIR))
							{
								cancap2 = true;
							}
						}
					}
					i++;
				}
				if (cancap2)
				{
					cap2.check();
					if (cap2.clicked())
					{
						game->state = MECHANIC_CAPPING;
					}
				}
			}
			
			i = 0;
			while (i < 2)
			{
				if (u->can_unload_unit(i))
				{
					unload[i].check();
					if (unload[i].clicked())
					{
						game->state = UNIT_UNLOADING;
						game->unload_slot = i;
					}
				}
				i++;
			}
			
			if ((worldmap.get_tile(u->tilex, u->tiley)->same_type(6, 0)) && (unitstats[u->type].basetype == LAND))
			{  //if the tile the unit's on is a teleport tile
				tele.check();
				if (tele.clicked())
				{
					game->state = UNIT_TELEPORTING;
				}
			}
		}
		
		i = 0;
		while (i < 2)
		{
			if (i != tab)
			{
				unittab[i].check();
				if (unittab[i].clicked())
				{
					tab = i;
				}
				i++;
			}
			i++;
		}
		if (tab == 0)
		{
			buffer_textout_centre_ex(med, unitstats[u->type].name, leftx + 69, 193, BLACK);
			i = 0;
			while (i < 3)
			{
				sprintf(c, "%d", u->attack[i]);
				buffer_textout_centre_ex(normal, c, leftx - 1 + 20 * (i + 1), 216, BLACK);
				buffer_textout_centre_ex(normal, c, leftx + 20 * (i + 1), 217, WHITE);
				sprintf(c, "%d", u->resist[i]);
				buffer_textout_centre_ex(normal, c, leftx + 79 + (20 * i), 216, BLACK);
				buffer_textout_centre_ex(normal, c, leftx + 80 + (20 * i), 217, WHITE);
				i++;
			}
			
			if (unitstats[u->type].canhit & land) statbmp.draw(3, leftx + 5, 255);
			if (unitstats[u->type].canhit & air) statbmp.draw(4, leftx + 5, 285);
			if (unitstats[u->type].canhit & sea) statbmp.draw(5, leftx + 5, 315);
			
			bigunits.draw(u->type, leftx + 30, 251);
		}
		else if (tab == 1)
		{
			buffer_rectfill(leftx + 11, 182, leftx + 127, 373, WHITE, 0.5);
			buffer_textout_ex(med, unit_name(u->type), leftx + 14, 184, BLACK);
			multiline_textout_ex(normal, unitstats[u->type].description, leftx + 14, 205, 112, BLACK);
		}
	}
	
	if (!drawonly && (mouse_b & 1))
	{  //center the map on the area of the minimap that was clicked
		mm_mousex = (mouse_x - (leftx + 5) - ((150 - minimap.bmp->Width()) / 2)) / 3;
		mm_mousey = (mouse_y - minimapy - ((150 - minimap.bmp->Height()) / 2)) / 3;
		
		if ((mm_mousex >= 0) && (mm_mousex < worldmap.get_length()))
		{
			if ((mm_mousey >= 0) && (mm_mousey < worldmap.get_height()))
			{
				int jumpx = mm_mousex - (XTILES / 2);
				int jumpy = mm_mousey - (YTILES / 2);
				
				const bool tooleft = (jumpx < 0);
				const bool tooright = (jumpx + XTILES > worldmap.get_length());
				const bool toohigh = (jumpy < 0);
				const bool toolow = (jumpy + YTILES > worldmap.get_height());
				
				if (XTILES >= worldmap.get_length()) //map is not as wide as the screen, center the map horizontally
					jumpx = (worldmap.get_length() - XTILES) / 2;
				else if (tooleft)
					jumpx = 0;
				else if (tooright)
					jumpx = worldmap.get_length() - XTILES + 1;  // + 1, because we want the final tile to be shown in full, not just a fraction of it
				
				if (YTILES >= worldmap.get_height())  //map is not as tall as the screen, center the map vertically
					jumpy = (worldmap.get_height() - YTILES) / 2;
				else if (toohigh)
					jumpy = 0;
				else if (toolow)
					jumpy = worldmap.get_height() - YTILES + 1;  // + 1, because we want the final tile to be shown in full, not just a fraction of it
				
				worldmap.camera.jump_to(jumpx, jumpy);
				
				avoid_map_gaps();  //make sure we don't leave gaps to the bottom or right, unless the map fits within the map space (where it's centered)
			}
		}
	}
	
	if (global.netgame)
	{
		talk.check();
		if (talk.clicked()) game->typingchat = true;
	}
	stats.check();
	if (stats.clicked())
	{
		stat_display = !stat_display;
	}
	if (stat_display)
	{
		const int stat_left = leftx - 395 - 195;
		const int stat_top = bottomy - 200;
		
		statbmp.draw(6 + player[p].number, stat_left, stat_top);
		statbmp.draw(6 + player[p].number, 65, 376);
		
		i = 0;
		while (i < 4)
		{
			if (player[i].everplaying == 1)
			{
				if (player[i].playing == 1)
				{
					if (global.netgame) buffer_textout_centre_ex(med, player[i].name, stat_left + 75, stat_top + 50 + (25 * i), WHITE);
					else
					{
						sprintf(c, "Player %d", i + 1);
						buffer_textout_centre_ex(med, c, stat_left + 75, stat_top + 40 + (25 * i), WHITE);
					}
					sprintf(c, "%d", player[i].cash);
					buffer_textout_centre_ex(med, c, 260, 431 + (25 * i), WHITE);
					sprintf(c, "%d", income[i]);
					buffer_textout_centre_ex(med, c, 380, 431 + (25 * i), WHITE);
					
					if (i == p)
					{
						buffer_rect(88, 432 + (25 * i), 190, 448 + (25 * i), WHITE);
					}
				}
				else
				{
					if (global.netgame) buffer_textout_centre_ex(med, player[i].name, 140, 431 + (25 * i), GREY);
					else
					{
						sprintf(c, "Player %d", i + 1);
						buffer_textout_centre_ex(med, c, 140, 431 + (25 * i), GREY);
					}
					sprintf(c, "%d", player[i].cash);
					buffer_textout_centre_ex(med, c, 260, 431 + (25 * i), GREY);
					sprintf(c, "%d", income[i]);
					buffer_textout_centre_ex(med, c, 380, 431 + (25 * i), WHITE);
				}
			}
			i++;
		}
	}
	
	if (player[p].controller == HUMAN)
	{
		if (drawonly)
			endturn.draw_disabled();
		else
			endturn.check();
	}
	
	if (drawonly)
		option.draw_disabled();
	else
		option.check();
	
	if (!drawonly)
	{
		if (player[p].controller == HUMAN)
		{
			if (endturn.clicked())
			{
				game->unitselected = NULL;
				game->state = NOTHING_HAPPENING;
				
				if ((!global.netgame) || (net.server))
				{  //only change the turn yourself if not a network client
					game->next_turn();
					first = true;
				}
				
				if (global.netgame)
				{
					if (net.server)
					{
						data.clear();
						data.appendByte(NET_NEWTURN);
						data.appendByte(game->pturn);
						net.engine->broadcastTCP(data);
					}
					else
					{
						data.clear();
						data.appendByte(NET_CLIENT_ENDTURN);
						net.engine->sendTCP(net.thread, data);
					}
				}
			}
			
			if (!spacefirst)  //all this makes the turn end if the space bar is double-tapped
			{
				if (spacedelay2 > 0)
				{
					spacedelay2--;
				}
				else
				{
					if (key[KEY_SPACE])
					{
						spacefirst = true;
					}
				}
			}
			else
			{
				if (!spacesecond)
				{
					if (!key[KEY_SPACE])
					{
						spacedelay = 35;
						spacesecond = true;
					}
				}
				else
				{
					if (spacedelay > 0)
					{
						spacedelay--;
						if (key[KEY_SPACE])
						{
							spacedelay2 = 35;
							
							if (!game->typingchat)
							{  //don't let spacebar end the turn when typing
								game->unitselected = NULL;
								game->state = NOTHING_HAPPENING;
								
								if ((!global.netgame) || (net.server))
								{  //only change the turn yourself if not a network client
									game->next_turn();
									first = true;
								}
								
								if (global.netgame)
								{
									if (net.server)
									{
										data.clear();
										data.appendByte(NET_NEWTURN);
										data.appendByte(game->pturn);
										net.engine->broadcastTCP(data);
									}
									else
									{
										data.clear();
										data.appendByte(NET_CLIENT_ENDTURN);
										net.engine->sendTCP(net.thread, data);
									}
								}
							}
						}
					}
					else
					{
						spacefirst = false;
						spacesecond = false;
					}
				}
			}
		}
		
		if ((option.clicked()) || (key[KEY_ESC]))
		{
			game->state = IN_GENERAL_MENU;
		}
	}
}
