/* CEAppManager.m				 
 *
 * This is the basic controller of the App. It manages all big abstraction
 * tasks for the panels, documents and connections to the outside.
 *
 * For interface-info see the header file. The comments in this file mostly
 * cover only the real implementation details.
 *
 * Written by: 		Thomas Engel
 * Created:    		23.10.1993 (Copyleft)
 * Last modified: 	07.05.1994
 */

#import "CNAppManager.h"
#import "Text_more.h"
#import "Application_ext.h"
#import <misckit/MiscString.h>
#import <misckit/MiscTime.h>
#import <misckit/MiscAppDefaults.h>
#import <misckit/MiscAppExtensions.h>


@implementation CNAppManager

- appWillInit:sender
{
	// This is the init part we need to pass before we get the messages that
	// we have to open some files.
	// To be able to init a class we need the have the Preferences,

	// preferences = [CNPreferencesManager new];

	tempPb = [Pasteboard newName:"CNTempPb"];
	_notesLoaded = NO;
	newPastes = 0;
	[newPasteCountField setIntValue:newPastes];

	[notesWindow setFrameAutosaveName:"NotesWindow"];
	_firstActivation = YES;

	[self openDefaults];
	return self;
}

- appDidInit:sender
{
	// This is some kind of late init. These object are need for working but
	// not for reading the classes or having a class initialized.


	[[NXApp appListener] setServicesDelegate:self];	
	// Opening with nil won't cause the window to open if it should not..

	[self open:nil];
	[notesWindow setMiniwindowImage:[NXImage findImageNamed:"NoteIcon"]];
	return self;
}

- (int)app:sender openFile:(const char *)path type:(const char *)type
{
	// This method is performed whenever a user opens a document from the
	// Workspace Manager.
	// We use our default file open method with some default params.
	
	return NO;
}

- (BOOL)appAcceptsAnotherFile:sender
{
	// Inform the workspace that we can open multiple files.
	return NO;
}

- appDidBecomeActive:sender
{
	if( _firstActivation )
	{		
		_firstActivation = NO;
		if( [NXApp didAutolaunch] )
		{
			[NXApp hide:self];
			return self;
		}
	}
	[notesWindow makeKeyAndOrderFront:self];
	return self;
}

- appWillTerminate:sender
{
	// Now lets see what we have...ask every window what is going on.

	BOOL	ready;
	int	result;

	if( !_isEscaping )
	{
		[self save:self];
		[self saveDefaults];	
	}
	else
	{
		ready = NO;
		while( !ready )
		{
			result = NXRunAlertPanel( "Quit", "There are usaved notes.", 
								"Review Notes", "Quit Anyway", "Cancel" );

			if( result == NX_ALERTOTHER )
				return nil;
	
			ready = YES;

			if( result == NX_ALERTDEFAULT )
				[notesWindow makeKeyAndOrderFront:self];
		}
	}

	return self;
}

- app:sender powerOffIn:(int)ms andSave:(int)aFlag
{	
	// Now we might not be on the save side here !!
	// There is no guarateen to write the data down fast enough.
	// BUG: We should extend power off time here but seems like it is working.

	[self save:self];
	[self saveDefaults];
	return self;
}

- powerOff:(NXEvent *)theEvent
{	
	// Now we might not be on the save side here !!
	// There is no guarateen to write the data down fast enough.
	// We can't extend power off time here.

	[self save:self];
	[self saveDefaults];
	return self;
}

- showInfo:sender
{
	return self;
}

- showPreferences:sender
{
	return self;
}

- preferences
{
	return self;
}

- openDefaults
{
	id	aPath;

	// Well now this is a little rough....maybe we should search for the files
	// inside the ~/.AppInfo or even *Library/ClassEditor sections..anyway.	
	// Now the Text-object has a bug that prevendts us from usign the prede-
	// dinfen Template that is inside the preferences NIB part.
	// So we have to load it from the appp bundle.

	aPath = [MiscString newWithString:"~/Library/ClipNotes/NoteTemplate.rtfd"];
	[aPath replaceTildeWithHome];
	if( [aPath doesExistInFileSystem] )
		[notesTemplateText openRTFDFrom:[aPath stringValue]];
	
	else
	{
		[aPath setStringValue:"/LocalLibrary/ClipNotes/NoteTemplate.rtfd"];
		[aPath cat:"/NoteTemplate.rtfd"];
		if( [aPath doesExistInFileSystem] )
			[notesTemplateText openRTFDFrom:[aPath stringValue]];

		else
		{
			[aPath setStringValue:[NXApp appDirectory]];
			[aPath cat:"/NoteTemplate.rtfd"];
			if( [aPath doesExistInFileSystem] )
				[notesTemplateText openRTFDFrom:[aPath stringValue]];
		}
	}
	[aPath free];

	[notesWindow setFrameUsingName:[notesWindow frameAutosaveName]];

	// Now lets get the other..simpler defaults..
	
	if( [NXApp knowsDefaultValue:"EnableService"] )
		[enableServicesSwitch setState:
							[NXApp defaultBoolValue:"EnableService"]];

	if( [NXApp knowsDefaultValue:"SaveWithBackup"] )
		[saveWithBackupSwitch setState:
							[NXApp defaultBoolValue:"SaveWithBackup"]];

	if( [NXApp knowsDefaultValue:"ClipNotesPath"] )
		[notesPathField setStringValue:[NXApp defaultValue:"ClipNotesPath"]];

	if( [NXApp knowsDefaultValue:"ReplaceSelection"] )
		[replaceSelectionSwitch setState:
							[NXApp defaultBoolValue:"ReplaceSelection"]];

	if( [NXApp knowsDefaultValue:"InsertPosition"] )
		[notesCreationModeSwitch selectCellWithTag:
							[NXApp defaultIntValue:"InsertPosition"]];

	if( [NXApp knowsDefaultValue:"Timeformat"] )
		[timeFormatField setStringValue:[NXApp defaultValue:"Timeformat"]];

	if( [NXApp knowsDefaultValue:"Dateformat"] )
		[dateFormatField setStringValue:[NXApp defaultValue:"Dateformat"]];


	return self;
}

- saveDefaults
{
	// Write down the defaults. 

	id	aPath;

	if( _templateChanged )
	{
		aPath = [MiscString newWithString:
								"~/Library/ClipNotes/NoteTemplate.rtfd"];
		
		[aPath replaceTildeWithHome];
		[notesTemplateText saveRTFDTo:[aPath stringValue]
						  removeBackup:YES errorHandler:nil];
		[aPath free];
		_templateChanged = NO;
	}

	// Now lets get the other..simpler defaults..
	
	[NXApp setDefault:"EnableService" toBool:[enableServicesSwitch state]];
	[NXApp setDefault:"SaveWithBackup" toBool:[saveWithBackupSwitch state]];
	[NXApp setDefault:"ClipNotesPath" to:[notesPathField stringValue]];
	[NXApp setDefault:"ReplaceSelection" toBool:
									[replaceSelectionSwitch state]];
	[NXApp setDefault:"InsertPosition" toInt:
						[[notesCreationModeSwitch selectedCell] tag]];
	[NXApp setDefault:"Timeformat" to:[timeFormatField stringValue]];
	[NXApp setDefault:"Dateformat" to:[dateFormatField stringValue]];

	return self;
}

- new:sender
{
	// All we do here is to put some default on the clip area.
	// Well by default we wnat to see the notes in this case...

	[self open:self];
	[tempNoteText selectAll:self];
	[tempNoteText replaceSel:"My Note:"];
	[self _pasteIt];
	
	return self;
}

- open:sender
{
	id	path;
	
	// If the document was edited we should ask first !

	if( _notesLoaded == NO )
	{
		path = [[MiscString alloc] initDirectory:[notesPathField stringValue]
								file:"ClipNotes.rtfd"];
		[path replaceTildeWithHome];
		[notesText openRTFDFrom:[path stringValue]];

		[path free];
		_notesLoaded = YES;
	}

	// If the notes are loaded we asume that this was triggered by the menu
	// item and the user wants to see the entries. So just show the window.
	// If the sender is nil we won't bring up the

	else if( _notesLoaded || sender != nil )
		[notesWindow makeKeyAndOrderFront:self];

  	return self;
}

- save:sender
{
	id	path;
	BOOL	removeBackup;

	if( [notesWindow isDocEdited] == NO ) return self;

	// Now lets see if we need a backup or not..

	removeBackup = NO;
	if( [saveWithBackupSwitch state] == NO ) removeBackup = YES;

	path = [[MiscString alloc] initDirectory:[notesPathField stringValue]
							file:"ClipNotes.rtfd"];
	[path replaceTildeWithHome];
	[notesText saveRTFDTo:[path stringValue] removeBackup:removeBackup 
			errorHandler:nil];

	[path free];


	newPastes = 0;
	[newPasteCountField setIntValue:newPastes];
	[notesWindow setDocEdited:NO];

	// Well somehow the notes are loaded now...at least the stored don't
	// differ from what we have.

	_notesLoaded = YES;

	return self;
}

- revert:sender
{
	if( [notesWindow isDocEdited] == NO ) return [self open:self];

	// Oh...there really is something to revert...not only topping the
	// windows.

	if( NXRunAlertPanel( "Revert", 
				"Do you want the revert changes to the saved ClipNotes?", 
				"Revert", "Cancel", NULL ) == NX_ALERTDEFAULT )
	{
		_notesLoaded = NO;
		[self open:self];
	}
	return self;
}

- print:sender
{
	[notesText printPSCode:sender];
	return self;
}

- escape:sender
{
	_isEscaping = YES;
	[NXApp terminate:self];
	return self;
}

- copyNotesTemplate
{
	// All we do here is to copy the docu template to the pasteboard.
	// Will corrupt the pasteboard !

	[notesTemplateText selectAll:self];
	[notesTemplateText copyTo:tempPb];
	[composeText selectAll:self];
	[composeText pasteFrom:tempPb];
	[notesTemplateText selectNull];

	return self;
}

- pasteAsNote:sender
{
	// All we do here is to paste the current pasteboard contents into the
	// temp area and trigger a notes pasting operation (_pasteIt )

	[tempNoteText selectAll:self];
	[tempNoteText paste:self];
	[self _pasteIt];
	
	return self;
}

- _pasteIt
{
	// We will paste the text that is inside the tempArea.

	id	aTime;

	[self copyNotesTemplate];

	// Now lets update the stuff that is inside the compose area to
	// match our needs.

	[composeText setSel:0 :0];
	if( [composeText findText:"<App>" 
					ignoreCase:NO backwards:NO wrap:NO] )
	{
		if( [NXApp isActive] )
			[composeText replaceSel:"Pasteboard"];
		else	[composeText replaceSel:"SomeApp"];
	}

	[composeText setSel:0 :0];
	if( [composeText findText:"<Time>" 
					ignoreCase:NO backwards:NO wrap:NO] )
	{
		aTime = [[MiscTime alloc] initWithCurrentTime];
		[composeText replaceSel:[aTime format:[timeFormatField stringValue]]];
		[aTime free];
	}
	
	[composeText setSel:0 :0];
	if( [composeText findText:"<Date>" 
					ignoreCase:NO backwards:NO wrap:NO] )
	{
		aTime = [[MiscTime alloc] initWithCurrentTime];
		[composeText replaceSel:[aTime format:[dateFormatField stringValue]]];
		[aTime free];
	}

	[tempNoteText selectAll:self];
	[tempNoteText copyTo:tempPb];
	[composeText setSel:0 :0];
	if( [composeText findText:"<Note>" 
					ignoreCase:NO backwards:NO wrap:NO] )
		[composeText pasteFrom:tempPb];

	[composeText selectAll:self];
	[composeText copyTo:tempPb];
	
	// Now depending on where we should paste the note we will set our 
	// position.
	
	if( [replaceSelectionSwitch state] == NO ||
	    [notesText hasEmptySelection] )
	{
		if( [[notesCreationModeSwitch selectedCell] tag] == 1 )
				[notesText setSel:0 :0];
		else		[notesText setSel:[notesText textLength]
							    :[notesText textLength]];
	}
	[notesText pasteFrom:tempPb];

	// In every case we will deselect it all afterwards. This way we can 
	// prevent a replaceSelection setting to remove all our last clips. !

	[notesText setSel:0 :0];

	newPastes++;
	[newPasteCountField setIntValue:newPastes];
	[notesWindow setDocEdited:YES];

	return self;
}

- note:(id)pb userData:(const char *)udata error:(char **)ermsg
{
	[tempNoteText selectAll:self];
	[tempNoteText pasteFrom:pb];
	[self _pasteIt];
	return self;
}

- textDidChange:sender
{
	if( sender == notesTemplateText ) _templateChanged = YES;

	else if( sender == notesText ) [notesWindow setDocEdited:YES];
	return self;
}

@end

/*
 * History: 13.01.95 Bla.
 *
 *
 * Bugs: No bugs and birds seen....
 */