#import "SearchAndReplace.h"
#import <sys/types.h>
#import <sys/stat.h>

@implementation SearchAndReplace

- appDidInit:sender
{
	if ((homeDir = getenv("HOME")) == NULL)
		printf("Error: could not find home directory!");
	else {
		strcpy(fullFilename,homeDir);
		[directoryText setStringValue:homeDir];
		strcpy(backupsDirectory,homeDir);
		[backupsDirectoryText setStringValue:homeDir];
	}
	return self;
}

- execute:sender
{	int			selection,
				extensionCount,
				changedDirectoryCount,
				i;
	char			unixCommand[1024],
				currentPathAndFile[256],
				currentDirectory[256],
				textLine[256],
				tempFileName1[256],
				tempFileName2[256],
				tempFileName3[256],
				filterName[256],
				fromString[128],
				toString[128],
				lastChar,
				*lastCharPointer,
				*temp1,
				temp4[4],
				*currentExt,
				extension[20][32],
				*changedDirectory[1000],
				tempDirectory[256],
				newFileName[256],
				newPathAndFile[256];
	FILE			*f;
	BOOL		excludeChosen,
				excludeCurrent,
				matched;
	struct stat 	buf;

	changedDirectoryCount = 0;
	excludeChosen = (BOOL)[[includeExcludeRadio selectedCell] tag];
	extensionCount = 0;
	for (i=0; i<[extensionForm cellCount]; i++) {
		strcpy(extension[extensionCount],[[extensionForm cellAt:i:0] stringValue]);
		if (strlen(extension[extensionCount]) > 0)
			extensionCount++;
	}
	selection = NXRunAlertPanel("Warning:","Performing this operation could cause irreversible damage to the ENTIRE subtree you have chosen (including any linked directories).  Do you still want to execute this operation?", "Execute","Cancel",NULL);
	if ((selection == NX_ALERTDEFAULT) && (homeDir != NULL)){
		strcpy(currentDirectory, fullFilename);
		strcpy(fromString,[searchStringForm stringValueAt:0]);
		strcpy(toString,[searchStringForm stringValueAt:1]);
		sprintf(tempFileName1,"%s/#SAR.temp1#",homeDir);
		sprintf(tempFileName2,"%s/#SAR.temp2#",homeDir);
		sprintf(tempFileName3,"%s/#SAR.temp3#",homeDir);
		sprintf(filterName,"%s/Filter.o",[[NXBundle mainBundle] directory]);
		strcpy(temp4,"");
		if ([[operationSwitch cellAt:2:0] intValue])
			strcpy(temp4,"R");
		sprintf(unixCommand,"ls -%sFa %s > %s",temp4,fullFilename,tempFileName1);
		system(unixCommand);
		f = fopen(tempFileName1,"r");
		fscanf(f,"%s[^\n]\n",textLine);
		while (!feof(f)) {
			lastCharPointer = textLine + strlen(textLine) - 1;
			lastChar = textLine[strlen(textLine)-1];
			if (lastChar == ':') {
				strncpy(currentDirectory,textLine,strlen(textLine)-1);
				currentDirectory[strlen(textLine)-1] = '\0';
				excludeCurrent = YES;
				for (i=0; i<changedDirectoryCount; i++)
					if (strncmp(currentDirectory,changedDirectory[i],strlen(changedDirectory[i])) == 0) {
						strcpy(tempDirectory,currentDirectory);
						temp1 = tempDirectory + (rindex(changedDirectory[i],'/') - changedDirectory[i]);
						*temp1 = '\0';
						temp1++;
						[self renameFile:temp1 searchFor:fromString replaceWith:toString];
						sprintf(currentDirectory,"%s/%s",tempDirectory,temp1);
					}
			}
			else {
				if ((lastChar == '/') || (lastChar == '@') || (lastChar == '*') || (lastChar == '='))					*lastCharPointer = '\0';
				excludeCurrent = !excludeChosen;
				if (currentExt = rindex(textLine,'.')) {
					currentExt++;
					matched = NO;
					for (i=0; i<extensionCount; i++)
						if (strcmp(currentExt,extension[i]) == 0)
							matched = YES;
					if (matched)
						excludeCurrent = excludeChosen;
				}
				sprintf(currentPathAndFile,"%s/%s",currentDirectory,textLine);
			}
			if ((!excludeCurrent) && (textLine[0] != '.')) {
				if (([[operationSwitch cellAt:1:0] intValue]) && (lastChar != '/') && (lastChar != '@') &&
						(lastChar != '=')) {
					sprintf(unixCommand,"grep \"%s\" %s > %s", fromString, currentPathAndFile,
							tempFileName3);
					system(unixCommand);
					stat(tempFileName3, &buf);
					if (buf.st_size > 0) {
						if ([[operationSwitch cellAt:3:0] intValue]) {
							sprintf(unixCommand,"cp %s %s/%s",currentPathAndFile,
									backupsDirectory,textLine);
							system(unixCommand);
						}
						sprintf(unixCommand,"cat %s | %s | sed 's/%s/%s/g' > %s; mv %s %s",
								currentPathAndFile,filterName,fromString,toString,
								tempFileName2,tempFileName2,currentPathAndFile);
						system(unixCommand);
						printf("Search and Replace: Modifying file -- %s\n", currentPathAndFile);
					}
				}
				if (([[operationSwitch cellAt:0:0] intValue])) {
					strcpy(newFileName,textLine);
					if ([self renameFile:newFileName searchFor:fromString replaceWith:toString]) {
						sprintf(newPathAndFile,"%s/%s",currentDirectory,newFileName);
						sprintf(unixCommand,"mv %s %s",currentPathAndFile,newPathAndFile);
						system(unixCommand);
						printf("Search and Replace: Renaming file -- %s\n", currentPathAndFile);
						if (lastChar == '/') {
							changedDirectory[changedDirectoryCount] = 
									(char *)malloc(256 * sizeof(char));
							strcpy(changedDirectory[changedDirectoryCount],currentPathAndFile);
							changedDirectoryCount++;
						}
					}
				}
			}
			[filenameText setStringValue:currentPathAndFile];
			fscanf(f,"%s[^\n]\n",textLine);
		}
		fclose(f);
		sprintf(unixCommand,"rm %s; rm %s; rm %s",tempFileName1,tempFileName2,tempFileName3);
		system(unixCommand);
	}
	for (i=0; i<changedDirectoryCount; i++)
		free(changedDirectory[i]);
	return self;
}

- (BOOL)renameFile:(char *)aName searchFor:(char *)searchString replaceWith:(char *)replaceString
{	char			*temp1,
				temp2[256],
				*temp3;
			
	strcpy(temp2,aName);
	if (temp1 = strstr(temp2,searchString)) {
		temp3 = temp1 + strlen(searchString);
		*temp1 = '\0';
		sprintf(aName,"%s%s%s",temp2,replaceString,temp3);
		return YES;
	}
	else
		return NO;				
}

- setBackupsDirectory:sender
{	char		filename[64],
			path[256];

	strcpy(filename,"");
	strcpy(path, backupsDirectory);
	if (getOpenFilenameAndPath(filename,path,NULL)) {
		sprintf(backupsDirectory,"%s/%s",path,filename);
		[backupsDirectoryText setStringValue:backupsDirectory];
	}
	return self;
}

- setDirectory:sender
{	char		filename[64],
			path[256];

	strcpy(filename,"");
	strcpy(path,fullFilename);
	if (getOpenFilenameAndPath(filename,path,NULL)) {
		sprintf(fullFilename,"%s/%s",path,filename);
		[directoryText setStringValue:fullFilename];
	}
	return self;
}

@end
