/*
 *  R.app : a Cocoa front end to: "R A Computer Language for Statistical Data Analysis"
 *  
 *  R.app Copyright notes:
 *                     Copyright (C) 2004-5  The R Foundation
 *                     written by Stefano M. Iacus and Simon Urbanek
 *
 *                  
 *  R Copyright notes:
 *                     Copyright (C) 1995-1996   Robert Gentleman and Ross Ihaka
 *                     Copyright (C) 1998-2001   The R Development Core Team
 *                     Copyright (C) 2002-2004   The R Foundation
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  A copy of the GNU General Public License is available via WWW at
 *  http://www.gnu.org/copyleft/gpl.html.  You can also obtain it by
 *  writing to the Free Software Foundation, Inc., 59 Temple Place,
 *  Suite 330, Boston, MA  02111-1307  USA.
 */


#import "RGUI.h"
#import "RDocument.h"
#import "RDocumentController.h"
#import "RDocumentWinCtrl.h"
#import "RController.h"
#import "Preferences.h"

@implementation RDocument

- (id)init
{
    self = [super init];
    if (self) {
		SLog(@"RDocument(%@) init", self);
		initialContents=nil;
		initialContentsType=nil;
		isEditable=YES;
		isREdit=NO;
		myWinCtrl=nil;
    }
    return self;
}

- (void)close {
	SLog(@"RDocument.close <%@> (wctrl=%@)", self, myWinCtrl);
	if (initialContents) [initialContents release];
	initialContents=nil;
	if (initialContentsType) [initialContentsType release];
	initialContentsType=nil;
	if (myWinCtrl) {
		SLog(@" - window: %@", [myWinCtrl window]);
		[self removeWindowController:myWinCtrl];
		[myWinCtrl close];
		// --- something is broken - winctrl close doesn't work - I have no idea why - this is a horrible hack to cover up
		NSWindow *w = [myWinCtrl window];
		if (w) [NSApp removeWindowsItem: w];
		[[(RDocumentController*)[NSDocumentController sharedDocumentController] walkKeyListBack] makeKeyAndOrderFront:self];
		// --- end of hack
		[myWinCtrl release];
		myWinCtrl=nil;
	}
	[super close];
}

- (void)dealloc {
	if (myWinCtrl) [self close];
	[super dealloc];
}

// FIXME: I don't like this - we should use common text storage instead; conceptually textView is NOT the storage part
- (NSTextView *)textView {
	return [myWinCtrl textView];
}

- (void) makeWindowControllers {
	SLog(@"RDocument.makeWindowControllers: creating RDocumentWinCtrl");
	if (myWinCtrl) {
		SLog(@"*** RDocument.makeWindowControllers: my assumption is that I have only one win controller, but I already have %@! I'll autorelease the first one but won't detach it - don't blame me if this crashes...", myWinCtrl);
		[myWinCtrl autorelease];
	}
	// create RDocumentWinCtrl which is a window controller - it loads the corresponding NIB and sets up the window
	myWinCtrl = [[RDocumentWinCtrl alloc] initWithWindowNibName:@"RDocument"];
	[self addWindowController:myWinCtrl];
}

- (NSString*)windowNibName
{
	return @"RDocument";
}

- (BOOL)writeToFile:(NSString *)fileName ofType:(NSString *)docType {
	SLog(@"RDocument.writeToFile: %@ ofType: %@", fileName, docType);
	return [super writeToFile:fileName ofType:docType];
}

- (void) loadInitialContents
{
	if (!initialContents) {
		SLog(@"RDocument.loadInitialContents: empty contents, skipping");
		return;
	}
	
	SLog(@"RDocument.loadInitialContents: loading");
	NSEnumerator *e = [[self windowControllers] objectEnumerator];
	RDocumentWinCtrl *wc = nil;
	while (wc = (RDocumentWinCtrl*)[e nextObject]) { 
		if ([initialContentsType isEqual:@"rtf"]) {
			SLog(@" - new RTF contents (%d bytes) for window controller %@", [initialContents length], wc);
			[wc replaceContentsWithRtf: initialContents];
		} else {
			NSString * cs = [NSString stringWithUTF8String:[initialContents bytes]];
			if (!cs) cs = [NSString stringWithCString:[initialContents bytes] length:[initialContents length]];
			if (cs) {
				SLog(@" - new string contents (%d chars) for window controller %@", [cs length], wc);
				[wc replaceContentsWithString: cs];
			}
		}
	}
}

- (NSData *)dataRepresentationOfType:(NSString *)aType
{
	
	// Insert code here to write your document from the given data.  You can also choose to override -fileWrapperRepresentationOfType: or -writeToFile:ofType: instead.
	NSEnumerator *e = [[self windowControllers] objectEnumerator];
	RDocumentWinCtrl *wc = nil;
	while (wc = (RDocumentWinCtrl*)[e nextObject]) { 
		if([aType isEqual:@"rtf"])
			return [wc contentsAsRtf];
		else
			return [[wc contentsAsString] dataUsingEncoding: NSUTF8StringEncoding];
	}
	return nil;
}

/* This method is implemented to allow image data file to be loaded into R using open
or drag and drop. In case of a successfull loading of image file, we don't want to
create the UI for the document.
*/
- (BOOL)readFromFile:(NSString *)fileName ofType:(NSString *)docType{
	if( [docType isEqual:@"R Data File"] || [[RController sharedController] isImageData:fileName] == 0){
		[[RController sharedController] sendInput: [NSString stringWithFormat:@"load(\"%@\")",fileName]];
		[[NSDocumentController sharedDocumentController]  setShouldCreateUI:NO];
		return(YES);
	} else {
		[[NSDocumentController sharedDocumentController]  setShouldCreateUI:YES];
		return( [super readFromFile: fileName ofType: docType] );
	}
}

- (BOOL) loadDataRepresentation: (NSData *)data ofType:(NSString *)aType {
	if (initialContents) {
		[initialContents release];
		initialContents=nil;
	}
	
	initialContentsType = [[NSString alloc] initWithString:aType];
	{ // terminate the data so it can be loaded as 0ts
		int tl = [data length]+4;
		void *buf = (void*) malloc(tl);
		SLog(@"RDocument.loadDataRepresentation loading %d bytes of data", [data length]);
		memcpy(buf, [data bytes], [data length]);
		memset(buf+tl-4, 0, 4); // set trailing 4 bytes to 0 to make sure the termination is safe
		
		// for performance resons we leave it to the NSData to take over the ownership, no need to copy anything.
		initialContents = [[NSData alloc] initWithBytesNoCopy:buf length:tl freeWhenDone:YES];
		SLog(@" - resulting ic has %d bytes", [initialContents length]);
	}

	[self loadInitialContents];

	return YES;
}

+ (void) changeDocumentTitle: (NSDocument *)document Title:(NSString *)title{
	NSEnumerator *e = [[document windowControllers] objectEnumerator];
	NSWindowController *wc = nil;
	
	while (wc = [e nextObject]) {
		NSWindow *dw = [wc window];
		[dw setTitle: title];
	}
}

- (void) setEditable: (BOOL) editable
{
	isEditable=editable;
	NSEnumerator *e = [[self windowControllers] objectEnumerator];
	RDocumentWinCtrl *wc = nil;
	while (wc = (RDocumentWinCtrl*)[e nextObject])
		[wc setEditable: editable];
}

- (BOOL) editable
{
	return isEditable;
}

- (void) setREditFlag: (BOOL) flag
{
	isREdit=flag;
}

- (BOOL) hasREditFlag
{
	return isREdit;
}

@end

