#include "spooler.h"
#include "/include/memory.h"

/* our memory pool header */
#define POOLSIZE 4096
APTR pool;

/* storage for library bases */
struct Library *UtilityBase;
struct Library *PagerSupportBase;

/* our pager-support.library handle */
APTR ph;

#define ARG_TEMPLATE "TO/M/A,URGENT/S,LOGLEVEL/N/K,MESSAGE/F"
  enum ReadArgsArray {
	  ARG_DEST,
	  ARG_URGENT,
	  ARG_LOGLEVEL,
	  ARG_PAGE,
	  ARG_sizeof
  };

static UBYTE dialCommand[1024];

static void DoUrgent(LONG *logLevel)
{
	STRPTR urgentModem;

	urgentModem = FindPagerConfigDefault(ph, "URGENTMODEM", "0");

	sprintf(dialCommand, "Run DialIXO modem %s", urgentModem);

	if (logLevel)
		sprintf(&dialCommand[strlen(dialCommand)], " loglevel %ld", *logLevel);

	ULog(ph, 0, dialCommand);

	SystemTags(dialCommand, SYS_UserShell, TRUE, TAG_DONE);
}

static STRPTR GetPageText(STRPTR pageText)
{
	STRPTR messagePtr, newPtr;
	ULONG messageLen, inputLen;

	if (pageText) {
		messageLen = strlen(pageText);

		/* remove white space at end of message */
		while (messageLen && isspace(pageText[messageLen - 1]))
			pageText[--messageLen] = '\0';

		if (messagePtr = MyAllocVec(messageLen + 1)) {
			CopyMem(pageText, messagePtr, messageLen);
			messagePtr[messageLen] = '\0';
			return messagePtr;
		}
		else
			return NULL;
	}
	else {
		messageLen = 0;

		if (messagePtr = MyAllocVec(1)) {
			messagePtr[0] = '\0';

			while (FGets(Input(), inputBuffer, sizeof(inputBuffer) - 1)) {
				inputLen = strlen(inputBuffer);

				if (!(newPtr = MyAllocVec(messageLen + inputLen + 1))) {
					MyFreeVec(messagePtr);
					return NULL;
				}

				CopyMem(messagePtr, newPtr, messageLen);
				MyFreeVec(messagePtr);

				messagePtr = newPtr;

				CopyMem(inputBuffer, &messagePtr[messageLen], inputLen);

				messageLen += inputLen;

				messagePtr[messageLen] = '\0';
			}

			/* remove white space at end of message */
			while (messageLen && isspace(messagePtr[messageLen - 1]))
				messagePtr[--messageLen] = '\0';
		}

		return messagePtr;
	}
}

int DoDest(STRPTR to, STRPTR pageText)
{
	PagerAlias_t *als, nonAls;
	int result = 0;
	STRPTR ptr;
	UBYTE c;

	ptr = to;

	/* check to see if this is a non-alias specification */

	while (c = *ptr++) {
		if (c == ':') {
			if (nonAls.als_Service = MyAllocVec(strlen(to) + 1)) {
				strcpy(nonAls.als_Service, to);

				nonAls.als_Service[ptr - to - 1] = '\0';

				nonAls.als_Name = to;
				nonAls.als_PIN = &nonAls.als_Service[ptr - to];
				nonAls.als_MaxMessageLen = 0;
				nonAls.als_MaxPageLen = 0;

				SetLogWho(ph, to);

				result = DoPage(&nonAls, pageText);

				SetLogWho(ph, NULL);

				return result;
			}
			else {
				ErrorMsg("out of memory!");
				return 5;
			}
		}
	}

	/* it's not a non-alias so try and read it as an alias */

	if (!(als = FindPagerAlias(ph, to))) {
		ErrorMsg("couldn't find \"%s\" alias.", to);
		ULog(ph, -1, "couldn't find \"%s\" alias.", to);
		result = 5;
	}

	if (!result) {
		SetLogWho(ph, als->als_Name);

		result = DoPage(als, pageText);

		SetLogWho(ph, NULL);

		FreePagerAlias(als);
	}

	return result;
}

static int DoArgs(void)
{
	struct RDArgs *RArgs;
	STRPTR ArgArray[ARG_sizeof];
	int result = 0;
	STRPTR alwaysUrgent;
	STRPTR pageText;
	STRPTR *destList;

	/* do the stuff needed to call ReadArgs to parse the command line */
	memset(ArgArray, 0, sizeof(ArgArray));

	if (RArgs = ReadArgs(ARG_TEMPLATE, (LONG *)&ArgArray, NULL)) {
		if (ArgArray[ARG_LOGLEVEL])
			SetLogLevel(ph, *((LONG *)ArgArray[ARG_LOGLEVEL]));

		destList = (STRPTR *)ArgArray[ARG_DEST];

		if (!destList) {
			ErrorMsg("no destinations specified.");
		}
		else {
			if (pageText = GetPageText(ArgArray[ARG_PAGE])) {
				if (pageText[0]) {
					while (*destList && !result)
						result = DoGroup(*destList++, pageText);
				}
				else {
					ErrorMsg("no message specified - page not spooled");
				}
			}
			else {
				ErrorMsg("out of memory!");
				result = 5;
			}

			if (!result)
				if (ArgArray[ARG_URGENT])
					DoUrgent((LONG *)ArgArray[ARG_LOGLEVEL]);
				else if (alwaysUrgent = FindPagerConfig(ph, "ALWAYSURGENT")) {
					if (PagerConfigYesNo(alwaysUrgent))
						DoUrgent((LONG *)ArgArray[ARG_LOGLEVEL]);

					FreePagerConfig(alwaysUrgent);
				}
		}

		FreeArgs(RArgs);
	}
	else {
		PrintFault(IoErr(), PROGNAME);
		result = 5;
	}

	return result;
}

void __regargs main(char *cmdptr, int cmdlen, struct WBStartup *WBMsg)
{
	int result;

	/* punt if started from Workbench */
	if (WBMsg)
		XCEXIT(20);

#ifdef _DEBUG
#define SUPPORT_LIB "pager:libs/pager-support-debug.library"
#else
#define SUPPORT_LIB "pager:libs/pager-support.library"
#endif

	if (UtilityBase = OpenLibrary("utility.library", 37)) {
		if (PagerSupportBase = OpenLibrary(SUPPORT_LIB, 0)) {
			if (pool = CreatePool(MEMF_CLEAR, POOLSIZE, POOLSIZE / 2)) {
				if (ph = AllocPagerHandle(PROGNAME)) {
					result = DoArgs();

					FreePagerHandle(ph);
				}
				else {
					ErrorMsg("couldn't allocate support library handle.");
					result = 10;
				}

				DeletePool(pool);
			}
			else {
				ErrorMsg("out of memory!");
				result = 20;
			}

			CloseLibrary(PagerSupportBase);
		}
		else {
			ErrorMsg("couldn't open %s.\n", SUPPORT_LIB);
			result = 20;
		}

		CloseLibrary(UtilityBase);
	}
	else {
		ErrorMsg("couldn't open %s.\n", "utility.library");
		result = 20;
	}

	XCEXIT(result);
}
