#include "memory.h"

#define TEMPLATE "LABEL/A,VALUE/F"
  enum templateArgs {
	  ARG_LABEL,
	  ARG_VALUE,
	  ARG_sizeof
  };

#define INPUT_BUFFER_SIZE (1024)

static ConfigEntry_t *__inline AllocConfigEntry(PagerHandle_t * ph, STRPTR label, STRPTR value)
{
	ConfigEntry_t *ce;

	if (!value)
		value = "";

	if (ce = (ConfigEntry_t *) MyAllocVec(sizeof(ConfigEntry_t) + strlen(label) + strlen(value) + 2)) {
		ObtainSemaphore(&ph->ph_Sema);

		ce->ce_Handle = ph;

		ce->ce_UseCount = 1;
		AddTail(&ph->ph_ConfigList, &ce->ce_Node);

		strcpy(ce->ce_Data, value);
		ce->ce_Node.ln_Name = &ce->ce_Data[strlen(ce->ce_Data) + 1];
		strcpy(ce->ce_Node.ln_Name, label);
		ReleaseSemaphore(&ph->ph_Sema);
	}

	return ce;
}

STRPTR __saveds __asm FindPagerConfig(register __a0 PagerHandle_t * ph, register __a1 STRPTR configEntryName)
{
	ConfigEntry_t *ce;
	ULONG line = 0;
	STRPTR inputBuffer, ptr;
	struct RDArgs *ArgsPtr, *MyArgs;
	char *ArgArray[ARG_sizeof];
	BOOL leave;
	BPTR fh;

	ObtainSemaphore(&ph->ph_Sema);

	/* first look to see if we have already read this config entry in */

	for (ce = (ConfigEntry_t *) ph->ph_ConfigList.lh_Head;
	     ce->ce_Node.ln_Succ;
	     ce = (ConfigEntry_t *) ce->ce_Node.ln_Succ)
		if (stricmp(configEntryName, ce->ce_Node.ln_Name) == 0) {
			ce->ce_UseCount++;
			ReleaseSemaphore(&ph->ph_Sema);
			return ce->ce_Data;
		}

	/* sigh.  need to read the config file */

	ce = NULL;

	if (inputBuffer = MyAllocVec(INPUT_BUFFER_SIZE)) {
		/* try and open the config file */

		if (fh = Open("pager:config", MODE_OLDFILE)) {
			/* loop reading lines looking for the service desired */

			leave = FALSE;

			while (leave == FALSE && FGets(fh, inputBuffer, INPUT_BUFFER_SIZE - 1)) {
				line++;

				/*
				 * check to make sure the line isn't all
				 * blank
				 */

				ptr = inputBuffer;
				while (isspace(*ptr))
					ptr++;

				if (!*ptr)
					continue;

				/*
				 * check for comment character at beginning
				 * of line
				 */

				if (*ptr == ';')
					continue;

				/* setup to call ReadArgs() to parse the line */

				if (MyArgs = (struct RDArgs *)AllocDosObject(DOS_RDARGS, TAG_DONE)) {
					MyArgs->RDA_Flags |= RDAF_NOPROMPT;
					MyArgs->RDA_Source.CS_Buffer = inputBuffer;
					MyArgs->RDA_Source.CS_Length = strlen(inputBuffer);
					MyArgs->RDA_Source.CS_CurChr = 0L;

					memset((char *)ArgArray, 0, sizeof(ArgArray));
					if (ArgsPtr = ReadArgs(TEMPLATE, (LONG *)&ArgArray, MyArgs)) {
						if (stricmp(configEntryName, ArgArray[ARG_LABEL]) == 0) {

							/*
							 * we've found the
							 * config entry so
							 * allocate and fill
							 * in a config
							 * structure
							 */
							leave = TRUE;

							ce = AllocConfigEntry(ph, ArgArray[ARG_LABEL], ArgArray[ARG_VALUE]);
						}

						FreeArgs(ArgsPtr);
					}
					else {
						Fault(IoErr(), NULL, inputBuffer, INPUT_BUFFER_SIZE - 1);
						ULog(ph, -1, "Error in config file - line %ld: %s", line, inputBuffer);
						leave = TRUE;
					}

					FreeDosObject(DOS_RDARGS, MyArgs);
				}
			}

			Close(fh);
		}
		else
			ULog(ph, -1, "Couldn't open config file");

		MyFreeVec(inputBuffer);
	}

	ReleaseSemaphore(&ph->ph_Sema);

	if (ce)
		return ce->ce_Data;
	else
		return NULL;
}

STRPTR __saveds __asm FindPagerConfigDefault(register __a0 PagerHandle_t * ph, register __a1 STRPTR configEntryName, register __a2 STRPTR defValue)
{
	ConfigEntry_t *ce;
	STRPTR entry;

	if (!defValue)
		defValue = "";

	if (entry = FindPagerConfig(ph, configEntryName))
		return entry;
	else {
		ce = AllocConfigEntry(ph, configEntryName, defValue);

		if (ce)
			return ce->ce_Data;
		else
			return NULL;
	}
}

void __saveds __asm FreePagerConfig(register __a0 STRPTR configEntry)
{
	ConfigEntry_t *ce;

	if (configEntry) {
		ce = (ConfigEntry_t *) ((size_t) configEntry - offsetof(ConfigEntry_t, ce_Data));

		ObtainSemaphore(&ce->ce_Handle->ph_Sema);

		if (--ce->ce_UseCount == 0) {
			Remove(&ce->ce_Node);
			MyFreeVec(ce);
		}

		ReleaseSemaphore(&ce->ce_Handle->ph_Sema);
	}
}

BOOL __saveds __asm PagerConfigYesNo(register __a0 STRPTR configEntry)
{
	UBYTE value;

	if (configEntry) {
		while (isspace(*configEntry))
			configEntry++;

		value = tolower(*configEntry);

		if (value == 'y' || value == 't' || atol(configEntry) == 1)
			return TRUE;
		else
			return FALSE;
	}
	else
		return FALSE;
}
