#import "Controller.h"
#import "DragView.h"
#import "String.h"

@implementation Controller

- focusToTex
{
    [theWindow makeFirstResponder:texView];
	return self;
}

 - appDidInit:sender
{
	char path[MAXPATHLEN];
	const char *scriptFlag, *appName = [NXApp appName];

	static NXDefaultsVector theDefaults =
		{
			{"Script", "Original"},
			{NULL, NULL}
		};
	NXRegisterDefaults(appName, theDefaults);
	
	// Check for tex2eps.bat in the bundlepath
	if (! [[NXBundle mainBundle]
		getPath: path forResource: "tex2eps.bat" ofType: ""]) {
		[self showError: "Can't find tex2eps.bat!"];
		[NXApp terminate: self];
		return nil;
	}
	bundlepath = [[[String alloc] init] setString: path];
	
	// Setup the splitviev and delegation
	[splitView addSubview: theDragView];
	[splitView addSubview: texView];
	[splitView display];
	[theWindow setDelegate:self];
	[[texView docView] setDelegate:self];
	
    // Focus in the texview
    [self focusToTex];
	[[[theWindow setTitle:"Untitled"] display] makeKeyAndOrderFront:self];

	// Show introduction eps image and script window text
	[theDragView setImage:[[NXImage alloc] initFromSection:"tex2eps.eps"]];
	
	// Setup Preferences stuff
	scriptFlag = NXGetDefaultValue(appName, "Script");
	if (scriptFlag)
	{
		if (strcasecmp(scriptFlag, "Original") == 0)
			[scriptRadioButton selectCellWithTag:0];
		else
			[scriptRadioButton selectCellWithTag:1];
	}
	
	// Setup the userlib, usertmp and save paths 
    userlib  = [[[String alloc] init] setString: NXHomeDirectory()];
	usertmp  = [userlib copy];
	[userlib cat: "/Library/Tex2Eps"];
	[usertmp  cat:"/Tex2Eps_tmp"];
	savepath = [userlib copy];
              
	// Create the needed directories
	system("mkdirs ~/Library/Tex2Eps");
	system("mkdirs ~/Tex2Eps_tmp");
	[NXApp setAutoupdate: YES];
	return self;
}

- setScript:sender
{
	const char *appName = [NXApp appName];
	switch ([[scriptRadioButton selectedCell] tag])
	{
		case 0:	NXWriteDefault(appName, "Script", "Original");
				break;
		case 1:	NXWriteDefault(appName, "Script", "Customized");
				break;
	}
	return self;
}

- (BOOL)whichScript
{
	const char *scriptFlag;
	const char *appName = [NXApp appName];

	// The value in the database may be newer than the value in the 
	// registration table because of the Prefs panel; thus, update 
	// the value in the table to match the value in the database.
	NXUpdateDefault(appName, "Script");
	
	// Get value from registration table now that it's been updated.
	scriptFlag = NXGetDefaultValue(appName, "Script");
	
	// Make sure scriptFlag is not NULL before comparing it.
	if (scriptFlag)
	{
		if (strcasecmp(scriptFlag, "Original") == 0)
			return TRUE;
	}
	return FALSE;
}


- latexCompile:sender
{
	NXStream *stream = NULL;
	id sfile, ifile, bpath;
	
	
    // Check for latex input, if OK write to file and run formel2eps.bat
    if ([[texView docView] textLength] == 0)
      {
        [self showError:"Fill some latex code in the field above!"];
        return self;
      }
	
	sfile = [usertmp copy]; [sfile cat: "/tex2eps.tex"];
	
	if (stream = (NXOpenMemory(NULL, 0, NX_WRITEONLY)))
	{
    	[[texView docView] writeText: stream];
		if (NXSaveToFile(stream, [sfile stringValue]) != 0)
		{
			[self showError: "Can't save file"];
			NXCloseMemory(stream, NX_FREEBUFFER);
		}
		else
			NXCloseMemory(stream, NX_FREEBUFFER);
	}
	else
	{
		[self showError: "Can't open stream memory file"];
		return nil;
	}
			
  	// Setup the bundle path for the formel2eps.bat script and call it
  	if ([self whichScript] == TRUE)
		system([bundlepath stringValue]);
	else {
		bpath = [userlib copy]; [bpath cat: "/tex2eps.bat"];
    	system([bpath stringValue]);
	}

    // Setup the eps image file and show the image.

	ifile = [usertmp copy]; [ifile cat: "/tex2eps.eps"];
    [theDragView setImage:[[NXImage alloc] 
			initFromFile: [ifile stringValue]]];

    // Focus again in the texinput
    [self focusToTex];

    return self;
}

- load:sender
{
    const char *fileName;
    const char *const types[2] = {"tex", NULL};

	id op = [OpenPanel new];
    if ([op runModalForTypes:types] && (fileName = [op filename]))
		[self openFile:fileName];
    else
		[self showError: "No file chosen or could not open file."];
    return self;

    [self focusToTex];
    return self;
}

- openFile:(const char *)fileName
{
	NXStream *stream;
   	
	if (stream = (NXMapFile(fileName, NX_READONLY)))
	{
    	[[texView docView] readText: stream];
		[theWindow setTitle:fileName];
		NXCloseMemory(stream, NX_FREEBUFFER);
		return self;
	}
	else
	{
		[self showError: "Can't open file!"];
		return nil;
	}
}

- save:sender
{
    const char *fileName;
    const char *const types[2] = {"tex", NULL};
	id sp = [SavePanel new];
    [sp setRequiredFileType: types[0]];
	
	// Check to see if the current window is titled and the title is not
	// "Untitled". If so, save the file, else put up a save panel...
	
	fileName = [theWindow title];
	if (strcmp (fileName, "Untitled"))
	    [self saveFile: fileName];
	else
		[self saveAs: self];
    
    [self focusToTex];
    return self;
}

- saveAs:sender
{
    const char *fileName;
    const char *const types[2] = {"tex", NULL};
	id sp = [SavePanel new];
    [sp setRequiredFileType: types[0]];
	
	// Get a file name from the user; use title of the window as default.
	if (([sp runModalForDirectory: "."
		 file:[theWindow title]]) && (fileName = [sp filename])) 
	    [self saveFile: fileName];
    
    [self focusToTex];
    return self;
}

- saveFile: (const char *)name
{	
    NXStream *stream;
    
   	if (stream = (NXOpenMemory(NULL, 0, NX_WRITEONLY)))
	{
    	[[texView docView] writeText: stream];
		if (NXSaveToFile(stream, name) != 0)
		{
			[self showError: "Can't save file"];
			NXCloseMemory(stream, NX_FREEBUFFER);
			return nil;
		}
		else
		{
			[theWindow setTitle:name];
			[theWindow setDocEdited:NO];
			NXCloseMemory(stream, NX_FREEBUFFER);
		}
	}
	else
	{
		[self showError: "Can't open stream memory for file saving..."];
		return nil;
	}
    return self;
}

- revertFormatWindow:sender
{
	NXStream *stream;

	// Remove the tex2eps.bat script in ~/Library/Tex2Eps/
	
	system("rm -f ~/Library/Tex2Eps/tex2eps.bat");

  	// Setup the bundle path for the main formel2eps.bat script and load it
	
	if (stream = (NXMapFile([bundlepath stringValue], NX_READONLY)))
	{
    	[[formatScript docView] readText: stream];
		[formatWindow setTitle:[bundlepath stringValue]];
		NXCloseMemory(stream, NX_FREEBUFFER);
		return self;
	}
	else
	{
		[self showError: "Can't open file!"];
		return nil;
	}
	
    [self focusToTex];
    return self;
}

- customFormatWindow:sender
{
	NXStream *stream;
	id customfile;
	
	customfile = [userlib copy]; [customfile cat: "/tex2eps.bat"];

  	// Setup the bundle path for the custom formel2eps.bat script and load it
	
	if (stream = (NXMapFile([customfile stringValue], NX_READONLY)))
	{
    	[[formatScript docView] readText: stream];
		[formatWindow setTitle:[customfile stringValue]];
		NXCloseMemory(stream, NX_FREEBUFFER);
		return self;
	}
	else
	{
		[self showError: "Can't open file!"];
		return nil;
	}
	
    [self focusToTex];
    return self;
}

- saveFormatWindow:sender
{
	NXStream *stream;
	id scriptfile;
	
	scriptfile = [userlib copy]; [scriptfile cat: "/tex2eps.bat"];
	
	if (stream = (NXOpenMemory(NULL, 0, NX_WRITEONLY)))
	{
    	[[formatScript docView] writeText: stream];
		if (NXSaveToFile(stream, [scriptfile stringValue]) != 0)
		{
			[self showError: "Can't save file"];
			NXCloseMemory(stream, NX_FREEBUFFER);
		}
		else
		{
			NXCloseMemory(stream, NX_FREEBUFFER);
			[formatWindow setTitle:[scriptfile stringValue]];
			[formatWindow setDocEdited:NO];
			// Do a chmod +x on tex2eps.bat
    		system("chmod +x ~/Library/Tex2Eps/tex2eps.bat");
		}
	}
	else
	{
		[self showError: "Can't open stream memory file"];
		return nil;
	}
    [self focusToTex];
    return self;
}

- showFormatWindow:sender
{
    if (!formatWindow) {
        [NXApp loadNibSection:"Format.nib" owner: self withNames: NO];
    }
	[formatWindow setDelegate:self];
	[[formatScript docView] setDelegate:self];
	[[[formatWindow setTitle:"Script Window"] display] 	
			makeKeyAndOrderFront:self];
    return self;
}

- showInfoPanel:sender
{
	if (! infoPanel)
		[NXApp loadNibSection:"Info.nib" owner: self withNames: NO];
	[infoPanel makeKeyAndOrderFront:self];
    return self;
}

- showError: (const char*) errorMessage
{
	NXRunAlertPanel (NULL, errorMessage, "OK", NULL, NULL);
	return self;
}

// textDidGetKeys: is called every time a key is pressed
// if the window is marked dirty, we don't do anything 
// -- if it's not dirty, we set it to dirty

- textDidGetKeys:sender isEmpty:(BOOL)flag
{
	if ([theWindow isMainWindow])
	{
		// if theWindow is not dirty, then set it to dirty
		if ([theWindow isDocEdited] == NO)
			[theWindow setDocEdited:YES];
	}
	else
	{
		// if formatWindow is not dirty, then set it to dirty
		if ([formatWindow isDocEdited] == NO)
			[formatWindow setDocEdited:YES];
	}
	return self;
}

-(BOOL) appAcceptsAnotherFile:sender
{
	return (YES);
}

- appOpenFile:(char *)fileName type:(char *)fileType
{
    return [self openFile:fileName];  
}

- windowWillClose:sender
{
	int result;
	
	// display alert panel only if window is marked dirty
	if ([theWindow isMainWindow])
	{
		if ([theWindow isDocEdited]) {
			result = NXRunAlertPanel
				([NXApp appName],
				"Unsaved changes. Close Anyway?\n",
				"Save",
				"Close anyway",
				"Cancel");
	
			switch(result) {
				case NX_ALERTDEFAULT:
					if ([theWindow isMainWindow])
						return [self save: self];
					break;
				case NX_ALERTALTERNATE:
					return self;
				case NX_ALERTOTHER:
					return nil;
			}
		}
	}
	if ([formatWindow isMainWindow])
	{
		if ([formatWindow isDocEdited]) {
			result = NXRunAlertPanel
				([NXApp appName],
				"Unsaved changes. Close Anyway?\n",
				"Save",
				"Close anyway",
				"Cancel");
	
			switch(result) {
				case NX_ALERTDEFAULT:
					if ([formatWindow isMainWindow])
						return [self saveFormatWindow: self];
					break;
				case NX_ALERTALTERNATE:
					return self;
				case NX_ALERTOTHER:
					return nil;
			}
		}
	}
	return self;
}

- appWillTerminate:sender
{	
	if (([theWindow isDocEdited]) || [formatWindow isDocEdited]) {
		int q = NXRunAlertPanel("Quit",
						"There are edited windows.",
						"Review Unsaved", 
						"Quit Anyway", "Cancel");
		if (q==1) {								/* Review */
			[theWindow performClose:nil];
			[formatWindow performClose:nil];
			system("rm -f -r ~/Tex2Eps_tmp");
			return self;
		}
		if (q==-1) {							/* cancel */
			return nil;
		}
	}
	// Remove the ~/Tex2Eps_tmp directory and its contents
  	system("rm -f -r ~/Tex2Eps_tmp");
	return self;								/* quit */		
}

@end
