#include "qtv.h"

#define CENTERTIME 1.5

void Menu_Enter(cluster_t *cluster, viewer_t *viewer, int buttonnum)
{
	//build a possible message, even though it'll probably not be sent

	sv_t *sv;
	int i, min;

	switch(viewer->menunum)
	{
	default:
		if (buttonnum < 0)
			QW_SetMenu(viewer, MENU_MAIN);	//no other sort of back button...
		break;

	case MENU_MAIN:
		if (buttonnum < 0)
			viewer->menuop -= (MENU_MAIN_ITEMCOUNT + 1)/2;
		else if (buttonnum > 0)
			viewer->menuop += (MENU_MAIN_ITEMCOUNT + 1)/2;
		else if (buttonnum == 0)
		{
			switch(viewer->menuop)
			{
			case MENU_MAIN_STREAMS: //Streams
				QW_SetMenu(viewer, MENU_SERVERS);
				break;
			case MENU_MAIN_CLIENTLIST://Client List
				QW_SetMenu(viewer, MENU_CLIENTS);
				break;

			case MENU_MAIN_NEWSTREAM://New Stream
				QW_PrintfToViewer(viewer, "Not implemented yet\n");
				break;
			case MENU_MAIN_DEMOS://Demos
				Cluster_BuildAvailableDemoList(cluster);
				QW_SetMenu(viewer, MENU_DEMOS);
				break;

			case MENU_MAIN_SERVERBROWSER://Server Browser
				QW_PrintfToViewer(viewer, "Not implemented yet\n");
				break;
			case MENU_MAIN_ADMIN://Admin
				QW_SetMenu(viewer, MENU_ADMIN);
				break;

			case MENU_MAIN_PREVPROX://Previous Proxy
				if (viewer->isproxy)
				{
					QW_SetMenu(viewer, MENU_NONE);
					QW_StuffcmdToViewer(viewer, "say proxy:menu\n");
				}
				else
					QW_PrintfToViewer(viewer, "No client proxy detected\n");
				break;
			case MENU_MAIN_NEXTPROX://Next Proxy
				if (viewer->server && viewer->server->serverisproxy && viewer->server->controller == viewer)
				{
					viewer->server->proxyisselected = false;
					QW_SetMenu(viewer, MENU_NONE);
					SendClientCommand(viewer->server, "say .menu");
				}
				else
					QW_PrintfToViewer(viewer, "No server proxy detected\n");
				break;
			
			case MENU_MAIN_HELP://Help Menu
				QW_PrintfToViewer(viewer, "Not implemented yet\n");
				break;
			}
		}
		break;

	case MENU_CLIENTS:
		if (buttonnum >= 0)
		{
			viewer_t *v = cluster->viewers;
			for (i = 0; i < viewer->menuop && v; i++)
				v = v->next;
			if (!v)
				break;
			if (v == viewer)
			{
				if (viewer->commentator)
					QW_SetCommentator(cluster, viewer, NULL);
				else
					QW_PrintfToViewer(viewer, "Please stop touching yourself\n");
			}
			else
				QW_SetCommentator(cluster, viewer, v);
		}
		else
			QW_SetMenu(viewer, MENU_MAIN);
		break;

	case MENU_DEMOS:
		if (buttonnum >= 0)
			QW_StuffcmdToViewer(viewer, "say .demo %s\n", cluster->availdemos[viewer->menuop].name);
		else
			QW_SetMenu(viewer, MENU_MAIN);
		break;

	case MENU_ADMINSERVER:
		if (viewer->server)
		{
			i = 0;
			sv = viewer->server;
			if (i++ == viewer->menuop)
			{	//auto disconnect
				sv->autodisconnect = sv->autodisconnect?AD_NO:AD_WHENEMPTY;
			}
			if (i++ == viewer->menuop)
			{	//disconnect
				QTV_ShutdownStream(viewer->server);
			}
			if (i++ == viewer->menuop)
			{
				if (sv->controller == viewer)
					sv->controller = NULL;
				else
				{
					sv->controller = viewer;
					sv->controllersquencebias = viewer->netchan.outgoing_sequence - sv->netchan.outgoing_sequence;
				}
			}
			if (i++ == viewer->menuop)
			{	//back
				QW_SetMenu(viewer, MENU_ADMIN);
			}
			break;
		}
		//fallthrough
	case MENU_SERVERS:
		if (buttonnum < 0)
			QW_SetMenu(viewer, MENU_MAIN);
		else if (!cluster->servers)
		{
			QW_StuffcmdToViewer(viewer, "echo Please enter a server ip\nmessagemode\n");
			strcpy(viewer->expectcommand, "insecadddemo");
		}
		else
		{
			if (viewer->menuop < 0)
				viewer->menuop = 0;
			i = 0;
			min = viewer->menuop - 10;
			if (min < 0)
				min = 0;
			for (sv = cluster->servers; sv && i<min; sv = sv->next, i++)
			{//skip over the early connections.
			}
			min+=20;
			for (; sv && i < min; sv = sv->next, i++)
			{
				if (i == viewer->menuop)
				{
					/*if (sv->parsingconnectiondata || !sv->modellist[1].name[0])
					{
						QW_PrintfToViewer(viewer, "But that stream isn't connected\n");
					}
					else*/
					{
						QW_SetViewersServer(cluster, viewer, sv);
						QW_SetMenu(viewer, MENU_NONE);
						viewer->thinksitsconnected = false;
					}
					break;
				}
			}
		}
		break;
	case MENU_ADMIN:
		i = 0;
		if (i++ == viewer->menuop)
		{	//connection stuff
			QW_SetMenu(viewer, MENU_ADMINSERVER);
		}
		if (i++ == viewer->menuop)
		{	//qw port
			QW_StuffcmdToViewer(viewer, "echo You will need to reconnect\n");
			cluster->qwlistenportnum += (buttonnum<0)?-1:1;
		}
		if (i++ == viewer->menuop)
		{	//hostname
			strcpy(viewer->expectcommand, "hostname");
			QW_StuffcmdToViewer(viewer, "echo Please enter the new hostname\nmessagemode\n");
		}
		if (i++ == viewer->menuop)
		{	//master
			strcpy(viewer->expectcommand, "master");
			QW_StuffcmdToViewer(viewer, "echo Please enter the master dns or ip\necho Enter '.' for masterless mode\nmessagemode\n");
		}
		if (i++ == viewer->menuop)
		{	//password
			strcpy(viewer->expectcommand, "password");
			QW_StuffcmdToViewer(viewer, "echo Please enter the new rcon password\nmessagemode\n");
		}
		if (i++ == viewer->menuop)
		{	//add server
			strcpy(viewer->expectcommand, "messagemode");
			QW_StuffcmdToViewer(viewer, "echo Please enter the new qtv server dns or ip\naddserver\n");
		}
		if (i++ == viewer->menuop)
		{	//add demo
			strcpy(viewer->expectcommand, "adddemo");
			QW_StuffcmdToViewer(viewer, "echo Please enter the name of the demo to play\nmessagemode\n");
		}
		if (i++ == viewer->menuop)
		{	//choke
			cluster->chokeonnotupdated ^= 1;
		}
		if (i++ == viewer->menuop)
		{	//late forwarding
			cluster->lateforward ^= 1;
		}
		if (i++ == viewer->menuop)
		{	//no talking
			cluster->notalking ^= 1;
		}
		if (i++ == viewer->menuop)
		{	//nobsp
			cluster->nobsp ^= 1;
		}
		if (i++ == viewer->menuop)
		{	//back
			QW_SetMenu(viewer, MENU_NONE);
		}

		break;
	}
}

void WriteStringSelection(netmsg_t *b, qboolean selected, const char *str)
{
	if (selected)
	{
		WriteByte(b, 13);
		while(*str)
			WriteByte(b, 128|*str++);
	}
	else
	{
		WriteByte(b, ' ');
		while(*str)
			WriteByte(b, *str++);
	}
}

void Menu_Draw(cluster_t *cluster, viewer_t *viewer)
{
	char buffer[2048];
	char str[256];
	sv_t *sv;
	int i, min;
	unsigned char *s;

	netmsg_t m;

	if (viewer->backbuffered)
		return;

	if (viewer->menunum == MENU_FORWARDING)
		return;

	if (viewer->menuspamtime > cluster->curtime && viewer->menuspamtime < cluster->curtime + CENTERTIME*2000)
		return;
	viewer->menuspamtime = cluster->curtime + CENTERTIME*1000;

	InitNetMsg(&m, buffer, sizeof(buffer));

	WriteByte(&m, svc_centerprint);

	WriteString2(&m, "/PFTEQTV "QTV_VERSION_STRING"\n");
	WriteString2(&m, PROXYWEBSITE"\n");
	WriteString2(&m, "-------------\n");
	
	if (strcmp(cluster->hostname, DEFAULT_HOSTNAME))
		WriteString2(&m, cluster->hostname);

	switch(viewer->menunum)
	{
	default:
		WriteString2(&m, "bad menu");
		break;

	case MENU_MAIN:
		{
			WriteString2(&m, "\n\x1d\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1f\n");
			while (viewer->menuop < 0)
				viewer->menuop += MENU_MAIN_ITEMCOUNT;
			while (viewer->menuop >= MENU_MAIN_ITEMCOUNT)
				viewer->menuop -= MENU_MAIN_ITEMCOUNT;
			i = viewer->menuop;	

			WriteStringSelection(&m, i==MENU_MAIN_STREAMS,		"Streams          ");
			WriteStringSelection(&m, i==MENU_MAIN_CLIENTLIST,	"Client List      ");
			WriteByte(&m, '\n');
			WriteStringSelection(&m, i==MENU_MAIN_NEWSTREAM,	"New Stream       ");
			WriteStringSelection(&m, i==MENU_MAIN_DEMOS,		"Demos            ");
			WriteByte(&m, '\n');
			WriteStringSelection(&m, i==MENU_MAIN_SERVERBROWSER,"Server Browser   ");
			WriteStringSelection(&m, i==MENU_MAIN_ADMIN,		"Admin            ");
			WriteByte(&m, '\n');
			WriteStringSelection(&m, i==MENU_MAIN_PREVPROX,		"Previous Proxy   ");
			WriteStringSelection(&m, i==MENU_MAIN_NEXTPROX,		"Next Proxy       ");
			WriteByte(&m, '\n');
			WriteStringSelection(&m, i==MENU_MAIN_HELP,			"Help             ");
			WriteString2(&m,									"                  ");

			WriteString2(&m, "\n\x1d\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1f\n");
		}
		break;

	case MENU_CLIENTS:
		{
			int start;
			viewer_t *v;
			char *srv;
			int c;
			v = cluster->viewers;

			if (viewer->menuop < 0)
				viewer->menuop = 0;
			if (viewer->menuop > cluster->numviewers - 1)
				viewer->menuop = cluster->numviewers - 1;

			WriteString2(&m, "\nActive Clients\n\n");

			start = viewer->menuop & ~7;
			for (i = 0; i < start && v; i++)
				v = v->next;
			for (i = start; i < start+8 && v; i++, v = v->next)
			{
				for (c = strlen(v->name); c < 14; c++)
					WriteByte(&m, ' ');
				WriteStringSelection(&m, viewer->menuop == i, v->name);
				WriteString2(&m, ": ");
				if (v->server)
				{
					if (!v->server->sourcefile && !v->server->parsingconnectiondata)
						srv = v->server->map.hostname;
					else
						srv = v->server->server;
				}
				else
					srv = "None";
				for (c = 0; c < 20; c++)
				{
					if (*srv)
						WriteByte(&m, *srv++);
					else
						WriteByte(&m, ' ');
				}

				WriteByte(&m, '\n');
			}
			for (; i < start+8; i++)
				WriteByte(&m, '\n');
		}
		break;


	case MENU_DEMOS:
		{
			int start;

			WriteString2(&m, "\nAvailable Demos\n\n");

			if (cluster->availdemoscount == 0)
			{
				WriteString2(&m, "No demos are available");
				break;
			}
			
			if (viewer->menuop < 0)
				viewer->menuop = 0;
			if (viewer->menuop > cluster->availdemoscount-1)
				viewer->menuop = cluster->availdemoscount-1;

			start = viewer->menuop & ~7;
			for (i = start; i < start+8; i++)
			{
				char cleanname[128];
				char *us;
				strlcpy(cleanname, cluster->availdemos[i].name, sizeof(cleanname));
				for (us = cleanname; *us; us++)
					if (*us == '_')
						*us = ' ';
				WriteStringSelection(&m, i == viewer->menuop,	cleanname);
				WriteByte(&m, '\n');
			}
		}
		break;

	case MENU_ADMINSERVER:	//per-connection options
		if (viewer->server)
		{
			sv = viewer->server;
			WriteString2(&m, "\n\nConnection Admin\n");
			WriteString2(&m, sv->map.hostname);
			if (sv->sourcefile)
				WriteString2(&m, " (demo)");
			WriteString2(&m, "\n\n");

			if (viewer->menuop < 0)
				viewer->menuop = 0;

			i = 0;

			WriteString2(&m, " auto disconnect");
			WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : ");
			switch(viewer->server->autodisconnect)
			{
			default:
			case AD_NO:
				sprintf(str, "%-20s", "permanent connection");
				break;
			case AD_REVERSECONNECT:
				sprintf(str, "%-20s", "when server disconnects");
				break;
			case AD_WHENEMPTY:
				sprintf(str, "%-20s", "when inactive");
				break;
			case AD_STATUSPOLL:
				sprintf(str, "%-20s", "idle when empty");
				break;
			}
			WriteString2(&m, str);
			WriteString2(&m, "\n");

			WriteString2(&m, "force disconnect");
			WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : ");
			sprintf(str, "%-20s", "...");
			WriteString2(&m, str);
			WriteString2(&m, "\n");

			WriteString2(&m, "    take control");
			WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : ");
			sprintf(str, "%-20s", "...");
			WriteString2(&m, str);
			WriteString2(&m, "\n");

			WriteString2(&m, "            back");
			WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : ");
			sprintf(str, "%-20s", "...");
			WriteString2(&m, str);
			WriteString2(&m, "\n");

			if (viewer->menuop >= i)
				viewer->menuop = i - 1;

			WriteString2(&m, "\n");

			WriteString2(&m, "          status");
			WriteString2(&m, " : ");
			sprintf(str, "%-20s", viewer->server->status);
			WriteString2(&m, str);
			WriteString2(&m, "\n");

			break;
		}
		//fallthrough
	case MENU_SERVERS:	//connections list

		WriteString2(&m, "\n\nServers\n\n");

		if (!cluster->servers)
		{
			WriteString2(&m, "No active connections");
		}
		else
		{
			if (viewer->menuop < 0)
				viewer->menuop = 0;
			i = 0;
			min = viewer->menuop - 10;
			if (min < 0)
				min = 0;
			for (sv = cluster->servers; sv && i<min; sv = sv->next, i++)
			{//skip over the early connections.
			}
			min+=20;
			for (; sv && i < min; sv = sv->next, i++)
			{
				//Info_ValueForKey(sv->serverinfo, "hostname", str, sizeof(str));
				//if (sv->parsingconnectiondata || !sv->modellist[1].name[0])
				//	snprintf(str, sizeof(str), "%s", sv->server);
				snprintf(str, sizeof(str), "%s", *sv->map.hostname?sv->map.hostname:sv->server);

				if (i == viewer->menuop)
					for (s = (unsigned char *)str; *s; s++)
					{
						if ((unsigned)*s >= ' ')
							*s = 128 | (*s&~128);
					}
				WriteString2(&m, str);
				WriteString2(&m, "\n");
			}
		}
		break;

	case MENU_ADMIN:	//admin menu

		WriteString2(&m, "\n\nCluster Admin\n\n");

		if (viewer->menuop < 0)
			viewer->menuop = 0;
		i = 0;

		WriteString2(&m, " this connection");
		WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : ");
		sprintf(str, "%-20s", "...");
		WriteString2(&m, str);
		WriteString2(&m, "\n");

		WriteString2(&m, "            port");
		WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : ");
		sprintf(str, "%-20i", cluster->qwlistenportnum);
		WriteString2(&m, str);
		WriteString2(&m, "\n");

		WriteString2(&m, "        hostname");
		WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : ");
		sprintf(str, "%-20s", cluster->hostname);
		WriteString2(&m, str);
		WriteString2(&m, "\n");

		WriteString2(&m, "          master");
		WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : ");
		sprintf(str, "%-20s", cluster->master);
		WriteString2(&m, str);
		WriteString2(&m, "\n");

		WriteString2(&m, "        password");
		WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : ");
		sprintf(str, "%-20s", "...");
		WriteString2(&m, str);
		WriteString2(&m, "\n");

		WriteString2(&m, "      add server");
		WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : ");
		sprintf(str, "%-20s", "...");
		WriteString2(&m, str);
		WriteString2(&m, "\n");

		WriteString2(&m, "        add demo");
		WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : ");
		sprintf(str, "%-20s", "...");
		WriteString2(&m, str);
		WriteString2(&m, "\n");

		WriteString2(&m, "           choke");
		WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : ");
		sprintf(str, "%-20s", cluster->chokeonnotupdated?"yes":"no");
		WriteString2(&m, str);
		WriteString2(&m, "\n");

		WriteString2(&m, "delay forwarding");
		WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : ");
		sprintf(str, "%-20s", cluster->lateforward?"yes":"no");
		WriteString2(&m, str);
		WriteString2(&m, "\n");

		WriteString2(&m, "         talking");
		WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : ");
		sprintf(str, "%-20s", cluster->notalking?"no":"yes");
		WriteString2(&m, str);
		WriteString2(&m, "\n");

		WriteString2(&m, "           nobsp");
		WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : ");
		sprintf(str, "%-20s", cluster->nobsp?"yes":"no");
		WriteString2(&m, str);
		WriteString2(&m, "\n");

		WriteString2(&m, "            back");
		WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : ");
		sprintf(str, "%-20s", "...");
		WriteString2(&m, str);
		WriteString2(&m, "\n");

		if (viewer->menuop >= i)
			viewer->menuop = i - 1;
		break;
	}


	WriteByte(&m, 0);
	SendBufferToViewer(viewer, m.data, m.cursize, true);
}