/***************************************************************************
 * FindPlace.c
 *
 * FindPlace, Copyright ©1995 Lee Kindness.
 *
 */

#define PROGNAME "FindPlace"

/* All our includes are in this file */
#include "gst.c"

#include "FindPlace_rev.h"

/* Libraries used, don't auto open them SAS/C :) */
struct Library *NodelistBase = NULL;

/* Structure we pass to NLEnumNode, holds useful data */
struct NLEnumData
{
	NodeList ed_NodeList;
	STRPTR   ed_Pattern;
	Addr    *ed_Start;
	BOOL     ed_Full;
	BOOL     ed_Points;
	BOOL     ed_Return;
	ULONG    ed_Matches;
};

const char *const nl_keys[NL_ENTRY_MAX] =
	{ "Node", "Host", "Hold", "Hub", "Pvt", "Point", "Zone", "Region", "Down" };

const char *vtag = VERSTAG;


/***************************************************************************
 * EnumFunc() -- Called for each node in the nodelist. Print node if it
 * matches 'pattern'
 */
BOOL __saveds __stdargs EnumFunc(Addr *addr, ULONG region, struct NLEnumData *ud)
{
	BOOL ret;
	NodeDesc *nd;
	ret = FALSE;
	
	/* Check if a point, and what to do... */
	if( !ud->ed_Points && addr->Point )
		/* Skip this entry... */
		return( TRUE );

	/* Check for ctrl-c */
	if( !CheckSignal(SIGBREAKF_CTRL_C) )
	{
		ret = TRUE;
	
		/* Find that node in nodelist */
		if( nd = NLIndexFind(ud->ed_NodeList, addr, 0) )
		{
			if( (nd->System) &&
			    (MatchPatternNoCase(ud->ed_Pattern, nd->City)) )
			  {
			  	/* Match! Print the node details */
			  	ud->ed_Matches++;
			  	if( ud->ed_Full )
			  	{
						Printf("Node %ld:%ld/%ld.%ld, \"%s\" is in %s\n",
						       nd->Node.Zone, nd->Node.Net,
						       nd->Node.Node, nd->Node.Point,
						       nd->System, nd->City);
						Printf("System is listed as %s\n",
						       (nd->Type < NL_ENTRY_MAX) ? nl_keys[nd->Type] : "unknown type");
						Printf("Operated by %s\n", nd->Sysop);
						Printf("Region %ld, Hub %ld\n", nd->Region, nd->Hub);
						Printf("Baud %ld\n", nd->BaudRate);
						Printf("Phone %s, ", nd->Phone);
						if(nd->Cost != -1)
							Printf("Cost %01ld.%02ld\n", nd->Cost/100, nd->Cost%100);
						else
							Printf("Undialable\n");
						Printf("Flags %s\n\n", nd->Flags);
					} else
					{
						/* Short output mode */
						Printf("%ld:%ld/%ld.%ld %s, %s, %s, %s\n", nd->Node.Zone, 
						       nd->Node.Net, nd->Node.Node, nd->Node.Point, nd->System, 
						       nd->City, nd->Sysop, nd->Phone);
					}
				}
			NLFreeNode(nd);
		}
	} else
		SetIoErr(ERROR_BREAK);
	if( ret )
		ud->ed_Return = TRUE;
	else
		ud->ed_Return = FALSE;
	return ret;
}


/***************************************************************************
 * main() --
 */
int main(int argc, char **argv)
{
	int ret = RETURN_FAIL;
	
	/* Open libraries */
	if( (NodelistBase = OpenLibrary(TRAPLIST_NAME, TRAPLIST_VER)) &&
	    (DOSBase->dl_lib.lib_Version >= 36) ) 
	{
		/* Parse arguments */
		struct RDArgs *rda;
		#define DEF_NODELIST "Nodelist:"
		#define TEMPLATE "PATTERN/M/A,START/K,FULL/S,POINTS/S,BUFSIZE/K/N,NODELIST/K"
		#define OPT_PATTERN 0
		#define OPT_START 1
		#define OPT_FULL 2
		#define OPT_POINTS 3
		#define OPT_BUFSIZE 4
		#define OPT_NODELIST 5
		#define OPT_MAX 6
		STRPTR args[OPT_MAX] = {0, 0, 0, 0, 0, DEF_NODELIST};

		if( rda = ReadArgs(TEMPLATE, (LONG *)&args, NULL) ) 
		{
			STRPTR s;
			NodeList nl;
			ULONG bufsize;
			
			if( args[OPT_BUFSIZE] )
				bufsize = *((ULONG *)args[OPT_BUFSIZE]);
			else
				bufsize = 0;
			
			/* Open nodelist */
			if( nl = NLOpen(args[OPT_NODELIST], 0) )
			{
				ret = RETURN_OK;
				s = *((STRPTR *)args[OPT_PATTERN]);
				while( (s) && (*s) && !ret ) 
				{
					STRPTR pattern;
					/* Act on the pattern */
				
					/* Alloc buffer for tokenized widcard */
					if( pattern = AllocVec(strlen(s)*3, MEMF_CLEAR) )
					{
						/* Parse wildcard */
						if( ParsePatternNoCase(s, pattern, strlen(s)*3) != -1 )
						{
							Addr *start;
							struct NLEnumData *ud;
							/* Parse start address */
							if( args[OPT_START] )
							{
								if( start = AllocVec(sizeof(Addr), MEMF_CLEAR) )
								{
									if( NLParseAddr(start, args[OPT_START], NULL) )
									{
										FreeVec(start);
										start = NULL;
									}
								}
							} else
								start = NULL;
							/* Alloc user data structure */
							if( ud = AllocVec(sizeof(struct NLEnumData), MEMF_CLEAR) )
							{	
								ud->ed_NodeList = nl;
								ud->ed_Pattern = pattern;
								ud->ed_Start = start;
								ud->ed_Full = (BOOL)args[OPT_FULL];
								ud->ed_Points = (BOOL)args[OPT_POINTS];
								ud->ed_Matches = 0;
							
								NLEnumNode(nl, bufsize, start, EnumFunc, ud);
								if( !ud->ed_Return )
								{
									LONG error;
									error = IoErr();
									PrintFault(error, PROGNAME);
									ret = RETURN_FAIL;
								}
								
								if( ud->ed_Matches )
								{
									Printf("\n"
									       "---\n"
									       "%ld %s found.\n"
									       VERS " (" DATE ")\n"
									       "Copyright (c)Lee Kindness, 2:259/26.20\n",
									       ud->ed_Matches,
									       ((ud->ed_Matches == 1) ? "match" : "matches"));
								}
								FreeVec(ud);
							}
						}
						FreeVec(pattern);
					}
				
					/* Get the next string in the array */
					s = strchr(s,'\0');
					s++;
				}
				NLClose(nl);
			}
			FreeArgs(rda);
		}
		CloseLibrary(NodelistBase);
	}
	return ret;
}
