
#import <libc.h>
#import <sys/dir.h>
#import <sys/stat.h>
#import <sys/types.h>
#import <strings.h>

#import "Tree.h"
#import "UnixFilter.h"

static id createUnixTree(const char *directoryName,Properties *props,NXZone *aZone,int depth,int maxdepth);
static BOOL isFilenameOK(const char *s);

@implementation UnixFilter

+ filterWithProps:(Properties *)props inZone:(NXZone *)aZone
{
	const char *localDirectory;
	const char *const *localFiles;
	char buffer[MAXPATHLEN];
	id openpanel = [[OpenPanel new] chooseDirectories:YES];
	
	if([openpanel runModalForTypes:NULL]){
		[openpanel chooseDirectories:NO];
		localDirectory = [openpanel directory];
		localFiles = [openpanel filenames];
		strcpy(buffer,localDirectory);
		strcat(buffer,"/");
		strcat(buffer,*localFiles);
		return createUnixTree(buffer, props, aZone, 0, 3);
	}
	return nil;
}

@end

static id createUnixTree(const char *directoryName,Properties *props,NXZone *aZone,int depth,int maxdepth)
{
	id newTree,childTree;
	struct stat buf;
	DIR	*dirp;
	struct direct *dp;
	char file[MAXPATHLEN], *charPtr;

	if(depth >= maxdepth)
		return nil;
	charPtr = rindex(directoryName,'/');
	if(charPtr && (charPtr != directoryName + strlen(directoryName)))
		newTree = [[Tree allocFromZone:aZone] initLabel:(charPtr + 1) props:props];
	else
		newTree = [[Tree allocFromZone:aZone] initLabel:directoryName props:props];
	dirp = opendir(directoryName);
	for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)){
		if(isFilenameOK(dp->d_name)){
			strcpy(file, directoryName);
			strcat(file, "/");
			strcat(file, dp->d_name);
			stat(file, &buf);
			if((buf.st_mode & S_IFMT) == S_IFDIR){
				childTree = createUnixTree(file,props,aZone, depth + 1, maxdepth);
				if(childTree)
					[newTree addTree:childTree];
				[newTree setPathKind:ELLIPSE_NODETYPE];
			} else {
				charPtr = rindex(dp->d_name,'/');
				if(charPtr && (charPtr != dp->d_name + strlen(dp->d_name)))
					childTree = [[Tree allocFromZone:aZone] initLabel:(charPtr + 1) props:props];
				else
					childTree = [[Tree allocFromZone:aZone] initLabel:(dp->d_name) props:props];
				[newTree addTree:childTree];	
			}
		}
	}
	closedir(dirp);
	return newTree;
}

static BOOL isFilenameOK(const char *s)
{
	return (!s[0] || s[0] == '.') ? NO : YES;
}
