#import "ArchieServer.h"

#import <appkit/appkit.h>
#import <ctype.h>

// Host browser cell string for custom archie server
static const char *CUSTOM_SERVER_STRING = "Custom Server";

@implementation ArchieServer

static List *archieServers;
static HashTable *archieServersByName;

/*\ ------ Initializing/accessing instance list ------ \*/
+ initArchieServers: serverTable
{
/* --- MethodDescription
	ReturnValue: self if serverTable is not empty, Nil if it is;
	Description: This method traverses the NXStringTable given by serverTable
		and instantiates an ArchieServer object for each entry;
	Args: serverTable: The NXStringTable with the server information;
*/
const char *key, *value; 
NXHashState state;
ArchieServer *server;

	if( [serverTable count] == 0 )
		return Nil;

	archieServers = [[List alloc] initCount: 0];
	archieServersByName = [[HashTable alloc] initKeyDesc: "*" valueDesc: "@"];
	state = [serverTable initState]; 
	while([serverTable nextState: &state key: &key value: &value])
	{	// Create next instance
		server = [[ArchieServer alloc] initForName: key tableValue: value];
		[archieServers addObject: server];
		[archieServersByName insertKey: key value: server];
	}
	// Add a default 'Custom Server' object
	server = [[ArchieServer alloc] initForName: CUSTOM_SERVER_STRING
		tableValue: "123.345.678.90 (Your server)"];
	[archieServers addObject: server];
	[archieServersByName insertKey: CUSTOM_SERVER_STRING value: server];

	return self;
}

+ (List *) archieServers
{
	return archieServers;
}

+ archieServerAt:(int) index
{
/* --- MethodDescription
	ReturnValue: The ArchieServer for index if it exists, nil otherwise;
	Description: Retrieves and returns the ArchieSever instance from
		the archieServers list. If the list is nil or the index does not
		refer to a valid object nil is returned;
	Args: index: the index into archieServers;
*/
ArchieServer *server;

	if( archieServers == nil )
		return nil;
	server = [archieServers objectAt: index];
	return server;
}

+ archieServerFor:(const char *) name
{
/* --- MethodDescription
	ReturnValue: The ArchieServer for name if it exists, nil otherwise;
	Description: Retrieves and returns the ArchieSever instance from
		the archieServersByName list. If the table is nil or the name does
		not refer to a valid object nil is returned;
	Args: index: the index into archieServers;
*/
ArchieServer *server;

	if( archieServersByName == nil )
		return nil;
	server = (ArchieServer *)[archieServersByName valueForKey: name];
	return server;
}

/*\ ------ Instance methods ------ \*/
- initForName:(const char *) name tableValue:(const char *) value
{
/* --- MethodDescription
	ReturnValue: self;
	Description: Sets up the server instance from name and value. The
		instance variables are simply pointer to or into the name and
		value arguments since we assume that their storage is maintained
		int the NXStringTable from which they were taken. The value string
		is assumed to be of the form 'dot_dec_addr server_info'.;
	Args:
		name: the serverName string;
		value: the 'dot_dec_addr server_info' string;
*/
int addrLen;

	serverName = name;
	addrLen = strspn(value, "0123456789.");
	strncpy(serverDotAddr, value, addrLen);
	serverInfo = value + addrLen;
	// Move past any white space
	while( *serverInfo != 0 && isspace(*serverInfo) )
		serverInfo ++;

	return self;
}

- (const char *) serverName
{
	return serverName;
}
- (const char *) serverDotAddr
{
	return serverDotAddr;
}
- (const char *) serverInfo
{
	return serverInfo;
}

@end
