/*
**	TransferPanel.c
**
**	File transfer control panel support routines
**
**	Copyright © 1990-1993 by Olaf `Olsen' Barthel & MXM
**		All Rights Reserved
*/

#include "termGlobal.h"

STATIC struct Gadget	*GadgetList;
STATIC BYTE		 LastStatus = -1;
STATIC LONG		 TransferInfoCount = 0;

STATIC struct IBox	 TransferBox = { -1, -1, -1, -1 };

STATIC struct Gadget *
CreateAllGadgets(struct TextBox **BoxArray,struct TextBox **BoxList,struct Gadget **GadgetArray,struct Gadget **GadgetList)
{
	struct Gadget		*Gadget;
	struct NewGadget	 NewGadget;
	UWORD			 Counter,
				 BoxCounter;
	struct TextBox		*Box;
	LONG			 TotalLines = 10;

	FOREVER
	{
		SZ_SizeSetup(Window -> WScreen,&UserFont,TRUE);

		*GadgetList	= NULL;
		*BoxList	= NULL;

		Counter		= 0;
		BoxCounter	= 0;

		memset(&NewGadget,0,sizeof(struct NewGadget));

		if(Gadget = CreateContext(GadgetList))
		{
			LONG Width,Left;

			SZ_AddLeftOffset(SZ_LeftOffsetDelta(MSG_TRANSFERPANEL_PROTOCOL_TXT,MSG_TRANSFERPANEL_ELAPSED_TIME_TXT));

			Width = SZ_BoxWidth(16) + INTERWIDTH + SZ_LeftOffsetDelta(MSG_TRANSFERPANEL_CHARACTERS_PER_SECOND_TXT,MSG_TRANSFERPANEL_NUMBER_OF_TIMEOUTS_TXT) + SZ_BoxWidth(16);

			if(Width > SZ_BoxWidth(50))
				SZ_SetWidth(Width);
			else
				SZ_SetWidth(SZ_BoxWidth(50));

			BoxArray[BoxCounter++] = Box = SZ_CreateTextBox(BoxList,
				SZ_Lines,	1,
				SZ_AutoWidth,	TRUE,
			TAG_DONE);

			SZ_SetBoxTitles(Box,LocaleString(MSG_TRANSFERPANEL_PROTOCOL_TXT),NULL);

			NewGadget . ng_GadgetText	= LocaleString(MSG_TRANSFERPANEL_INFORMATION_GAD);
			NewGadget . ng_GadgetID		= Counter;
			NewGadget . ng_Flags		= PLACETEXT_LEFT;

			GadgetArray[Counter++] = Gadget = CreateGadget(LISTVIEW_KIND,Gadget,&NewGadget,
				SZ_Adjust,	TRUE,
				SZ_AutoWidth,	TRUE,
				SZ_Lines,	TotalLines,

				GTLV_ReadOnly,	TRUE,
			TAG_DONE);

			BoxArray[BoxCounter++] = Box = SZ_CreateTextBox(BoxList,
				SZ_Lines,	3,
				SZ_AutoWidth,	TRUE,
			TAG_DONE);

			SZ_SetBoxTitles(Box,LocaleString(MSG_TRANSFERPANEL_FILE_TXT),LocaleString(MSG_TRANSFERPANEL_NEXT_FILE_TXT),LocaleString(MSG_TRANSFERPANEL_SPACE_LEFT_TXT),NULL);

			BoxArray[BoxCounter++] = Box = SZ_CreateTextBox(BoxList,
				SZ_Lines,	6,
				SZ_Chars,	16,
				SZ_SaveY,	TRUE,
			TAG_DONE);

			SZ_SetBoxTitles(Box,LocaleString(MSG_TRANSFERPANEL_FILE_SIZE_TXT),LocaleString(MSG_TRANSFERPANEL_FILE_SIZE_TRANSFERRED_TXT),LocaleString(MSG_TRANSFERPANEL_TOTAL_SIZE_TXT),LocaleString(MSG_TRANSFERPANEL_TOTAL_SIZE_TRANSFERRED_TXT),LocaleString(MSG_TRANSFERPANEL_FILES_TRANSFERRED_TXT),LocaleString(MSG_TRANSFERPANEL_BLOCKS_TRANSFERRED_TXT),NULL);

			Left = SZ_GetLeftEdge();

			BoxArray[BoxCounter++] = Box = SZ_CreateTextBox(BoxList,
				SZ_Lines,	6,
				SZ_Chars,	16,
				SZ_AlignRight,	TRUE,
			TAG_DONE);

			SZ_SetBoxTitles(Box,LocaleString(MSG_TRANSFERPANEL_CHARACTERS_PER_SECOND_TXT),LocaleString(MSG_TRANSFERPANEL_CHARACTER_DELAY_TXT),LocaleString(MSG_TRANSFERPANEL_PACKET_DELAY_TXT),LocaleString(MSG_TRANSFERPANEL_PACKET_TYPE_TXT),LocaleString(MSG_TRANSFERPANEL_BLOCK_CHECK_TYPE_TXT),LocaleString(MSG_TRANSFERPANEL_BLOCK_SIZE_TXT),NULL);

			BoxArray[BoxCounter++] = Box = SZ_CreateTextBox(BoxList,
				SZ_Lines,	2,
				SZ_Chars,	16,
				SZ_UseLeft,	Left,
				SZ_AlignBottom,	TRUE,
				SZ_SaveY,	TRUE,
			TAG_DONE);

			SZ_SetBoxTitles(Box,LocaleString(MSG_TRANSFERPANEL_ESTIMATED_TIME_TXT),LocaleString(MSG_TRANSFERPANEL_ELAPSED_TIME_TXT),NULL);

			BoxArray[BoxCounter] = Box = SZ_CreateTextBox(BoxList,
				SZ_Lines,	2,
				SZ_Chars,	16,
				SZ_AlignRight,	TRUE,
			TAG_DONE);

			SZ_SetBoxTitles(Box,LocaleString(MSG_TRANSFERPANEL_NUMBER_OF_ERRORS_TXT),LocaleString(MSG_TRANSFERPANEL_NUMBER_OF_TIMEOUTS_TXT),NULL);

			SZ_SetWidth((SZ_GetWindowWidth() - 3 * InterWidth) / 2);

			NewGadget . ng_GadgetText	= LocaleString(MSG_TRANSFERPANEL_DATA_TRANSFERRED_GAD);
			NewGadget . ng_GadgetID		= Counter;
			NewGadget . ng_Flags		= PLACETEXT_ABOVE;

			GadgetArray[Counter++] = Gadget = CreateGadget(TEXT_KIND,Gadget,&NewGadget,
				SZ_Adjust,	TRUE,
				SZ_AutoWidth,	TRUE,
				SZ_AlignLeft,	TRUE,
				SZ_AlignBottom,	TRUE,

				GTTX_Border,	TRUE,
			TAG_DONE);

			NewGadget . ng_GadgetText	= LocaleString(MSG_TRANSFERPANEL_TIME_TO_GO_GAD);
			NewGadget . ng_GadgetID		= Counter;

			GadgetArray[Counter++] = Gadget = CreateGadget(TEXT_KIND,Gadget,&NewGadget,
				SZ_Adjust,	TRUE,
				SZ_AutoWidth,	TRUE,
				SZ_AlignRight,	TRUE,
				SZ_UseTop,	SZ_GetTopEdge(),

				GTTX_Border,	TRUE,
			TAG_DONE);

			NewGadget . ng_GadgetText	= LocaleString(MSG_TRANSFERPANEL_ABORT_ENTIRE_TRANSFER_GAD);
			NewGadget . ng_GadgetID		= Counter;
			NewGadget . ng_Flags		= 0;

			GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
				SZ_AlignExtra,	TRUE,
				SZ_Adjust,	TRUE,
				SZ_AutoWidth,	TRUE,
				SZ_AlignLeft,	TRUE,
				SZ_AlignBottom,	TRUE,
			TAG_DONE);

			NewGadget . ng_GadgetText	= LocaleString(MSG_TRANSFERPANEL_SKIP_CURRENT_FILE_GAD);
			NewGadget . ng_GadgetID		= Counter;

			GadgetArray[Counter] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
				SZ_Adjust,	TRUE,
				SZ_AutoWidth,	TRUE,
				SZ_AlignRight,	TRUE,
			TAG_DONE);
		}
		else
			return(Gadget);

		if(SZ_GetWindowHeight() > Window -> Height - (Window -> BorderTop + Window -> BorderBottom) && TotalLines > 2)
		{
			TotalLines--;

			if(*GadgetList)
			{
				FreeGadgets(*GadgetList);

				*GadgetList = NULL;
			}

			if(*BoxList)
			{
				SZ_FreeBoxes(*BoxList);

				*BoxList = NULL;
			}

			SZ_SizeSetup(Window -> WScreen,&UserFont,TRUE);
		}
		else
			return(Gadget);
	}
}

	/* GhostStats(struct Gadget *Gadget):
	 *
	 *	Ghost the percentage bars.
	 */

VOID
GhostStats(struct Gadget *Gadget)
{
	struct RastPort	*RPort = TransferWindow -> RPort;
	UBYTE		 FgPen = ReadAPen(RPort);

	SetAPen(RPort,DrawInfo -> dri_Pens[SHADOWPEN]);

	SetAfPt(RPort,(UWORD *)&Crosshatch,1);

	RectFill(RPort,Gadget -> LeftEdge + 2,Gadget -> TopEdge + 1,Gadget -> LeftEdge + Gadget -> Width - 3,Gadget -> TopEdge + Gadget -> Height - 2);

	SetAPen(RPort,FgPen);

	SetAfPt(RPort,NULL,0);
}

	/* ShowStats(struct Gadget *Gadget,LONG Value,LONG Max):
	 *
	 *	Show the percentage bars.
	 */

VOID
ShowStats(struct Gadget *Gadget,LONG Value,LONG Max)
{
	if(TransferWindow)
	{
		struct RastPort	*RPort = TransferWindow -> RPort;
		LONG		 MaxWidth = Gadget -> Width - 4,Width;

		if(Max < 1)
			Max = 0;

		if(Value > Max)
			Value = Max;

		if((Width = (MaxWidth * Value) / Max) > 0)
		{
			UBYTE FgPen = ReadAPen(RPort);

			if(Width != MaxWidth)
			{
				SetAPen(RPort,0);

				RectFill(RPort,Gadget -> LeftEdge + 2 + Width - 1,Gadget -> TopEdge + 1,Gadget -> LeftEdge + Gadget -> Width - 3,Gadget -> TopEdge + Gadget -> Height - 2);
			}

			SetAPen(RPort,DrawInfo -> dri_Pens[FILLPEN]);

			RectFill(RPort,Gadget -> LeftEdge + 2,Gadget -> TopEdge + 1,Gadget -> LeftEdge + Width + 1,Gadget -> TopEdge + Gadget -> Height - 2);

			SetAPen(RPort,FgPen);
		}
		else
		{
			UBYTE FgPen = ReadAPen(RPort);

			SetAPen(RPort,0);

			RectFill(RPort,Gadget -> LeftEdge + 2,Gadget -> TopEdge + 1,Gadget -> LeftEdge + Gadget -> Width - 3,Gadget -> TopEdge + Gadget -> Height - 2);

			SetAPen(RPort,FgPen);
		}
	}
}

	/* ShowString(struct Gadget *Gadget,STRPTR String,...):
	 *
	 *	Display percentage information.
	 */

VOID __stdargs
ShowString(struct Gadget *Gadget,STRPTR String,...)
{
	if(TransferWindow)
	{
		va_list		 VarArgs;
		WORD		 Len;
		UWORD		 Width;
		struct RastPort	*RPort;
		LONG		 FgPen,DrawMode;
		struct TextFont	*Font;

		RPort		= TransferWindow -> RPort;
		FgPen		= ReadAPen(RPort),
		DrawMode	= ReadDrMd(RPort);
		Font		= RPort -> Font;

		if(Font != UserTextFont);
			SetFont(RPort,UserTextFont);

		va_start(VarArgs,String);
		VSPrintf(SharedBuffer,String,VarArgs);
		va_end(VarArgs);

		Len	= strlen(SharedBuffer);
		Width	= TextLength(RPort,SharedBuffer,Len);

		Move(RPort,Gadget -> LeftEdge + 2 + (Gadget -> Width - 4 - Width) / 2,Gadget -> TopEdge + 1 + (Gadget -> Height - 2 - UserFontHeight) / 2 + UserFontBase);

		SetAPen(RPort,DrawInfo -> dri_Pens[HIGHLIGHTTEXTPEN]);

		if(DrawInfo -> dri_Pens[FILLPEN] == DrawInfo -> dri_Pens[HIGHLIGHTTEXTPEN])
			SetDrMd(RPort,JAM1 | COMPLEMENT);
		else
			SetDrMd(RPort,JAM1);

		Text(RPort,SharedBuffer,Len);

		SetAPen(RPort,FgPen);
		SetDrMd(RPort,DrawMode);

		if(Font != UserTextFont);
			SetFont(RPort,Font);
	}
}

	/* AddTransferInfo(STRPTR Message,...):
	 *
	 *	Add another entry to the transfer information list.
	 */

VOID __stdargs
AddTransferInfo(STRPTR Message,...)
{
	STATIC UBYTE TempBuffer[256];

	struct Node	*Node;
	va_list		 VarArgs;

	va_start(VarArgs,Message);
	VSPrintf(TempBuffer,Message,VarArgs);
	va_end(VarArgs);

	if(Node = AllocVec(sizeof(struct Node) + strlen(TempBuffer) + 1,MEMF_ANY | MEMF_CLEAR))
	{
		Node -> ln_Name = (STRPTR)(Node + 1);

		strcpy(Node -> ln_Name,TempBuffer);

		GT_SetGadgetAttrs(TransferGadgetArray[GAD_TRANSFER_INFORMATION_LIST],TransferWindow,NULL,
			GTLV_Labels,		~0,
		TAG_DONE);

		AddTail(&TransferInfoList,Node);

		GT_SetGadgetAttrs(TransferGadgetArray[GAD_TRANSFER_INFORMATION_LIST],TransferWindow,NULL,
			GTLV_Labels,		&TransferInfoList,
			GTLV_Top,		TransferInfoCount,
			GTLV_MakeVisible,	TransferInfoCount,
		TAG_DONE);

		TransferInfoCount++;
	}
}

	/* RefreshTransferWindow():
	 *
	 *	Refresh the entire transfer window.
	 */

VOID
RefreshTransferWindow()
{
	SZ_DrawBoxes(TransferWindow -> RPort,TransferBoxList);

	GT_RefreshWindow(TransferWindow,NULL);

	GhostStats(TransferGadgetArray[GAD_TRANSFER_PERCENT]);
	GhostStats(TransferGadgetArray[GAD_TRANSFER_TIME]);
}

	/* TransferPanel(STRPTR Title):
	 *
	 *	Open the transfer window.
	 */

BYTE
TransferPanel(STRPTR Title)
{
	if(TransferWindow)
		return(TRUE);
	else
	{
		TransferFailed = TransferAborted = FALSE;

		if(Status != STATUS_DOWNLOAD && Status != STATUS_UPLOAD)
		{
			LastStatus = Status;

			Status = STATUS_DOWNLOAD;
		}
		else
			LastStatus = -1;

		if(CreateAllGadgets(TransferBoxArray,&TransferBoxList,TransferGadgetArray,&GadgetList))
		{
			TransferBox . Width	= SZ_GetWindowWidth();
			TransferBox . Height	= Window -> WScreen -> WBorTop + Window -> WScreen -> Font -> ta_YSize + 1;

			TransferBox . Left	= GetScreenLeft(Window) + (GetScreenWidth(Window) - SZ_GetWindowWidth()) / 2;
			TransferBox . Top	= GetScreenTop(Window) + (GetScreenHeight(Window) - SZ_GetWindowHeight()) / 2;

			if(TransferWindow = OpenWindowTags(NULL,
				WA_Left,		TransferBox . Left,
				WA_Top,			TransferBox . Top,
				WA_Width,		SZ_GetWindowWidth(),
				WA_Height,		SZ_GetWindowHeight(),

				WA_DragBar,		TRUE,
				WA_DepthGadget,		TRUE,
				WA_CloseGadget,		TRUE,
				WA_RMBTrap,		TRUE,
				WA_NoCareRefresh,	TRUE,
				WA_SmartRefresh,	TRUE,
				WA_Zoom,		&TransferBox,

				WA_CustomScreen,	Window -> WScreen,

				WA_IDCMP,		IDCMP_CLOSEWINDOW | IDCMP_RAWKEY | IDCMP_VANILLAKEY | IDCMP_NEWSIZE | BUTTONIDCMP | LISTVIEWIDCMP | TEXTIDCMP,

				WA_Title,		Title,
			TAG_DONE))
			{
				ULONG	IntuiLock = LockIBase(NULL);
				BYTE	Activate,Move;

				GuideContext(CONTEXT_TRANSFER);

				if(Config -> TerminalConfig -> AlertMode == ALERT_SCREEN || Config -> TerminalConfig -> AlertMode == ALERT_BEEP_SCREEN)
					Move = Activate = TRUE;
				else
				{
					if(IntuitionBase -> ActiveScreen == TransferWindow -> WScreen)
						Activate = TRUE;
					else
						Activate = FALSE;
				}

				UnlockIBase(IntuiLock);

				if(Move)
				{
					if(TransferWindow -> WScreen -> LeftEdge > 0)
					{
						if(TransferWindow -> WScreen -> TopEdge > 0)
							MoveScreen(TransferWindow -> WScreen,-TransferWindow -> WScreen -> LeftEdge,-TransferWindow -> WScreen -> TopEdge);
						else
							MoveScreen(TransferWindow -> WScreen,-TransferWindow -> WScreen -> LeftEdge,0);
					}
					else
					{
						if(TransferWindow -> WScreen -> TopEdge > 0)
							MoveScreen(TransferWindow -> WScreen,0,-TransferWindow -> WScreen -> TopEdge);
					}

					WindowToFront(TransferWindow);

					ScreenToFront(TransferWindow -> WScreen);
				}

				if(Activate)
					ActivateWindow(TransferWindow);

				PushWindow(TransferWindow);

				AddGList(TransferWindow,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
				RefreshGList(GadgetList,TransferWindow,NULL,(UWORD)-1);

				RefreshTransferWindow();

					/* Protocol */

				SZ_PrintLine(TransferWindow -> RPort,TransferBoxArray[BOX_TRANSFER_1],		0,LocaleString(MSG_GLOBAL_UNKNOWN_TXT));

					/* File, Next file, Space left */

				SZ_PrintLine(TransferWindow -> RPort,TransferBoxArray[BOX_TRANSFER_2],		0,"-");
				SZ_PrintLine(TransferWindow -> RPort,TransferBoxArray[BOX_TRANSFER_2],		1,"-");
				SZ_PrintLine(TransferWindow -> RPort,TransferBoxArray[BOX_TRANSFER_2],		2,"-");

					/* File size, Transferred, Total size, Transferred, Files transferred, Blocks transferred */

				SZ_PrintLine(TransferWindow -> RPort,TransferBoxArray[BOX_TRANSFER_LEFT1],	0,"-");
				SZ_PrintLine(TransferWindow -> RPort,TransferBoxArray[BOX_TRANSFER_LEFT1],	1,"-");
				SZ_PrintLine(TransferWindow -> RPort,TransferBoxArray[BOX_TRANSFER_LEFT1],	2,"-");
				SZ_PrintLine(TransferWindow -> RPort,TransferBoxArray[BOX_TRANSFER_LEFT1],	3,"-");
				SZ_PrintLine(TransferWindow -> RPort,TransferBoxArray[BOX_TRANSFER_LEFT1],	4,"-");
				SZ_PrintLine(TransferWindow -> RPort,TransferBoxArray[BOX_TRANSFER_LEFT1],	5,"-");

					/* Characters per second, Character delay, Packet delay, Packet type, Block check type, Block size */

				SZ_PrintLine(TransferWindow -> RPort,TransferBoxArray[BOX_TRANSFER_RIGHT1],	0,"-");
				SZ_PrintLine(TransferWindow -> RPort,TransferBoxArray[BOX_TRANSFER_RIGHT1],	1,"-");
				SZ_PrintLine(TransferWindow -> RPort,TransferBoxArray[BOX_TRANSFER_RIGHT1],	2,"-");
				SZ_PrintLine(TransferWindow -> RPort,TransferBoxArray[BOX_TRANSFER_RIGHT1],	3,"-");
				SZ_PrintLine(TransferWindow -> RPort,TransferBoxArray[BOX_TRANSFER_RIGHT1],	4,"-");
				SZ_PrintLine(TransferWindow -> RPort,TransferBoxArray[BOX_TRANSFER_RIGHT1],	5,"-");

					/* Estimated time, Elapsed time. */

				SZ_PrintLine(TransferWindow -> RPort,TransferBoxArray[BOX_TRANSFER_LEFT2],	0,"-");
				SZ_PrintLine(TransferWindow -> RPort,TransferBoxArray[BOX_TRANSFER_LEFT2],	1,"-");

					/* Number of errors, Number of timeouts. */

				SZ_PrintLine(TransferWindow -> RPort,TransferBoxArray[BOX_TRANSFER_RIGHT2],	0,"-");
				SZ_PrintLine(TransferWindow -> RPort,TransferBoxArray[BOX_TRANSFER_RIGHT2],	1,"-");

				return(TRUE);
			}
		}

		return(FALSE);
	}
}

	/* DeleteTransferPanel(BYTE WaitForPrompt):
	 *
	 *	Close the transfer window.
	 */

VOID
DeleteTransferPanel(BYTE WaitForPrompt)
{
		/* Wait for user to close the window? */

	if(WaitForPrompt && TransferWindow && GadgetList)
	{
		struct IntuiMessage	*Message;
		ULONG			 IClass,
					 ICode;
		struct Gadget		*IGadget;
		BYTE			 Done = FALSE;

		GT_SetGadgetAttrs(TransferGadgetArray[GAD_TRANSFER_SKIP],TransferWindow,NULL,
			GA_Disabled,	TRUE,
		TAG_DONE);

		do
		{
			WaitPort(TransferWindow -> UserPort);

			while(Message = GT_GetIMsg(TransferWindow -> UserPort))
			{
				IClass	= Message -> Class;
				ICode	= Message -> Code;
				IGadget	= Message -> IAddress;

				GT_ReplyIMsg(Message);

				KeySelect(TransferGadgetArray,4,ICode,TransferWindow,&IGadget,&IClass,&ICode);

				switch(IClass)
				{
					case IDCMP_NEWSIZE:

						if(!(TransferWindow -> Flags & WFLG_ZOOMED))
							RefreshTransferWindow();

						break;

					case IDCMP_CLOSEWINDOW:

						Done = TRUE;

						break;

					case IDCMP_VANILLAKEY:

						if(ICode == ESC)
							Done = TRUE;

						break;

					case IDCMP_GADGETUP:

						if(IGadget -> GadgetID == GAD_TRANSFER_ABORT)
							Done = TRUE;

						break;
				}
			}
		}
		while(!Done);
	}

	TransferError = FALSE;

	if(FileTransferInfo)
	{
		FreeFileTransferInfo(FileTransferInfo);

		FileTransferInfo = NULL;
	}

	if(LastStatus != -1)
		Status = LastStatus;

	LastStatus = -1;

	if(TransferWindow)
	{
		PopWindow();

		CloseWindow(TransferWindow);

		TransferWindow = NULL;
	}

	if(GadgetList)
	{
		FreeGadgets(GadgetList);

		GadgetList = NULL;
	}

	if(TransferBoxList)
	{
		SZ_FreeBoxes(TransferBoxList);

		TransferBoxList = NULL;
	}

	if(TransferInfoList . lh_Head -> ln_Succ)
	{
		struct Node	*Node = TransferInfoList . lh_Head,
				*NextNode;

		while(NextNode = Node -> ln_Succ)
		{
			Remove(Node);

			FreeVec(Node);

			Node = NextNode;
		}

		TransferInfoCount = 0;
	}

	ReleaseWindows();
}
