#ifndef NETLOBBY_H_
#define NETLOBBY_H_

#include "empire.h"

extern int mapcolor(int set, int num, int owner, bool defaultcolors);
void get_lobby_data(DyBytes &indata);

class map_preview
{
	map_preview &operator=(const map_preview &p);
	
public:
	int8_t data_set[50*50];
	int8_t data_num[50*50];  //storing the tile set&number data separately, to make memcpy'ing easier
	
	unsigned int l, h;
	ol::Bitmap *bmp;
	
	map_preview() :
		l (0),
		h (0),
		bmp (0)
	{}
	
	map_preview(const map_preview &p) :
		l (p.l),
		h (p.h),
		bmp (0)
	{
		if (p.bmp != 0)
		{
			empdebug("Error: I was too lazy to write a full constructor for map_preview(const map_preview &), and this really shouldn't be used!");
			return;
		}
	}
	
	~map_preview()
	{
		if (bmp != 0)
		{
			bmp->Destroy();
			bmp = 0;
		}
	}
	
	void draw(int x, int y)
	{
		if (bmp != 0)
		{
			buffer_draw_sprite(bmp, x, y);
		}
	}
	
	void create_preview()
	{
		unsigned int x, y;
		int s, n;
		
		if (bmp != 0)
		{
			bmp->Destroy();
		}
		bmp = new ol::Bitmap(l * 3, h * 3);
		if (bmp == 0)
		{
			empdebug("Couldn't create minimap bitmap!");
			return;
		}
		
		ol::Canvas::SetTo(*bmp);
		ol::Canvas::SetPixelWriteMode(ol::COLOR_AND_ALPHA);

		ol::Rect(0, 0, l * 3, h * 3).Draw(ol::Rgba(BLACK, 255));

		y = 0;
		while (y < h)
		{
			x = 0;
			while (x < l)
			{
				s = data_set[x + (y * l)];
				n = data_num[x + (y * l)];
				
				ol::Rect(float(x * 3), float(y * 3), 3.0, 3.0).Draw(ol::Rgba(mapcolor(s, n, -1, true), 255));

				if (s == 4)  //buildings
				{
					if (n > 0)  //if a normal building
					{
						ol::Rect(float(x * 3), float(y * 3), 2.0, 2.0).DrawOutline(ol::Rgba(GREY, 255));
					}
					else  //if an HQ
					{
						ol::Rect(float(x * 3), float(y * 3), 2.0, 2.0).DrawOutline(ol::Rgba(WHITE, 255));
					}
				}
				if (s == 6)  //special tiles
				{
					if (n == 0) //teleporter
					{
						ol::Point(float(x * 3 + 1), float(y * 3)).Draw(ol::Rgba(WHITE, 255));
						ol::Point(float(x * 3), float(y * 3 + 2)).Draw(ol::Rgba(WHITE, 255));
						ol::Point(float(x * 3 + 2), float(y * 3 + 3)).Draw(ol::Rgba(WHITE, 255));
					}
				}

				x++;
			}
			y++;
		}

		ol::Canvas::Refresh();
		ol::Canvas::SetTo(ol::SCREEN_BACKBUF);
	}
	
	void create_preview(unsigned int _l, unsigned int _h, int8_t *_setdata, int8_t *_numdata)
	{
		l = _l;
		h = _h;
		memcpy(data_set, _setdata, l * h);
		memcpy(data_num, _numdata, l * h);
		create_preview();
	}
	
	void create_preview(unsigned int _l, unsigned int _h, int8_t *_data)
	{
		l = _l;
		h = _h;
		memcpy(data_set, _data, l * h);
		memcpy(data_num, _data + (l * h) + 1, l * h);
		create_preview();
	}
};

class listedgame
{
	uint8_t players, maxplayers, mapw, maph;
	std::string name, mapname, address;  //lengths of these can't go over 255, or everything breaks
	map_preview preview;
public:
	const static int w = 180, h = 168;
	
	listedgame() :
		players (0),
		maxplayers (0),
		mapw (0),
		maph (0),
		name (""),
		mapname (""),
		address (""),
		preview (map_preview())
	{}
	
	listedgame(int plyrs, int maxplyrs, string gamename, string gamemap, int newmapw, int newmaph, int8_t *mapdata) :
		players (plyrs),
		maxplayers (maxplyrs),
		mapw (newmapw),
		maph (newmaph),
		name (gamename),
		mapname (gamemap),
		address ("127.0.0.1"),
		preview (map_preview())
	{
		update(plyrs, maxplyrs, gamename, gamemap, mapw, maph, mapdata);
	}
	
	string get_address()
	{
		return address;
	}
	
	string get_name()
	{
		return name;
	}
	
	void update(unsigned int newplayers, unsigned int newmaxplayers, string newname, string newmapname, unsigned int newmapw, unsigned int newmaph, int8_t *data_set, int8_t *data_num)
	{
		players = newplayers;
		maxplayers = newmaxplayers;
		name = newname;
		mapname = newmapname;
		mapw = newmapw;
		maph = newmaph;
		address = "127.0.0.1";
		preview.create_preview(mapw, maph, data_set, data_num);
	}
	
	void update(unsigned int newplayers, unsigned int newmaxplayers, string newname, string newmapname, unsigned int newmapw, unsigned int newmaph, int8_t *mapdata)
	{
		players = newplayers;
		maxplayers = newmaxplayers;
		name = newname;
		mapname = newmapname;
		mapw = newmapw;
		maph = newmaph;
		address = "127.0.0.1";
		preview.create_preview(mapw, maph, mapdata);
	}
	
	void append_to(DyBytes &data)
	{
		unsigned int i;
		
		data.appendVariable(players);
		data.appendVariable(maxplayers);
		data.appendVariable(mapw);
		data.appendVariable(maph);
		
		for (i = 0; i < mapw * maph; i++)
			data.appendVariable(preview.data_set[i]);
		
		for (i = 0; i < mapw * maph; i++)
			data.appendVariable(preview.data_num[i]);
		
		data.appendByte(name.length());
		data.appendString(name);
		data.appendByte(mapname.length());
		data.appendString(mapname);
		data.appendByte(address.length());
		data.appendString(address);
	}
	
	bool get_from(DyBytes &data)
	{
		unsigned int i;
		unsigned char l;
		DyBytes subdata;
		
		if (data.size() < 4)
			return false;
		data.extractVariable(0, players);
		data.extractVariable(1, maxplayers);
		data.extractVariable(2, mapw);
		data.extractVariable(3, maph);
		data.removeFront(4);
		
		if ((maxplayers > 4) || (players > 4))
			return false;
		
		if ((mapw == 0) || (mapw > 50))
			return false;
		
		if ((maph == 0) || (maph > 50))
			return false;
		
		if (data.size() < ((unsigned int)mapw) * ((unsigned int)maph) * 2)
			return false;
		
		for (i = 0; i < mapw * maph; i++)
			data.extractVariable(i, preview.data_set[i]);
		data.removeFront(mapw * maph);
		
		for (i = 0; i < mapw * maph; i++)
			data.extractVariable(i, preview.data_num[i]);
		data.removeFront(mapw * maph);
		
		//-----
		
		if (data.size() == 0)
			return false;
		
		l = data.getByte(0);
		data.removeFront(1);
		
		if (data.size() < l)
			return false;
		
		for (i = 0; i < l; i++)
		{
			subdata.appendByte(data.getByte(i));
		}
		data.removeFront(l);
		name = subdata.getAsString();
		
		//-----
		
		if (data.size() == 0)
			return false;
		
		subdata.clear();
		l = data.getByte(0);
		data.removeFront(1);
		
		if (data.size() < l)
			return false;
		
		for (i = 0; i < l; i++)
		{
			subdata.appendByte(data.getByte(i));
		}
		data.removeFront(l);
		mapname = subdata.getAsString();
		
		//-----
		
		if (data.size() == 0)
			return false;
		
		subdata.clear();
		l = data.getByte(0);
		data.removeFront(1);
		
		if (data.size() < l)
			return false;
		
		for (i = 0; i < l; i++)
		{
			subdata.appendByte(data.getByte(i));
		}
		data.removeFront(l);
		address = subdata.getAsString();
		
		//-----
		
		preview.l = mapw;
		preview.h = maph;
		preview.create_preview();
		return true;
	}
	
	void draw(int x, int y)
	{
		int mx = mouse_x;
		int my = mouse_y;
		bool mouseover = false;
		
		if ((mx >= x) && (mx <= x + w) && (my >= y) && (my <= y + h))
			mouseover = true;
		
		buffer_rect(x, y, x + w, y + h, BLACK);
		buffer_rectfill(x + 1, y + 1, x + w - 1, y + h - 1, WHITE, 0.75);
		
		preview.draw(x + 15 + ((50 - preview.l) * 3) / 2, y + 9 + ((50 - preview.h) * 3)  / 2);
		
		buffer_rectfill(x, y, x + w, y + 18, WHITE, 0.8);
		buffer_rectfill(x, y + h - 18, x + w, y + h, WHITE, 0.8);
		buffer_textout_centre_ex(normal, name, x + (w / 2), y + 3, BLACK);
		buffer_textout_centre_ex(normal, mapname, x + (w / 2), y + h - 15, BLACK);
		
		if (mouseover)
		{
			char c[50];
			sprintf(c, "Players: %d / %d", players, maxplayers);
			
			buffer_rectrounded(x + 15, y + (h / 2) - 10, x + w - 15, y + (h / 2) + 10, BLACK, 0.75);
			buffer_textout_centre_ex(normal, c, x + (w / 2), y + (h / 2) - 6, WHITE);
		}
	}
};

extern string MOTD;
extern vector<listedgame *> gamelist;

#endif /*NETLOBBY_H_*/
