#import "ProsperoVLINK.h"

#import <objc/List.h>
#import <libc.h>
#import <strings.h>

@implementation ProsperoVLINK

/* Initialize an instance from a VLINK structure.  Parsing is based on
	the display_link() proceedure of archie.c in the Prospero distribution. */
- initVLINK : (VLINK) v
{
PATTRIB link;
int y,m,d,hr,min,sec;
int n;

	[super init];

	/* File path, component name and file level */
	filePath = (char *) malloc(strlen(v->filename)+1);
	subPath = (char *) malloc(strlen(v->filename)+1);
	if(filePath == NULL || subPath == NULL)
		return nil;
	strcpy(filePath,v->filename);
	componentIndex = strlen(v->filename) - strlen(v->name);
	for(n = 0, fileDepth = 0; n < strlen(filePath); n ++)
		if(filePath[n] == '/')
			fileDepth ++;

	/* Create a unique hostname NXAtom */
	hostname = NXUniqueString(v->host);

	/* Parse v->lattrib */
	link = v->lattrib;
	while(link)
	{
		if( strcmp(SIZE,link->aname) == 0)
			fileSize = atoi(link->value.ascii);
		else if(strcmp(MODES,link->aname) == 0)
			strncpy(unixMode,link->value.ascii,10);
		else if(strcmp(DATE,link->aname) == 0)
		{
			sscanf(link->value.ascii,"%4d%2d%2d%2d%2d",
				&y,&m,&d,&hr,&min);
			[super initFromDate : d : m : y];
			sec = 0;
			[super setTime : hr : min : sec];
		}
		link = link->next;
	}
	listing = nil;

	return self;
}

- initVLINK : (DirEntryPtr) dirList host: (const char *) host
	parent: (const char *) parentPath
{
int y,m,d,hr,min,sec;
int n,pathLength;

	[super init];

	/* File path, component name and file level */
	pathLength = strlen(parentPath) + strlen(dirList->name) + 2;
	filePath = (char *) malloc(pathLength);
	subPath = (char *) malloc(pathLength);
	if(filePath == NULL || subPath == NULL)
		return nil;
	sprintf(filePath,"%s/%s",parentPath,dirList->name);
	componentIndex = strlen(parentPath) + 1;
	for(n = 0, fileDepth = 0; n < strlen(filePath); n ++)
		if(filePath[n] == '/')
			fileDepth ++;
	hostname = host;

	/* File attributes */
	fileSize = dirList->bytes;
	strncpy(unixMode,dirList->mode,10);
	sscanf(dirList->date,"%4d%2d%2d%2d%2d",
				&y,&m,&d,&hr,&min);
	[super initFromDate : d : m : y];
	sec = 0;
	[super setTime : hr : min : sec];

	return self;
}


/* Go through the DirEntry list and generate a ProsperoVLINK with
	the correct path and hostname */
- setListing: (DirEntryPtr) list
{
DirEntryPtr next;
int parentPathLength;
id vlink;

	parentPathLength = strlen(filePath);
	listing = [[List alloc] initCount: 0];
	if(listing == nil)
		return nil;

	while(list != NULL)
	{
		vlink = [[ProsperoVLINK alloc]  initVLINK: list  host: hostname
				parent: filePath];
		if(vlink == nil)
		{
			[listing free];
			return nil;
		}
		[listing addObject: vlink];
		next = list->next;
		free(list);
		list = next;
	}
	return self;
}

- free
{
	free(filePath);
	free(subPath);
	[listing freeObjects];
	[listing free];

	return [super free];
}

/* Instance variable access methods */
- (int) fileSize
{
	return fileSize;
}
- (int) mode
{
int mode,i,j;
	mode = 0;
	for(i = 1,j = 8; i < 10; i ++, j --)
		if(unixMode[i] != '-')
			mode |= (1 << j);
	return mode;
}
- (const char *) unixMode
{
	return (const char *) unixMode;
}
- (BOOL) isDirectory
{
	if(unixMode[0] == 'd')
		return YES;
	return NO;
}
- (int) fileDepth;
{
	return fileDepth;
}
- (const char *) filePath
{
	return (const char *) filePath;
}
- (const char *) fileName
{
	return (const char *) &filePath[componentIndex];
}
- (const char *) hostname
{
	return hostname;
}

- (const char *) nameAtLevel: (int) level
{
int n;
char *thisLevel,*nextLevel;
	if(level > fileDepth)
		return NULL;
	strcpy(subPath,filePath);
	thisLevel = subPath;
	nextLevel = index(++thisLevel,'/');
	n = 1;
	while( n < level)
	{
		thisLevel = nextLevel;
		nextLevel = index(++thisLevel,'/');
		n ++;
	}
	if(nextLevel != NULL)
		*nextLevel = '\0';
	return (const char *) thisLevel;
}

- listing
{
	return listing;
}

@end
