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

struct Protocol *GetProtocol(LONG);

BOOL DoTransfer(STRPTR path, struct Protocol *protocol, BOOL send)
{
	struct Line *line;
	BPTR newlock, oldlock;
	LONG i;
	BOOL ok;

	if(!protocol)	return(FALSE);

	Location("Transfer gestartet");

	if(newlock = Lock(path, ACCESS_READ))
	{
		oldlock = CurrentDir(newlock);
	}
	else
	{
		SendError("DoTransfer", "Konnte Directory nicht finden");
		return(FALSE);
	}

	InitXPrReq();
	XPrReq.xpr_filename = protocol->options;

	AbortIO(DoTime);
	WaitIO(DoTime);

	ok = FALSE;
	if(XProtocolBase = OpenLibrary(protocol->library, 0))
	{
		ULONG		XPrFlags;

		XPrFlags = XProtocolSetup(&XPrReq);
		if(XPrFlags & XPRS_SUCCESS)
		{
			if(connected || login)
			{
				color(WHITE);
				MyPrintf("Bereit fuer Filetransfer mit ");
				color(VIOLET);
				MyPrintf("%ls", protocol->name);
				color(WHITE);
				MyPrintf(" (Abbruch mit ^X).\r\n");
			}

			KillSer();
			OpenXPrWindow();

			i = warnung;
			line = GetHead(&FileList);
			XPrReq.xpr_filename = (line ? line->text : "File");
			
			if(send)
			{
				warnung = GetFileSize(XPrReq.xpr_filename); /* fuer balken in window */
				ok = XProtocolSend(&XPrReq);
			}
			else
			{
				warnung = 0;
				ok = XProtocolReceive(&XPrReq);
			}
			warnung = i;

			CloseXPrWindow();

			KillSer();
			QueueSerial();
		}
		else SendError("DoTransfer", "XPrSetup() - Error");

		XProtocolCleanup(&XPrReq);
		CloseLibrary(XProtocolBase);
		XProtocolBase = NULL;
	}
	else	SendError("DoTransfer", "Konnte xpr.library nicht öffnen");

	CurrentDir(oldlock);
	UnLock(newlock);

	MyPrintf("Transfer Status : %ls\r\n", (ok ? "ok" : "failed"));
	QueueTimer();

	RemList(&FileList);
	Location("Transfer beendet");

	return(ok);
}

VOID FileInfo(struct Mail *entry)
{
	color(GREEN);
	MyPrintf("\r\nFilename     : ");
	color(CYAN);
	MyPrintf(entry->Filename);
	color(GREEN);
	MyPrintf("\r\nLaenge       : ");
	color(CYAN);
	MyPrintf("%ld bytes", atol(entry->Laenge));
	color(GREEN);
	MyPrintf("\r\nBeschreibung : ");
	color(CYAN);
	MyPrintf(entry->Betreff);
	color(GREEN);
	MyPrintf("\r\nTransfer-Zeit: ");
	color(CYAN);
	MyPrintf("%ld:%-02ld min", atol(entry->Laenge) / realbaud / 6, atol(entry->Laenge) * 10 / realbaud - (atol(entry->Laenge) / realbaud / 6) * 60);
	color(GREEN);
	MyPrintf("\r\nUpload von   : ");
	color(CYAN);
	MyPrintf(entry->Absender);
	color(GREEN);
	MyPrintf("\r\nDatum        : ");
	color(CYAN);
	MyPrintf("%.2ls-%.2ls-%.2ls %.2ls:%.2ls\r\n\r\n", &entry->Datum[4], &entry->Datum[2], &entry->Datum[0], &entry->Datum[6], &entry->Datum[8]);
}

LONG AskProtocol()
{
	struct Protocol *protocol;
	LONG i;

	i = 0;
	protocol = GetHead(&ProtocolList);
	while(protocol)
	{
		MyPrintf("[%2ld] %ls\r\n", ++i, protocol->name);
		protocol = GetSucc(protocol);
	}
	Ask("Protokoll [0 = Auswahl bei Ul/Dl] : ", NULL, -1, TRUE);

	return(atol(wait_buffer));
}

VOID Upload(STRPTR path)
{
	struct Protocol *protocol;

	Location("Upload");

	RemList(&FileList);
	if(!(protocol = GetProtocol(User.protocol)))
	{
		if(!(protocol = GetProtocol(AskProtocol())))
		{
			color(WHITE);
			MyPrintf("<Abbruch>\r\n");
			return;
		}
	}
	if(!protocol->batch)
	{
		struct Line *line;

		Ask("Filename : ", NULL, 20, TRUE);
		if(!connected && !login)	return;
		if(line = AllocVec(sizeof(struct Line), MEMF_ANY | MEMF_CLEAR))
		{
			strcpy(line->text, wait_buffer);
			AddTail(&FileList, line);
		}
	}

	if(!DoTransfer(Config.receive, protocol, FALSE) && !login)	return;
	else
	{
		struct Mail *mail;
		struct FileInfoBlock *finfo;
		char file[256];
		BPTR FH, lock;
		BOOL err;

		color(GREEN);
		MyPrintf("\r\n\r\n HERZLICHEN DANK für den Upload !!!  :-)\r\n\r\n");
		Beep();

		if(!(mail = AllocVec(sizeof(struct Mail), MEMF_ANY | MEMF_CLEAR)))
		{
			SendError("Upload", "Konnte Spiecher nicht reservieren");
			return;
		}

		if(lock = Lock(Config.receive, ACCESS_READ))
		{
			if(finfo = AllocVec(sizeof(struct FileInfoBlock), MEMF_ANY | MEMF_CLEAR))
			{
				do
				{
					if(Examine(lock, finfo) != DOSFALSE)
					{
						ExNext(lock, finfo);
						err = IoErr();
						if(!err)
						{
							if(finfo->fib_Size)
							{
								strcpy(mail->Filename, finfo->fib_FileName);
								SPrintf(mail->Laenge, "%ld", finfo->fib_Size);

								User.ul_already = TRUE;
								User.uploads++;
								User.bytes_upload += atol(mail->Laenge);
								Log.k_uloads += atol(mail->Laenge) / 1024;
								Log.uloads++;

								wait_buffer[0] = 0;
								if(connected || login)
								{
									if(strstr(path, Config.mail))
									{
										SPrintf(mail->Empfaenger, "/%ls", &path[strlen(Config.mail)]);
										mail->Empfaenger[strlen(mail->Empfaenger) - 1] = 0;
									}
									else	mail->Empfaenger[0] = 0;
									ClearDevs();
									Ask("Empfänger : ", mail->Empfaenger, 40, TRUE);
									if(!connected && !login)	wait_buffer[0] = 0;
								}
								if(!wait_buffer[0])
								{
									strcpy(mail->Empfaenger, "SYSOP");
									MyPrintf("Das File wird an den Sysop verschickt.\r\n");
								}
								else	strcpy(mail->Empfaenger, wait_buffer);

								strcpy(mail->Absender, User.alias);
								GetDate();
								SPrintf(mail->Datum, "%.2ls%.2ls%.2ls%.2ls%.2ls", &date[6], &date[3], &date[0], &time[0], &time[3]);
								mail->Pfad[0] = 0;
								SPrintf(mail->MsgId, "%ld%.02ld.%ld@%ls", RangeRand(9999), micros, Status.mail_counter++, Config.netz_name);
								mail->MsgId[19] = 0;
								SPrintf(mail->Typ, "F%ls", mail->Filename);

								FileInfo(mail);
								wait_buffer[0] = 0;
								if(connected || login)
									Ask("Beschreibung : ", NULL, 50, TRUE);
								if(wait_buffer[0])
									strcpy(mail->Betreff, wait_buffer);
								else
									strcpy(mail->Betreff, mail->Filename);

								color(WHITE);
								MyPrintf("\r\n\r\nEinen Moment...\r\n\r\n");

								SPrintf(file, "%lsPUFFER", Config.temp);
								if(!(FH = COpen(file)))
									SendError("Upload", "Konnte PUFFER nicht (er)öffnen");
								else
								{
									char file2[256];

									Seek(FH, 0L, OFFSET_END);
									SPrintf(file, "%ls\r\n", mail->Empfaenger);
									Write(FH, file, strlen(file));
									SPrintf(file, "%ls\r\n", mail->Betreff);
									Write(FH, file, strlen(file));
									SPrintf(file, "%ls\r\n", mail->Absender);
									Write(FH, file, strlen(file));
									SPrintf(file, "%ls\r\n", mail->Datum);
									Write(FH, file, strlen(file));
									SPrintf(file, "%ls\r\n", mail->Pfad);
									Write(FH, file, strlen(file));
									SPrintf(file, "%ls\r\n", mail->MsgId);
									Write(FH, file, strlen(file));
									SPrintf(file, "%ls\r\n", mail->Typ);
									Write(FH, file, strlen(file));
									SPrintf(file, "%ls\r\n", mail->Laenge);
									Write(FH, file, strlen(file));

									Close(FH);

									SPrintf(file, "%lsPUFFER", Config.temp);
									SPrintf(file2, "%ls%ls", Config.receive, mail->Filename);
									Append(file, file2);

									color(GREEN);
									MyPrintf("Das File wird nach dem Logoff einsortiert...\r\n\r\n");
									SPrintf(file, "File [%ls] verschickt", mail->MsgId);
									Location(file);

									do_sort = TRUE;
								}
							}
							SPrintf(file, "%ls%ls", Config.receive, finfo->fib_FileName);
							DeleteFile(file);
						}
					}
					else	err = TRUE;
				}	while(!err);
				FreeVec(finfo);
			}
			UnLock(lock);
		}
		FreeVec(mail);
	}
}

VOID Download(STRPTR path, struct List *list)
{
	struct Mail *mail;
	struct Line *line;
	struct List DownloadList;
	char file[256];
	LONG i, size;

	Location("Download");

	NewList(&DownloadList);

	i = 1;
	size = 0;
	do
	{
		SPrintf(file, "File #[%ld] : ", i);
		Ask(file, NULL, -1, TRUE);
		if(!connected && !login)	goto exit;

		if(wait_buffer[0])
		{
			if(mail = GetHead(list))
			{
				LONG j;

				j = atol(wait_buffer);
				while(mail && !Compare(mail->Filename, wait_buffer) && --j)
					mail = GetSucc(mail);
			}
			if(mail)
			{
				BOOL ok;

				ok = TRUE;

				if(User.time - User.time_used < (size + atol(mail->Laenge)) * 10 / realbaud)
				{
					color(YELLOW);
					MyPrintf("Downloadzeit überschreitet deine Systemzeit.\r\n");
					Beep();
					ok = FALSE;
				}

				if(ok && strlen(User.ud_ratio))
				{
					STRPTR ptr;
					char ud_ratio[21];
					LONG up, down;

					strcpy(ud_ratio, User.ud_ratio);
					if(ptr = strchr(ud_ratio, ':'))
					{
						*ptr = 0;
						up = atol(ud_ratio);
						down = atol(ptr + 1);

						if(User.uploads * down < (User.downloads + i - 1) * up && !User.b_ratio)
						{
							color(YELLOW);
							MyPrintf("Upload/Download-Beschränkung würde überschritten\r\n");
							color(GREEN);
							MyPrintf("Ul/Dl-Ratio : ");
							color(CYAN);
							MyPrintf("%ls\r\n", User.ud_ratio);
							color(GREEN);
							MyPrintf("Uploads     : ");
							color(CYAN);
							MyPrintf("%ld\r\n", User.uploads);
							color(GREEN);
							MyPrintf("Downloads   : ");
							color(CYAN);
							MyPrintf("%ld             ", User.downloads);
							color(YELLOW);
							MyPrintf("Du musst erst %ld File(s) uploaden.\r\n\r\n", (User.downloads + i - 1) * up - User.uploads * down);
							Beep();
							ok = FALSE;
						}
						if(User.bytes_upload * down < (User.bytes_download + size + atol(mail->Laenge)) * up && User.b_ratio)
						{
							color(YELLOW);
							MyPrintf("Upload/Download-Beschränkung würde überschritten\r\n");
							color(WHITE);
							MyPrintf("Ul/Dl-Ratio : ");
							color(CYAN);
							MyPrintf("%ls\r\n", User.ud_ratio);
							color(GREEN);
							MyPrintf("KB Upload   : ");
							color(CYAN);
							MyPrintf("%ld\r\n", User.bytes_upload / 1024);
							color(GREEN);
							MyPrintf("KB Download : ");
							color(CYAN);
							MyPrintf("%ld             ", User.bytes_download / 1024);
							color(YELLOW);
							MyPrintf("Du musst erst %ld KB uploaden.\r\n\r\n", ((User.bytes_download + size + atol(mail->Laenge)) * up - User.bytes_upload * down) / 1024 + 1);
							Beep();
							ok = FALSE;
						}
					}
				}

				if(ok && User.ul_first && !User.ul_already)
				{
					color(YELLOW);
					MyPrintf("Du hast heute noch nichts upgeloadet.\r\nErst etwas uploaden, bevor Download möglich ist.\r\n");
					Beep();
					ok = FALSE;
				}

				if(ok)
				{
					struct Mail *buf_mail;

					if(buf_mail = AllocVec(sizeof(struct Mail), MEMF_ANY | MEMF_CLEAR))
					{
						CopyMem(mail, buf_mail, sizeof(struct Mail));

						AddTail(&DownloadList, buf_mail);
						size += atol(mail->Laenge);
						i++;
					}
					else	SendError("Download", "Konnte Speicher nicht anfordern");
				}
			}
			else
			{
				color(WHITE);
				MyPrintf(out_buffer, "File nicht gefunden.\r\n");
			}
		}
	}	while(wait_buffer[0] && i < 50 && (connected || login));
	if(!connected && !login)	goto exit;

	if(!(mail = GetHead(&DownloadList)))
	{
		color(WHITE);
		MyPrintf("<Abbruch>\r\n");
		return;
	}

	ClrScr();
	color(WHITE);
	MyPrintf("Folgende Files wurden markiert :\r\n\r\n");
	i = 1;
	while(mail)
	{
		color(CYAN);
		MyPrintf("%ld) ", i++);
		color(WHITE);
		MyPrintf("%-20ls ", mail->Filename);
		color(GREEN);
		MyPrintf("%6ld bytes ", atol(mail->Laenge));
		color(YELLOW);
		MyPrintf("(%2ld:%02ld min)\r\n", (atol(mail->Laenge) * 10 / (realbaud * 98 / 100 ) / 60), (atol(mail->Laenge) * 10 / (realbaud * 98 / 100) - (atol(mail->Laenge) * 10 / (realbaud * 98 / 100) / 60) * 60));

		mail = GetSucc(mail);
	}

	do
	{
		color(WHITE);
		MyPrintf("\r\nTotal : ");
		color(GREEN);
		MyPrintf("%ld bytes.  ", size);
		color(WHITE);
		MyPrintf("Ungefähre Download-Zeit : ");
		color(YELLOW);
		MyPrintf("%ld:%02ld ", (size * 10 / (realbaud * 98 / 100) / 60), (size * 10 / (realbaud * 98 / 100) - (size * 10 / (realbaud * 98 / 100) / 60) * 60));
		color(WHITE);
		MyPrintf("Minuten mit ");
		color(GREEN);
		MyPrintf("%ld ", realbaud);
		color(WHITE);
		MyPrintf("Baud.\r\n");
		Ask("\r\n[S]tart, [e]ntfernen oder [a]bbrechen : ", NULL, HOTKEY, TRUE);
		if(!connected && !login)	goto exit;
		if(toupper(wait_buffer[0]) == 'A')	goto exit;
		if(toupper(wait_buffer[0]) == 'E')
		{
			Ask("File : ", NULL, -1, TRUE);
			if(!connected && !login)	goto exit;

			mail = GetHead(&DownloadList);
			i = atol(wait_buffer);
			while(mail && !Compare(mail->Filename, wait_buffer) && --i)
				mail = GetSucc(mail);
			if(mail)
			{
				Remove(mail);
				FreeVec(mail);
			}
			else
			{
				color(WHITE);
				MyPrintf("File nicht gefunden.\r\n");
			}
		}
	}	while((connected || login) && wait_buffer[0] == 'E');
	if(!connected && !login)	goto exit;

	if(mail = GetHead(&DownloadList))
	{
		RemList(&FileList);

		while(mail)
		{
			if(line = GetLine())
			{
				strcpy(line->text, mail->Filename);
				AddTail(&FileList, line);
			}
			mail = GetSucc(mail);
		}
	}
	else
	{
		color(YELLOW);
		MyPrintf("<Abbruch>\r\n");
		goto exit;
	}

	if(GetHead(&FileList))
	{
		struct Protocol *protocol;

		if(!(protocol = GetProtocol(User.protocol)))
		{
			if(!(protocol = GetProtocol(AskProtocol())))
			{
				color(WHITE);
				MyPrintf("<Abbruch>\r\n");
				goto exit;
			}
		}
		DoTransfer(path, protocol, TRUE);

		if(!strstr(path, Config.pmail))
		{
			mail = GetHead(&DownloadList);

			while(mail)
			{
				User.downloads++;
				User.bytes_download += atol(mail->Laenge);
				Log.dloads++;
				Log.k_dloads += atol(mail->Laenge) / 1024;
				mail = GetSucc(mail);
			}
		}
	}
	else	SendError("Download", "Konnte FileList nicht generieren");

	exit:
	RemList(&DownloadList);
	RemList(&FileList);
}

VOID ViewFile(STRPTR path, struct Mail *mail)
{
	Location("View Archive");

	FileInfo(mail);

	if(instr(mail->Filename, ".l"))
	{
		ShowPrg("C:LHA v %ls%ls", path, mail->Filename);
	}
	else
	{
		if(instr(mail->Filename, ".zoo"))
		{
			ShowPrg("C:ZOO v %ls%ls", path, mail->Filename);
		}
		else
		{
			if(instr(mail->Filename, ".arc"))
			{
				ShowPrg("C:ARC v %ls%ls", path, mail->Filename);
			}
			else
			{
				if(instr(mail->Filename, ".zip"))
				{
					ShowPrg("C:UnZip -v %ls%ls ", path, mail->Filename);
				}
				else
				{
					color(WHITE);
					MyPrintf("Dieses File kann nicht entpackt werden.\r\n");
					Ask("Soll es unentpackt angezeigt werden [y/N] : ", NULL, HOTKEY, TRUE);
					if(!connected && !login)	return;
					if(toupper(wait_buffer[0]) == 'Y')
					{
						color(WHITE);
						ShowFile("%ls%ls", path, mail->Filename);
					}
					return;
				}
			}
		}
	}

	Ask("Welches File entpacken und zeigen (z.B. *.doc) : ", NULL, 80, TRUE);
	if((!connected && !login) || !wait_buffer[0])	return;

	color(WHITE);
	MyPrintf("\r\nEinen Moment, das File wird entpackt....\r\n\r\n");

	if(instr(mail->Filename, ".l"))
	{
		ShowPrg("C:LHA p %ls%ls %ls", path, mail->Filename, wait_buffer);
	}
	else
	{
		if(instr(mail->Filename, ".zoo"))
		{
			ShowPrg("C:ZOO xp %ls%ls %ls", path, mail->Filename, wait_buffer);
		}
		else
		{
			if(instr(mail->Filename, ".arc"))
			{
				ShowPrg("C:ARC p %ls%ls %ls", path, mail->Filename, wait_buffer);
			}
			else
			{
				if(instr(mail->Filename, ".zip"))
				{
					ShowPrg("C:UnZip %ls%ls c %ls", path, mail->Filename, wait_buffer);
				}
			}
		}
	}
}


/*
Strange(STRPTR command)
{
	do
	{
		SPrintf(file, "%lsbbs_temp", Config.temp);
		if(!(FH = Open(file, MODE_NEWFILE)))
		{
			SendError("DoTransfer", "couldn't open temporary file !");
			return(FALSE);
		}
		else
		{
			i = 0;
			while(command[i])
			{
				if(command[i] == '%')
				{
					switch(command[++i])
					{
						case 'b':	/* baudrate */
							FPrintf(FH, "%ld", baud);
							break;

						case 'd':	/* device */
							FPrintf(FH, "%ls", Config.device);
							break;

						case 'u':	/* unit */
							FPrintf(FH, "%ld", Config.unit);
							break;

						case 'p':	/* path */
							FPrintf(FH, "%ls", path);
							break;

						case 's':	/* screen adress */
							FPrintf(FH, "%ld", Scr);
							break;

						case 'f':	/* files */
							if(filelist)	/* download */
							{
								if(name[0] == '*')	/* no batch */
								{
									if(strchr(filelist, ' '))
									{
										SPrintf(cmd, "%lc.%lds", '%', (strchr(filelist, ' ')-filelist));
										SPrintf(file, cmd, filelist);
										FPrintf(FH, "%ls", file);
										strcpy(filelist, strchr(filelist, ' ')+1);
									}
									else
									{
										FPrintf(FH, "%ls", filelist);
										SPrintf(file, "%ls", filelist);
										filelist[0] = 0;
									}
									color(WHITE);
									SPrintf(out_buffer, "Sende File : ");
									Send();
									color(CYAN);
									SPrintf(out_buffer, "%ls\r\n", file);
									Send();
								}
								else	FPrintf(FH, "%ls", filelist);	/* batch dl */
							}
							else	/* upload ohne filename-uebergabe */
							{
								Ask("Filename [RET=Abbruch] : ", NULL, 15, TRUE);
								if((!connected && !login) || wait_buffer[0] == 0)
								{
									if(connected || login)
									{
										color(WHITE);
										SPrintf(out_buffer, "\r\n*** Abbruch\r\n\n");
										Send();
									}
									Close(FH);
									return(FALSE);
								}
								FPrintf(FH, "%ls", wait_buffer);
							}
							break;

						default:
							FPrintf(FH, "%2ls", &command[i-1]);
							break;
					}
				}
				else	FPrintf(FH, "%.1ls", &command[i]);

				i++;
			}
			Close(FH);

/* die commandline ist nun ein file, wird geladen und ausgefuehrt */
			SPrintf(file, "%lsbbs_temp", Config.temp);
			if(!(buf = GetFile(file, &size)))
			{
				if(size)	SendError("DoTransfer", "couldn't read from temp-file !");
				return(FALSE);
			}
			else
			{
				Location("starting transfer");
				KillSer();
				err = ShowPrg(buf);
				FreeVec(buf);
				KillSer(); /* muss sein, da showprg sendfile aufruft, diese macht
                          checkio und cmd_read, d.h. doppelt mit naechstem befehl. */

				ReadSER->IOSer.io_Command	=	CMD_READ;
				ReadSER->IOSer.io_Data		=	(APTR)serial_in;
				ReadSER->IOSer.io_Length	=	1;
				SendIO(ReadSER);

				if(err > 0)
				{
					SPrintf(out_buffer, "ERROR [%ld]", err);
					Location(out_buffer);

					Return();
					return(FALSE);
				}
				else	Location("filetransfer finished");
			}
		}
	}	while(name[0] == '*' && strlen(filelist) && filelist);
}
*/
