#import "MyOpenPanel.h"

#import <appkit/Application.h>
#import <appkit/Button.h>
#import <appkit/Matrix.h>
#import <appkit/NXBrowser.h>
#import <appkit/NXBrowserCell.h>
#import <appkit/SavePanel.h>
#import <appkit/Text.h>
#import <appkit/TextField.h>
#import <appkit/appkit.h>
#import <appkit/nextstd.h>
#import <string.h>
#import <sys/types.h>
#import <sys/stat.h>
#import <stdlib.h>

#define CANCEL 0
#define OK 1

static int lastColumn = 0;
static char path[MAXPATHLEN], completedPath[MAXPATHLEN];
static char *completionName;

@implementation MyOpenPanel

- init
{
	[super init];
	[NXApp loadNibSection: "OpenPanel.nib" owner: self];

	dirLevel = 0;
	fileCount = 0;

	return self;
}
	
- goHome: sender
{
	strcpy(pathName,NXHomeDirectory());
	[browser setPath : pathName];
	[form setStringValue : NULL at : 0];
	return self;
}

- cancel:sender
{
	[NXApp stopModal : CANCEL];
	return self;
}

- ok:sender
{
	[NXApp stopModal : OK];
	return self;
}

- doubleClick
{
	if(isDirectory == YES && dirFlag == NO)
		return self;
	return [self ok : self];
}

- setTitle : (char *) theTitle
{
	[panelTitle setStringValue : theTitle];
	return self;
}

- (const char *) pathName
{
	return (const char *) pathName;
}

- (int) runModal: (BOOL) selectDirs
{
	return [self runModal: NULL : selectDirs];
}

- (int) runModal: (char *) directory :(BOOL) selectDirs
{
int rtnVal;
char *currentDir;

	dirFlag = selectDirs;
	if(directory == NULL)
		getwd(pathName);
	else
		strcpy(pathName,directory);
	[form setStringValue : NULL at : 0];
	[browser useScrollButtons : YES];
	[browser setTarget : self];
	[browser setAction : @selector(getSelectionPath)];
	[browser setDoubleAction : @selector(doubleClick)];
	[browser loadColumnZero];
	[browser setPath: pathName];

	currentDir = strrchr(pathName,'/');
	[form setStringValue : ++currentDir at : 0];
	[form selectTextAt: 0];

	[panel orderFront : self];
	while ( (rtnVal = [NXApp runModalFor : panel]) == NX_RUNCONTINUES );
	[panel orderOut : self];

	return rtnVal;
}

/* Return only the normally visible files */
int SelectFiles(struct direct *entry)
{
	if(entry->d_name[0] == '.')
		return 0;
	else
		return 1;
}

/* Case insenseitive alpha sort */
int AlphaSort(struct direct **d1,struct direct **d2)
{
	return strcasecmp((*d1)->d_name,(*d2)->d_name);
}

/* Browser delegate methods */
/* This method returns the number of visible files in the directory corresponding to column */
- (int) browser : sender getNumRowsInColumn : (int) column
{
struct direct **newList;

	if(column > 0)
	{
		[sender getPath : path toColumn : column];
		fileCount = scandir(path, &newList,SelectFiles, AlphaSort);
	}
	else
		fileCount = scandir("/", &newList,SelectFiles, AlphaSort);

	if(fileCount >= 0)
	{
	int i;
		if(column > lastColumn)
			lastColumn = column;
		if(nameList[column])
			for(i = 0; i < nameCount[column]; i ++)
				free(nameList[column][i]);
		nameList[column] = newList;
		nameCount[column] = fileCount;
	}

	return fileCount;
}

/* Lazy creation of the browser items */
 - browser : sender loadCell : cell atRow : (int)row inColumn : (int)column
{
struct stat fileInfo;
char fullPathname[MAXPATHLEN];

	if(column > 0)
	{
		[sender getPath : path toColumn : column];
		sprintf(fullPathname,"%s/%s",path,nameList[column][row]->d_name);
	}
	else
		sprintf(fullPathname,"/%s",nameList[column][row]->d_name);

	/* A check to see if this file exits, and it should */
	if(stat(fullPathname,&fileInfo) != 0)
	{
		perror(fullPathname);
		NXBeep();
		printf("col = %d\n",column);
		return self;
	}

	[cell setLoaded : YES];
	[cell setStringValue : nameList[column][row]->d_name];
	if( fileInfo.st_mode & S_IFDIR)	/* A directory file */
		[cell setLeaf : NO];
	else if(dirFlag == YES)
	{								/* Disable normal files */
		[cell setLeaf : YES];
		[cell setEnabled: NO];
	}
	else
		[cell setLeaf : YES];

	return self;
}

- getSelectionPath
{
int column;
id matrix;
struct stat fileInfo;

	column = [browser selectedColumn];
	[browser getPath : path toColumn : column];
	matrix = [browser matrixInColumn : column];
	sprintf(pathName,"%s/%s",path,[[matrix selectedCell] stringValue]);
	/* See if the file is a directory */
	isDirectory = NO;
	if(stat(pathName,&fileInfo) != 0)
		perror(pathName);
	if(fileInfo.st_mode & S_IFDIR)
	{	/* A directory file */
		isDirectory = YES;
		if(dirFlag == YES)	/* Display it if directory selection is allowed */
			[form setStringValue : [[matrix selectedCell] stringValue] at : 0];
	}
	else
		[form setStringValue : [[matrix selectedCell] stringValue] at : 0];
	[form selectTextAt: 0];

	return self;
}

/* Form's text delegate methods */
- (BOOL) textWillEnd : sender
{
int length,column;
char subdirName[128];
struct stat fileInfo;

NXLogError("textWillEnd_0: %s\n",pathName);
	length = [sender textLength];
	if(length > 0)
		[sender getSubstring: subdirName start: 0 length: 127];
	else
		return YES;

	subdirName[128] = '\0';

NXLogError("textWillEnd_1: %s/%s\n",pathName, subdirName);
	column = [browser selectedColumn];
	[browser getPath : path toColumn : column];
	sprintf(pathName,"%s/%s",path, subdirName);
	/* Check the path to make sure that what the user typed is valid */
	if(stat(pathName,&fileInfo) != 0)
	{
NXLogError("textWillEnd_1: %s/%s\n",pathName, subdirName);
		/* See if the user tried to specify a full pathname */
		if(stat(subdirName,&fileInfo) != 0)
			return YES;
		strcpy(pathName, subdirName);
	}
	return NO;
}

#ifdef FILE_COMPLETION
- textDidGetKeys: sender isEmpty: (BOOL)flag
{
char name[32],*cellName;
int count;
	fprintf(stderr,"length = %d\n",[sender getSubstring: name start: 0 length: 128]);
	sprintf(completedPath,"%s/%s",pathName,name);
	count = NXCompleteFilename(completedPath, MAXPATHLEN);
	cellName = strrchr(completedPath,'/');
	if(count == 0 || flag == YES)
	{
		completionName = NULL;
		[okButton setEnabled: NO];
		return self;
	}
	completionName = ++cellName;
fprintf(stderr,"textDidGetKeys: partial = %s; count = %d", completedPath,count);
	if(cellName[1] != '\0' && count > 0)
		[browser setPath: completedPath];
	return self;
}

- (BOOL)browser:sender selectCell:(const char *)entry inColumn:(int)column
{
id cell,matrix;
int row;
fprintf(stderr,"selectCell: %s\n",entry);
	row = 0;
	cell = [browser getLoadedCellAtRow: row inColumn: column];
	while( cell != nil && strcmp([cell stringValue],entry) != 0)
	{
		cell = [sender getLoadedCellAtRow: ++row inColumn: column];
	}
	if(cell == nil)
		return NO;
		
	matrix = [browser matrixInColumn: column];
	[matrix selectCellAt: row : 0];
	
	if(completionName != NULL && strcmp(completionName,entry) == 0)
		return NO;

	return YES;
}
#endif

@end
