
#import "FtpFileSystem.h"
#import "FtpDirectory.h"
#import "FtpHost.h"
#import "FtpSession.h"
#import "FtpConnection.h"
#import "NXmystd.h"

@implementation FtpFileSystem

- initForHost:host andUser:(NXAtom) user;
{
	[super init];
	myhost = host;
	myuser = user;
	rootDir = [[FtpDirectory alloc] initForName:"." withParent:nil];
	
	return self;
}

- free;
{
	rootDir = [rootDir free];
	return [super free];
}

- write:(NXTypedStream *)stream;
{
	[super write:stream];
	NXWriteTypes(stream,"%@@",&myuser,&myhost,&rootDir);
	return self;
}

- read:(NXTypedStream *)stream;
{
	[super read:stream];
	NXReadTypes(stream,"%@@",&myuser,&myhost,&rootDir);
	return self;
}


- getDirForPath:(const char *)path;
{
	char *s,*s2,*sorig;
	id dir;
	int len;
	
	len = strlen(path);
	sorig = s = calloc(len+1,sizeof(char));
	strcpy(s,path);
	dir = rootDir;
	
	while ( *s && dir )
	{
		while (*s == '/')
			s++;
		if ( !*s )
			break;
		s2 = strchr(s,'/');
		if ( !s2 )
		{
			dir = [dir getDirWithName:s];
			*s='\0';
			break;
		}
		*s2 = '\0';
		dir = [dir getDirWithName:s];
		s = s2+1;
	}
	free(sorig);
	return dir;
}
		
- createDirsForPath:(const char *)path;
{
	char *s,*s2,*sorig;
	id dir;
	int len;
	
	len = strlen(path);
	sorig = s = calloc(len+1,sizeof(char));
	strcpy(s,path);
	dir = rootDir;
	//LOGF("%s",path);
	while ( *s )
	{
		id parent;
		while (*s == '/')
			s++;
		if ( !*s )
			break;
		s2 = strchr(s,'/');
		parent = dir;
		if ( !s2 )
		{
			id file = [dir getObjWithName:s];
			if (!file)
			{
				file = [[FtpFile alloc] initForName:NXUniqueString(s) withParent:parent];
				[parent add:file];
				//LOGF("added file");
			}
			break;
		}
		*s2 = '\0';
		dir = [parent getDirWithName:s];
		if (!dir)
		{
			dir = [[FtpDirectory alloc] initForName:NXUniqueString(s) withParent:parent];
			[parent add:dir];
			//LOGF("added dir");
		}
		//LOGF("s=%s,dir=%s,parent=%s",s,[dir path],[parent path]);
		s = s2+1;
	}
	free(sorig);
	return self;
}
		

- rootDir;
{
	return rootDir;
}


// NXBrowser delegate methods
- (int) browser:sender fillMatrix:matrix inColumn:(int)column;
{
	id dir;
	char path[1000];
	
	//LOGF("browser:%p fillMatrix:%p inColumn:%d\n",sender,matrix,column);
	[sender getPath:path toColumn:column];
	//LOGF("fillMatrix: path for this column: %s\n",path);
	dir = [self getDirForPath:path];
	if (dir)
	{
		//LOGF("fillMatrix: dir for this column:%s\n",[dir name]);
		//LOGF("fillMatrix: path:%s\n",[dir path]);
		if ([dir needsCheck] || [dir needsUpdate])
		{
			//LOGF("dir needs update");
			//printf("target=%p,ftpConn=%p\n",[sender target],[[sender target] ftpConn]);
			[dir setShouldTransferIfNeeded];
			[[[sender target] ftpConn] addToQueue:dir];
		}
		//[sender validateVisibleColumns];
		//[dir addSubDirsToCheckTo:[[sender target] ftpConn]];
		return [dir fillMatrix:matrix];
	}
	else
	{
		puts("ERROR: dir not found");
		return 0;
	}
}

- (BOOL) browser:sender columnIsValid:(int) column;
{
	id dir;
	char path[1000];
	
	//printf("browser:%p columnIsValid:%d\n",sender,column);
	[sender getPath:path toColumn:column];
	//printf("isValid: path for this column: %s\n",path);
	dir = [self getDirForPath:path];
	if (dir)
	{
		BOOL needsDisplay = [dir needsDisplay];
		//LOGF("dir for column#%d:%s\n",column,[dir name]);
		//printf("isValid: path:%s\n",[dir path]);
		//LOGF(needsDisplay?"needs Display":"needs NO Display");
		return !needsDisplay;
	}
	//LOGF("no dir found");
	return NO;
}

- validateBrowser:browser;
{
	int i;
	id delegate = [browser delegate];
	
	for (i=0;i<=[browser lastColumn];i++)
	{
		if (![delegate browser:browser columnIsValid:i])
		{
			[delegate browser:browser fillMatrix:[browser matrixInColumn:i] inColumn:i];
			[browser setNeedsDisplay:YES];
		}
	}
	
	return self;
}

@end
