#include <libraries/zbbs.h>
#include "protos.h"
#include "globals.c"

enum { GD_palette, GD_red, GD_green, GD_blue, GD_undo, GD_default };

VOID ParagonDoor(STRPTR prg)
{
	struct	MsgPort *myport,*replyport;
	BPTR		newlock, oldlock;
	ULONG		waitmask;
	BOOL		stop;
	struct	DoorMsg
	{
		struct	Message Door_Msg;
		short		command;
		short		data;
		char		string[80];
		short		carrier;
	} *doormsg;

	if(replyport = CreatePort("DoorControl1", 2))
	{
		if(oldlock = Open(&prg[4], MODE_OLDFILE)) /* wegen 'run ' */
		{
			newlock = ParentOfFH(oldlock);
			Close(oldlock);
			oldlock = CurrentDir(newlock);
		}

		if(!(ShowPrg("%ls 1", prg)))
		{
			Delay(50);
		  	myport = FindPort("DoorReply1");

			stop = FALSE;
			do
			{
				waitmask = Wait((1L << Win1->UserPort->mp_SigBit) |
									(1L << Win2->UserPort->mp_SigBit) |
									(1L << ReadPortCON->mp_SigBit) |
									(1L << ReadPortSER->mp_SigBit) |
									(1L << DoTime->tr_node.io_Message.mn_ReplyPort->mp_SigBit) |
									(1L << replyport->mp_SigBit));

		   	if(!myport)	myport = FindPort("DoorReply1");

				if(waitmask & (1L << DoTime->tr_node.io_Message.mn_ReplyPort->mp_SigBit))
				{
					if(CheckIO(DoTime))
					{
						QueueTimer();
						Clock();
					}
				}

				if(waitmask & (1L << replyport->mp_SigBit))
				{
					if(doormsg = GetMsg(replyport))
					{
						doormsg->carrier = !(CarrierSet() || login);

						switch(doormsg->command)
						{
							/* print string with break-check */
							case 1:
								strcpy(out_buffer, doormsg->string);
								Send();
								if(doormsg->data == 1)	Return();
								if(GetMsg(ReadPortCON))
								{
									if(console_in[0] == 3)	doormsg->data = -1;
									QueueConsole();
								}
								if(CheckIO(ReadSER))
								{
									if(serial_in[0] == 3)	doormsg->data = -1;
									QueueSerial();
								}
								break;

							/* print string */
							case 2:
								strcpy(out_buffer, doormsg->string);
								Send();
								break;

							/* print char */
							case 3:
							case 4:
							case 5:
								Char(doormsg->data);
								break;

							/* print string and input string */
							case 6:
							case 7:
								strcpy(out_buffer, doormsg->string);
								Send();
								In(doormsg->data, 3);
								Return();
								strcpy(doormsg->string, wait_buffer);
								break;

							/* print string and input char */
							case 8:
								strcpy(out_buffer, doormsg->string);
								Send();
								In(1, 1);
								doormsg->string[0] = wait_buffer[0];
								break;

							/* hangup but don't end */
							case 9:
								HangUp();
								connected = TRUE;
								break;

							/* send a file */
							case 10:
								ShowFile(doormsg->string);
								break;

							/* check for existence of a file/dir */
							case 11:
								doormsg->data = (Exists(doormsg->string) ? 1 : -1);
								break;

							/* start editor */
							case 12:
								doormsg->data = Editor(doormsg->string, "unknown", "Door Mail");
								break;

							/* get some data about user */
							case 13:
								switch(doormsg->data)
								{
									case 1:	doormsg->data = User.level / 17;	break;
									case 2:	doormsg->data = User.help_level;	break;
									case 3:	doormsg->data = 0;					break;
									case 4:	doormsg->data = User.calls;		break;
									case 5:	doormsg->data = User.calls;		break;
									case 6:	doormsg->data = (ansi > 1);
Printf("door fragte nach ansi\n");
	break;
									case 7:	doormsg->data = (User.time-User.time_used) / 60;	break;
									case 8:	doormsg->data = 80;					break;
									case 9:	doormsg->data = User.lines;		break;
								}
								break;

							/* get more data about user/system */
							case 14:
								switch(doormsg->data)
								{
									case 1:	strcpy(doormsg->string, User.alias);		break;
									case 2:	strcpy(doormsg->string, "*protected*");	break;
									case 3:	strcpy(doormsg->string, User.street);		break;
									case 4:	strcpy(doormsg->string, User.place);		break;
									case 5:	strcpy(doormsg->string, User.place);		break;
									case 6:	strcpy(doormsg->string, User.place);		break;
									case 7:	strcpy(doormsg->string, Config.door);		break;
									case 8:	strcpy(doormsg->string, Config.system);	break;
									case 9:	strcpy(doormsg->string, time);				break;
								}
								break;

							/* change userlevel (15) or data (16) like 14 */
							case 15:
							case 16:
								MyPrintf("sorry, the door wanted to change some data.\r\nI refused it's access...\r\n");
								break;

							/* get a random-value between 0 and data */
							case 17:
								doormsg->data = RangeRand(doormsg->data);
								break;

							/* make bbs believe that the carrier is still present */
							case 18:
								connected = TRUE;
								break;

							/* show an ansi file  ansi: .gr1   nonansi: .txt oder .gr-1 */
							case 19:
								ShowFile("%ls.%ls", doormsg->string, (ansi > 1 ? "gr1" : "txt"));
								break;

							/* door finished */
							case 20:
								stop = TRUE;
								break;

							/* change user's time */
							case 21:
								User.time_used -= doormsg->data * 60;
								break;
						}
						if(myport)
							PutMsg(myport, doormsg);
						else
							ReplyMsg(doormsg);
					}
				}

				if(waitmask & (1L << ReadPortCON->mp_SigBit))
				{
					if(CheckIO(ReadCON))
					{
						WaitIO(ReadCON);
						QueueConsole();
					}
				}

				if(waitmask & (1L << ReadPortSER->mp_SigBit))
				{
					if(CheckIO(ReadSER))
					{
						WaitIO(ReadSER);
						QueueSerial();
					}
				}

				CheckMenu();
			}	while(!stop);
		}
		else	SendError("ParagonDoors", "couldn't start this door");

		CurrentDir(oldlock);
		if(newlock)	UnLock(newlock);

		DeletePort(replyport);
	}
	else	SendError("Doors", "couldn't open DoorControl-Port");
}

VOID Doors()
{
	char file[256];
	struct List DoorList;
	struct Line *entry;
	BOOL stop;
	LONG i;

	Location("Doors");

	NewList(&DoorList);
	SPrintf(file, "%lsIndex", Config.door);
	GetLineList(file, &DoorList);

	if(!User.help_level)
	{
		ClrScr();
		ShowFile("%lsDoorMenu.txt", Config.text);
		if(!connected && !login)	goto exit;
	}

	stop = FALSE;
	do
	{
		color(NORMAL);
		if(User.help_level == 1)
		{
			color(WHITE);
			MyPrintf("(Commands: #, C, G , Z, M, ?)\r\n");
		}
		Ask("Doors : ", NULL, -1, TRUE);
		if(!connected && !login)	goto exit;

		if(atol(wait_buffer))
		{
			entry = GetHead(&DoorList);
			i = atol(wait_buffer) - 1;
			while(i--)
			{
				entry = GetSucc(entry);
				entry = GetSucc(entry);
			}
			i++;

			color(WHITE);
			if(entry && !i)
			{
				if(Access(atol(entry->node.ln_Pri), 0))
				{
					entry = GetSucc(entry);

					if(!instr(entry->text, "run "))	ShowPrg(entry->text);
					else	ParagonDoor(entry->text);
				}
			}
			else
			{
				MyPrintf("Door nicht gefunden\r\n");
			}
		}
		else
		{
			switch(toupper(wait_buffer[0]))
			{
				case 'C':
					ChatRequest();
					break;

				case 'G':
					Goodbye();
					if(!connected && !login)	stop = TRUE;
					break;

				case 'Z':
				case 'M':
					Location("Main Menu");
					stop = TRUE;
					break;

				case '\0':
				case '?':
					ClrScr();
					ShowFile("%lsDoorMenu.txt", Config.text);
					break;

				default:
					color(WHITE);
					MyPrintf("Ungueltige Eingabe. (? fuer Hilfe)\r\n");
					break;
			}
		}
	}	while((connected || login) && !stop);

exit:
	RemList(&DoorList);
}

LONG ShowPrg(STRPTR prg, ...)
{
	ULONG systemtags[] = {SYS_Output, 0, TAG_DONE};
	BPTR FH;
	char file[256];
	LONG err;

	SPrintf(file, "%lsBBS_Temp", Config.temp);
	if(!(FH = Open(file , MODE_NEWFILE)))
	{
		SendError("ShowPrg", "couldn't open temporary file");
		return(999999);
	}

	VSPrintf(file, prg, (STRPTR)(&prg + 1));
	Location(file);

	systemtags[1] = (ULONG)FH;
	err = System(file, (APTR)&systemtags[0]);
	Close(FH);

	ShowFile("%lsBBS_Temp", Config.temp);

	return(err);
}

VOID Palette()
{
	struct Window			*PaletteWnd;
	struct IntuiMessage	*message;
	struct Gadget			*glist, *Gadgets[6], *g;
	struct NewGadget		ng;
 	UWORD red, green, blue, colornumber, undocolor;
	ULONG	class, code;
	LONG i;
	BOOL stop;

	colornumber = 0;
	red	= (Status.colors[0] >> 8) & 0xF;
	green	= (Status.colors[0] >> 4) & 0xF;
	blue	= (Status.colors[0]) & 0xF;

	if(!(g = CreateContext(&glist)))	return;

	ng.ng_LeftEdge		= Scr->WBorLeft + 17;
	ng.ng_TopEdge		= Scr->WBorTop + Scr->RastPort.TxHeight + 1 + 6;
	ng.ng_Width			= 250;
	ng.ng_Height		= 38;
	ng.ng_GadgetText	= NULL;
	ng.ng_TextAttr		= &FontAttr;
	ng.ng_GadgetID		= GD_palette;
	ng.ng_Flags			= 0;
	ng.ng_VisualInfo	= VisualInfo;

	Gadgets[GD_palette] =
	g = CreateGadget(PALETTE_KIND, g, &ng,
			GTPA_Color,				colornumber,
			GTPA_Depth,				depth,
			GTPA_IndicatorWidth,	40,
			TAG_DONE);

	ng.ng_LeftEdge		= Scr->WBorLeft + 65;
	ng.ng_TopEdge		= Scr->WBorTop + Scr->RastPort.TxHeight + 1 + 48;
	ng.ng_Width			= 200;
	ng.ng_Height		= 9;
	ng.ng_GadgetText	= "Red  ";
	ng.ng_GadgetID		= GD_red;
	ng.ng_Flags			= NG_HIGHLABEL;

	Gadgets[GD_red] =
	g = CreateGadget(SLIDER_KIND, g, &ng,
			GTSL_Min,			0,
			GTSL_Max,			15,
			GTSL_Level,			red,
			GTSL_LevelFormat,	"%02ld",
			GTSL_MaxLevelLen,	2,
			GTSL_LevelPlace, PLACETEXT_RIGHT,
			TAG_DONE);

	ng.ng_TopEdge		+= 11;
	ng.ng_GadgetText	= "Green";
	ng.ng_GadgetID		= GD_green;

	Gadgets[GD_green] =
	g = CreateGadget(SLIDER_KIND, g, &ng,
			GTSL_Min,			0,
			GTSL_Max,			15,
			GTSL_Level,			green,
			GTSL_LevelFormat,	"%02ld",
			GTSL_MaxLevelLen,	2,
			GTSL_LevelPlace, PLACETEXT_RIGHT,
			TAG_DONE);

	ng.ng_TopEdge		+= 11;
	ng.ng_GadgetText	= "Blue ";
	ng.ng_GadgetID		= GD_blue;

	Gadgets[GD_blue] =
	g = CreateGadget(SLIDER_KIND, g, &ng,
			GTSL_Min,			0,
			GTSL_Max,			15,
			GTSL_Level,			blue,
			GTSL_LevelFormat,	"%02ld",
			GTSL_MaxLevelLen,	2,
			GTSL_LevelPlace, PLACETEXT_RIGHT,
			TAG_DONE);

	ng.ng_TopEdge		+= 13;
	ng.ng_Height		= 12;
	ng.ng_GadgetText	= "undo this color";
	ng.ng_GadgetID		= GD_undo;
	ng.ng_Flags			= PLACETEXT_IN;

	Gadgets[GD_undo] =
	g = CreateGadget(BUTTON_KIND, g, &ng, TAG_DONE);

	ng.ng_LeftEdge		= Scr->WBorLeft + 270;
	ng.ng_TopEdge		= Scr->WBorTop + Scr->RastPort.TxHeight + 1 + 6;
	ng.ng_Height		= 38;
	ng.ng_Width			= 20;
	ng.ng_GadgetText	= NULL;
	ng.ng_GadgetID		= GD_default;

	Gadgets[GD_default] =
	g = CreateGadget(BUTTON_KIND, g, &ng, TAG_DONE);

	if(!g)
	{
		FreeGadgets(glist);
		return;
	}

	if(!(PaletteWnd = OpenWindowTags(NULL,
		WA_Left,				63,
		WA_Top,				41,
		WA_Width,			310,
		WA_Height,			100 + Scr->WBorTop + Scr->RastPort.TxHeight + 1,
		WA_IDCMP,			PALETTEIDCMP | SLIDERIDCMP | BUTTONIDCMP | IDCMP_MOUSEMOVE |
								IDCMP_CLOSEWINDOW | IDCMP_RAWKEY,
		WA_Activate,		TRUE,
		WA_DragBar,			TRUE,
		WA_DepthGadget,	TRUE,
		WA_RMBTrap,			TRUE,
		WA_CloseGadget,	TRUE,
		WA_Gadgets,			glist,
		WA_Title,			"Z-BBS Palette",
		WA_CustomScreen,	Scr,
		TAG_DONE )))
	{
		FreeGadgets(glist);
		return;
	}

	GT_RefreshWindow(PaletteWnd, NULL);
	BlockWindow(Win1);
	BlockWindow(Win2);

	stop = FALSE;
	while(!stop)
	{
		WaitPort(PaletteWnd->UserPort);

		while(message = GT_GetIMsg(PaletteWnd->UserPort))
		{
			class	= message->Class;
			code	= message->Code;
			g		= (struct Gadget *)message->IAddress;
			GT_ReplyIMsg(message);

			if(class == IDCMP_MOUSEMOVE)
			{
				switch(g->GadgetID)
				{
					case GD_red:
						red = code;
						SetRGB4(&Scr->ViewPort, colornumber, red, green, blue);
						Status.colors[colornumber] = (red << 8) | (green << 4) | (blue);
					break;

					case GD_green:
						green = code;
						SetRGB4(&Scr->ViewPort, colornumber, red, green, blue);
						Status.colors[colornumber] = (red << 8) | (green << 4) | (blue);
					break;

					case GD_blue:
						blue = code;
						SetRGB4(&Scr->ViewPort, colornumber, red, green, blue);
						Status.colors[colornumber] = (red << 8) | (green << 4) | (blue);
					break;
				}
			}

			if(class == IDCMP_GADGETUP)
			{
				switch(g->GadgetID)
				{
					case GD_palette:
						colornumber = code;
						Status.colors[colornumber] = GetRGB4(Scr->ViewPort.ColorMap, colornumber);
						undocolor = Status.colors[colornumber];

						red	= (Status.colors[colornumber] >> 8) & 0xF;
						green	= (Status.colors[colornumber] >> 4) & 0xF;
						blue	= (Status.colors[colornumber]) & 0xF;

SETCOLORGADGETS:
						GT_SetGadgetAttrs(Gadgets[GD_red], PaletteWnd, NULL,
							GTSL_Level,	red,
							TAG_DONE);
						GT_SetGadgetAttrs(Gadgets[GD_green], PaletteWnd, NULL,
							GTSL_Level,	green,
							TAG_DONE);
						GT_SetGadgetAttrs(Gadgets[GD_blue], PaletteWnd, NULL,
							GTSL_Level,	blue,
							TAG_DONE);
					break;

					case GD_undo:
						Status.colors[colornumber] = undocolor;
						red	= (Status.colors[colornumber] >> 8) & 0xF;
						green	= (Status.colors[colornumber] >> 4) & 0xF;
						blue	= (Status.colors[colornumber]) & 0xF;
						SetRGB4(&Scr->ViewPort, colornumber, red, green, blue);
					goto SETCOLORGADGETS;

					case GD_default:
						Status.colors[0] = 0x000;
						Status.colors[1] = 0xf00;
						Status.colors[2] = 0x0f0;
						Status.colors[3] = 0xff0;
						Status.colors[4] = 0x00f;
						Status.colors[5] = 0xf0f;
						Status.colors[6] = 0x0ff;
						Status.colors[7] = 0xfff;
						Status.colors[8] = 0x000;
						Status.colors[9] = 0xb00;
						Status.colors[10] = 0x0b0;
						Status.colors[11] = 0xbb0;
						Status.colors[12] = 0x00b;
						Status.colors[13] = 0xb0b;
						Status.colors[14] = 0x0bb;
						Status.colors[15] = 0xbbb;
						i = 0;
						while(i < (1 << depth))
						{
							red	= (Status.colors[i] >> 8) & 0xF;
							green	= (Status.colors[i] >> 4) & 0xF;
							blue	= (Status.colors[i]) & 0xF;
							SetRGB4(&Scr->ViewPort, i, red, green, blue);
							i++;
						}
						red	= (Status.colors[colornumber] >> 8) & 0xF;
						green	= (Status.colors[colornumber] >> 4) & 0xF;
						blue	= (Status.colors[colornumber]) & 0xF;
					goto SETCOLORGADGETS;
				}
			}

			if(class == IDCMP_RAWKEY)
			{
				/* enter oder return.. */
				if(code == 0x0043 || code == 0x0044)	stop = TRUE;
			}

			if(class == IDCMP_CLOSEWINDOW)	stop = TRUE;
		}
	}


	if(PaletteWnd)		CloseWindow(PaletteWnd);
	if(glist)	FreeGadgets(glist);

	ReleaseWindow(Win1);
	ReleaseWindow(Win2);
}
