//
//  TATAppDelegate.m
//  TadsTerp
//
//  Created by Rune Berg on 12/02/14.
//  Copyright (c) 2014 Rune Berg. All rights reserved.
//

#import "XTAppDelegate.h"
#import "XTPrefs.h"
#import "XTAbout.h"
#import "XTGameWindowController.h"
#import "XTPrefsWindowController.h"
#import "XTAboutWindowController.h"
#import "XTFileUrlStringValueTransformer.h"
#import "XTLogger.h"
#import "XTFileUtils.h"
#import "XTUIUtils.h"
#import "XTDirectoryHelper.h"
#import "XTNotifications.h"
#import "XTRecentGameFiles.h"


@interface XTAppDelegate ()

@property XTPrefs *prefs;
@property XTAbout *about;
@property XTDirectoryHelper *directoryHelper;
@property XTGameWindowController *gameWindowController;
@property XTPrefsWindowController *prefsWindowController;
@property XTAboutWindowController *aboutWindowController;
@property XTUIUtils *uiUtils;

@property NSArray *tadsGameFileExtensions;

@property BOOL modalPanelIsOpen;
@property NSUInteger countApplicationDidBecomeActive;

@end


@implementation XTAppDelegate

static XTLogger* logger;

/* Activate when/if needed:
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize managedObjectContext = _managedObjectContext;
*/

- (id)init
{
	self = [super init];
	if (self != nil) {
		_about = [XTAbout new];
		_prefs = [XTPrefs prefs];
		_about = [XTAbout about];
		_directoryHelper = [XTDirectoryHelper helper];
		_gameWindowController = nil;
		_prefsWindowController = nil;
		_uiUtils = [XTUIUtils new];
		_modalPanelIsOpen = NO;
		_countApplicationDidBecomeActive = 0;
		_tadsGameFileExtensions = @[@"gam", @"t3"];
	}
	return self;
}

+ (void)initialize
{
	logger = [XTLogger loggerForClass:[XTAppDelegate class]];
	
	// Register custom value transformers
	
	[NSValueTransformer setValueTransformer:[XTFileUrlStringValueTransformer new]
									forName:@"XTFileUrlStringValueTransformer"];
}

- (id<XTGameRunnerProtocol>)getGameRunner
{
	return self.gameWindowController;
}

/*------------------------------------------------------------------------------------
 *  Menu Application lifecycle functions
 */

- (void)applicationWillFinishLaunching:(NSNotification *)aNotification
{
	XT_TRACE_ENTRY;
	
	osxtads_init();

	//NSArray *recDocUrls = [[NSDocumentController sharedDocumentController] recentDocumentURLs];
	
	[self.prefs cleanupUnused];
	[self.prefs registerMissing];
	[self.prefs restoreFromPersisted];
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
	XT_TRACE_ENTRY;

	[self setupReceptionOfAppLevelNotifications];
	
	XTRecentGameFiles *recentGameFiles = [XTRecentGameFiles recentGameFiles];
	[recentGameFiles restoreFromPersisted];
	[self refreshMyOpenRecentMenu];
}

- (void)applicationDidBecomeActive:(NSNotification *)aNotification
{
	XT_TRACE_ENTRY;

	self.countApplicationDidBecomeActive += 1;
	
	if (self.countApplicationDidBecomeActive == 1) {
		[self hideFontPanelIfVisible];
		[self hideColorPanelIfVisible]; // can't reliably do this in applicationDidFinishLaunching :-(
		
		if (self.prefs.askForGameFileOnTerpStart.boolValue) {
			// Async notification to ask for a game file:
			NSNotification *myNotification = [NSNotification notificationWithName:XTadsNotifyAutoAskForGameFile object:self];
			[[NSNotificationQueue defaultQueue] enqueueNotification:myNotification postingStyle:NSPostASAP];
		}
	}
}

/*------------------------------------------------------------------------------------
 *  Menu event handlers
 */
- (IBAction)openAbout:(id)sender {
	
	XT_TRACE_ENTRY;
	
	//TODO Window menu: put "About" above game window(s)
	
	if (self.aboutWindowController == nil) {
		self.aboutWindowController = [XTAboutWindowController controllerWithAbout:self.about];
	}
	[self.aboutWindowController showWindow:self];
}

- (IBAction)openPreferences:(id)sender
{
	XT_TRACE_ENTRY;
	
	//TODO Window menu: put "Preferences" above game window(s)

	if (self.prefsWindowController == nil) {
		self.prefsWindowController = [XTPrefsWindowController controllerWithPrefs:self.prefs];
	}
	[self.prefsWindowController showWindow:self];
}

- (IBAction)openGameFile:(id)sender
{
	XT_TRACE_ENTRY;

	if (! [self quitCurrentlyRunningGame]) {
		return;
	}
	
	//TODO refactor to XTUIUtils method?
	
	NSOpenPanel* panel = [NSOpenPanel openPanel];
	[panel setTitle:@"Select TADS Game File  (.gam, .t3)"];
	NSArray *allowedExtensions = @[@"gam", @"t3"];
	[panel setAllowedFileTypes:allowedExtensions];
	NSURL *defaultGamesDirUrl = [self.directoryHelper findDefaultGamesDirectory];
	[panel setDirectoryURL:defaultGamesDirUrl];
	
	[XTNotifications notifyModalPanelOpened:self];
	
	[panel beginWithCompletionHandler:^(NSInteger result){

		[XTNotifications notifyModalPanelClosed:self];
		
		if (result == NSFileHandlingPanelOKButton) {
			NSURL* gameFileUrl = [[panel URLs] objectAtIndex:0];
			if ([self checkValidGameFile:gameFileUrl]) {
				[self runGameFile:gameFileUrl];
			}
		}
	}];
}

- (IBAction)openRecentMenu:(id)sender
{
	// When bound to menu item it triggers validateUserInterfaceItem for that menu, so that we can enable/disable it.
	// Apart from that, nothing to do here.
}

- (IBAction)myOpenRecentMenu:(id)sender
{
	// When bound to menu item it triggers validateUserInterfaceItem for that menu, so that we can enable/disable it.
	// Apart from that, nothing to do here.
}

- (IBAction)myClearRecentFiles:(id)sender
{
	XTRecentGameFiles *recentGameFiles = [XTRecentGameFiles recentGameFiles];
	[recentGameFiles removeAllEntries];
	[self refreshMyOpenRecentMenu];
}

- (IBAction)reloadGameFile:(id)sender
{
	XT_TRACE_ENTRY;
	
	if (self.gameWindowController != nil) {
		BOOL quitGameConfirmed = YES;
		if (self.prefs.askForConfirmationOnGameRestart.boolValue) {
			quitGameConfirmed = [self.gameWindowController confirmQuitGameIfRunning:@"A game is already running. Do you really want to quit and restart it?"];
		}
		if (quitGameConfirmed) {
			BOOL reloadedOk = [self.gameWindowController reloadGameFile];
			//TODO handle false return
		}
	} else {
		XT_WARN_0(@"found no active game window controller");
	}
}

// Event handler, programmatically set by refreshMyOpenRecentMenu.
// Called when user selects an actual recent game menu item.
- (void)myOpenRecent:(id)sender
{
	XT_DEF_SELNAME;

	if ([sender isKindOfClass:[NSMenuItem class]]) {
		NSMenuItem *menuItem = sender;
		id ro = menuItem.representedObject;
		if ([ro isKindOfClass:[XTRecentGameFilesEntry class]]) {
			XTRecentGameFilesEntry *entry = ro;
			NSURL *gameFileUrl = entry.gameFileUrl;
			[self application:[NSApplication sharedApplication] openFile:[gameFileUrl path]];
		} else {
			XT_ERROR_0(@"menu item's representedObject was not a XTRecentGameFilesEntry");
		}
	} else {
		XT_ERROR_0(@"sender was not a NSMenuItem");
	}
}

/*------------------------------------------------------------------------------------
 *  Delegate and overrides
 */

// Called when using Finder to open a file with XTads
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
{
	XT_DEF_SELNAME;
	XT_TRACE_1(@"%@", filename);
	
	if (self.modalPanelIsOpen) {
		XT_TRACE_0(@"-> NO - had modal dialog open");
		return NO;
	}
	
	NSURL* gameFileUrl = [NSURL fileURLWithPath:filename];
	
	if (! [self checkValidGameFile:gameFileUrl]) {
		return NO;
	}
	
	if ([self quitCurrentlyRunningGame]) {
		[self runGameFile:gameFileUrl];
	}
	
	XT_TRACE_0(@"-> YES");
	
	return YES;
}

- (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)anItem
{
	XT_DEF_SELNAME;
	NSString *actionSelName = NSStringFromSelector(anItem.action);
	XT_TRACE_1(@"got action %@", actionSelName);
	
	if (self.gameWindowController.isSleeping) {
		// allow nothing if game VM thread is sleeping
		XT_WARN_0(@"-> 0 (VM thread is sleeping)");
		return NO;
	}
	
	BOOL res = YES;
	NSString *title = @"(not a menu item)";
	
	NSObject *anItemObj = (NSObject *)anItem;
	BOOL isRestartGame = (anItem.action == @selector(reloadGameFile:));
	BOOL isOpenGame = (anItem.action == @selector(openGameFile:));
	BOOL isOpenARecentGame = (anItem.action == @selector(myOpenRecentMenu:));
	
	XT_TRACE_3(@"isRestartGame=%d isOpenGame=%d isOpenARecentGame=%d", isRestartGame, isOpenGame, isOpenARecentGame);
	
	if ([anItemObj isKindOfClass:[NSMenuItem class]]) {
		title = ((NSMenuItem *)anItem).title;
		XT_TRACE_1(@"got menu item \"%@\"", title);
	} else if ([anItemObj isKindOfClass:[NSMenu class]]) {
		// never get here. whatever.
		title = ((NSMenu *)anItem).title;
		XT_TRACE_1(@"got menU \"%@\"", title);
	}
	
	// disable "Restart" menu item if...
	if (isRestartGame) {
		if (self.modalPanelIsOpen) {
			//XT_TRACE_0(@"not allowed to restart - modalPanelIsOpen");
			res = NO;
		} else if (self.gameWindowController == nil) {
			//XT_TRACE_0(@"not allowed to restart - gameWindowController == nil");
			res = NO;
		} else if (! [self.gameWindowController canLoadAndStartGameFile]) {
			//XT_TRACE_0(@"not allowed to restart - ! canLoadAndStartGameFile");
			res = NO;
		} else {
			//XT_TRACE_0(@"allowed to restart");
		}
	}
	
	// disable "Open" menu item if...
	if (res && isOpenGame) {
		if (self.modalPanelIsOpen) {
			res = NO;
		} else if (self.gameWindowController == nil) {
			res = YES;
		} else if (! [self.gameWindowController canLoadAndStartGameFile]) {
			res = NO;
		}
	}
	
	// disable "Open Recent" if...
	if (res && isOpenARecentGame) {
		if (self.modalPanelIsOpen) {
			res = NO;
		} else if (self.gameWindowController == nil) {
			res = YES;
		} else if (! [self.gameWindowController canLoadAndStartGameFile]) {
			res = NO;
		}
	}
	
	XT_TRACE_2(@"(menu) \"%@\" -> %d", title, res);
	
	return res;
}

/*------------------------------------------------------------------------------------
 *  Misc.
 */

- (void)refreshMyOpenRecentMenu
{
	XT_DEF_SELNAME;

	NSMenu *mainMenu = [[NSApplication sharedApplication] mainMenu];
	NSMenuItem *fileMenuItem = [mainMenu itemWithTitle:@"File"];
	NSMenu *fileSubMenu = [fileMenuItem submenu];
	NSMenuItem *myOpenRecentMenuItem = [fileSubMenu itemWithTag:98765];  // 98765 is set in the xib
	NSMenu *myOpenRecentSubMenu = [myOpenRecentMenuItem submenu];
	
	[myOpenRecentSubMenu removeAllItems];
	
	XTRecentGameFiles *recentGameFiles = [XTRecentGameFiles recentGameFiles];
	NSUInteger countRecentGameFiles = [recentGameFiles numberOfEntries];
	
	for (NSUInteger i = 0; i < countRecentGameFiles; i++) {
		
		XTRecentGameFilesEntry *entry = [recentGameFiles entryAtIndex:i];
		if ([XTFileUtils isExistingFileUrl:entry.gameFileUrl]) {
			NSString *gameTitle = entry.gameTitle;
			NSMenuItem *item = [[NSMenuItem new] initWithTitle:gameTitle action:@selector(myOpenRecent:) keyEquivalent:@""];
			item.representedObject = entry;
			item.tag = i;
			[myOpenRecentSubMenu addItem:item];
		} else {
			XT_TRACE_1(@"Recent game file %@ does not exist - skipped from menu", entry.gameFileUrl);
		}
	}
	
	if (countRecentGameFiles >= 1) {
		[myOpenRecentSubMenu addItem:[NSMenuItem separatorItem]];
	}
	
	NSMenuItem *clearItem = [[NSMenuItem new] initWithTitle:@"Clear Menu" action:@selector(myClearRecentFiles:) keyEquivalent:@""];
	[myOpenRecentSubMenu addItem:clearItem];

	[recentGameFiles persist];
}

- (BOOL)quitCurrentlyRunningGame
{
	BOOL res = YES;
	
	if (self.gameWindowController != nil) {
		if (self.prefs.askForConfirmationOnGameOpenIfGameRunning.boolValue) {
			res = [self.gameWindowController confirmQuitGameIfRunning:@"A game is already running. Do you really want to quit it and load another?"];
		}
		if (res) {
			[self.gameWindowController quitGameIfRunning];
			[self.gameWindowController closeWindow];
			//TODO null current game runner when game window gets closed
		}
	}
	
	return res;
}

- (void)noteRecentGameFileOpened:(NSURL *)gameFileUrl
{
	XT_DEF_SELNAME;
	XT_TRACE_1(@"%@", gameFileUrl);
	
	[[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL:gameFileUrl];
		// doesn't really work... state lost after terp restarted, hence homwgrown solution with XTRecentGameFiles
	
	XTRecentGameFiles *recentGameFiles = [XTRecentGameFiles recentGameFiles];
	XTRecentGameFilesEntry *entry = [XTRecentGameFilesEntry entryWithGameFileUrl:gameFileUrl gameTitle:nil];
		//TODO real title, if known
	[recentGameFiles addNewestEntry:entry];
	
	[self refreshMyOpenRecentMenu];
}

- (BOOL)checkValidGameFile:(NSURL *)fileUrl
{
	BOOL res = NO;
	
	if (fileUrl != nil) {
		if ([XTFileUtils isExistingFileUrl:fileUrl]) {
			if ([XTFileUtils fileUrl:fileUrl hasExtensionIn:self.tadsGameFileExtensions]) {
				res = YES;
			}
		}
	}
	if (! res) {
		NSString *fileName = XTADS_FILESYSTEM_C_STRING_TO_NSSTRING([fileUrl fileSystemRepresentation]);
		NSString *msgText = [NSString stringWithFormat:@"\"%@\" is not a valid TADS game file. Please use existing files that end in \".gam\" or \".t3\"", fileName];
		[self.uiUtils showModalErrorDialogWithMessageText:msgText];
	}
	
	return res;
}

- (void)runGameFile:(NSURL *)gameFileUrl
{
	XT_DEF_SELNAME;
	XT_TRACE_1(@"", gameFileUrl);
	
	self.gameWindowController = [XTGameWindowController controller];
	[self.gameWindowController loadAndStartGameFile:gameFileUrl];

	[self.directoryHelper noteUsedGamesDirectory:gameFileUrl];
	[self noteRecentGameFileOpened:gameFileUrl];	
}


- (void)hideFontPanelIfVisible
{
	if ([[NSFontPanel sharedFontPanel] isVisible])
		[[NSFontPanel sharedFontPanel] orderOut:self];
}

- (void)hideColorPanelIfVisible
{
	XT_DEF_SELNAME;

	if ([[NSColorPanel sharedColorPanel] isVisible]) {
		[[NSColorPanel sharedColorPanel] orderOut:self];
		XT_TRACE_0(@"closed panel");
	}
}

//---  App level notifications  ------------------------------------------------------------

- (void)setupReceptionOfAppLevelNotifications
{
	XT_TRACE_ENTRY;
	
	[[NSNotificationCenter defaultCenter] addObserver:self
											 selector:@selector(handleNotifyGameWindowWillClose:)
												 name:XTadsNotifyGameWindowWillClose
											   object:nil]; // nil means "for any sender"
	
	[[NSNotificationCenter defaultCenter] addObserver:self
											 selector:@selector(handleNotifyModalPanelOpened:)
												 name:XTadsNotifyModalPanelOpened
											   object:nil]; // nil means "for any sender"
	
	[[NSNotificationCenter defaultCenter] addObserver:self
											 selector:@selector(handleNotifyModalPanelClosed:)
												 name:XTadsNotifyModalPanelClosed
											   object:nil]; // nil means "for any sender"
	
	[[NSNotificationCenter defaultCenter] addObserver:self
											 selector:@selector(handleNotifyPrefsWindowClosed:)
												 name:XTadsNotifyPrefsWindowClosed
											   object:nil]; // nil means "for any sender"
	
	[[NSNotificationCenter defaultCenter] addObserver:self
											 selector:@selector(handleNotifyAboutWindowClosed:)
												 name:XTadsNotifyAboutWindowClosed
											   object:nil]; // nil means "for any sender"
	
	[[NSNotificationCenter defaultCenter] addObserver:self
											 selector:@selector(handleNotifyAutoAskForGameFile:)
												 name:XTadsNotifyAutoAskForGameFile
											   object:nil]; // nil means "for any sender"
}

- (void)handleNotifyGameWindowWillClose:(NSNotification *)notification
{
	XT_TRACE_ENTRY;

	XTGameWindowController *gwc = (XTGameWindowController *)notification.object;

	if (self.gameWindowController == gwc) {
		// simply closed the game window
		self.gameWindowController = nil;
		XT_TRACE_0(@"after nilling self.gameWindowController (== gwc)");
	} else {
		// replaced game window with another - ok
	}
	
	XT_TRACE_0(@"exit");
}

- (void)handleNotifyModalPanelOpened:(NSNotification *)notification
{
	XT_TRACE_ENTRY;
	
	self.modalPanelIsOpen = YES;
}

- (void)handleNotifyModalPanelClosed:(NSNotification *)notification
{
	XT_TRACE_ENTRY;
	
	self.modalPanelIsOpen = NO;
}

- (void)handleNotifyPrefsWindowClosed:(NSNotification *)notification
{
	XT_TRACE_ENTRY;
	
	[self hideFontPanelIfVisible];
	[self hideColorPanelIfVisible];
}

- (void)handleNotifyAboutWindowClosed:(NSNotification *)notification
{
	XT_TRACE_ENTRY;
}

- (void)handleNotifyAutoAskForGameFile:(NSNotification *)notification
{
	XT_TRACE_ENTRY;

	[self openGameFile:nil];
}

//---------------------------------------------------------------

/* Activate when/if needed:

// Returns the directory the application uses to store the Core Data store file. This code uses a directory named "runeberg.TadsTerp" in the user's Application Support directory.
- (NSURL *)applicationFilesDirectory
{
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSURL *appSupportURL = [[fileManager URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask] lastObject];
    return [appSupportURL URLByAppendingPathComponent:@"runeberg.TadsTerp"];
}

// Creates if necessary and returns the managed object model for the application.
- (NSManagedObjectModel *)managedObjectModel
{
    if (_managedObjectModel) {
        return _managedObjectModel;
    }
	
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"TadsTerp" withExtension:@"momd"];
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return _managedObjectModel;
}

// Returns the persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. (The directory for the store is created, if necessary.)
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator) {
        return _persistentStoreCoordinator;
    }
    
    NSManagedObjectModel *mom = [self managedObjectModel];
    if (!mom) {
        [logger error:@"%@:%@ No model to generate a store from", [self class], NSStringFromSelector(_cmd)];
        return nil;
    }
    
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSURL *applicationFilesDirectory = [self applicationFilesDirectory];
    NSError *error = nil;
    
    NSDictionary *properties = [applicationFilesDirectory resourceValuesForKeys:@[NSURLIsDirectoryKey] error:&error];
    
    if (!properties) {
        BOOL ok = NO;
        if ([error code] == NSFileReadNoSuchFileError) {
            ok = [fileManager createDirectoryAtPath:[applicationFilesDirectory path] withIntermediateDirectories:YES attributes:nil error:&error];
        }
        if (!ok) {
            [[NSApplication sharedApplication] presentError:error];
            return nil;
        }
    } else {
        if (![properties[NSURLIsDirectoryKey] boolValue]) {
            // Customize and localize this error.
            NSString *failureDescription = [NSString stringWithFormat:@"Expected a folder to store application data, found a file (%@).", [applicationFilesDirectory path]];
            
            NSMutableDictionary *dict = [NSMutableDictionary dictionary];
            [dict setValue:failureDescription forKey:NSLocalizedDescriptionKey];
            error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:101 userInfo:dict];
            
            [[NSApplication sharedApplication] presentError:error];
            return nil;
        }
    }
    
    NSURL *url = [applicationFilesDirectory URLByAppendingPathComponent:@"TadsTerp.storedata"];
    NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];
    if (![coordinator addPersistentStoreWithType:NSXMLStoreType configuration:nil URL:url options:nil error:&error]) {
        [[NSApplication sharedApplication] presentError:error];
        return nil;
    }
    _persistentStoreCoordinator = coordinator;
    
    return _persistentStoreCoordinator;
}

// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) 
- (NSManagedObjectContext *)managedObjectContext
{
    if (_managedObjectContext) {
        return _managedObjectContext;
    }
    
    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (!coordinator) {
        NSMutableDictionary *dict = [NSMutableDictionary dictionary];
        [dict setValue:@"Failed to initialize the store" forKey:NSLocalizedDescriptionKey];
        [dict setValue:@"There was an error building up the data file." forKey:NSLocalizedFailureReasonErrorKey];
        NSError *error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict];
        [[NSApplication sharedApplication] presentError:error];
        return nil;
    }
    _managedObjectContext = [[NSManagedObjectContext alloc] init];
    [_managedObjectContext setPersistentStoreCoordinator:coordinator];

    return _managedObjectContext;
}

// Returns the NSUndoManager for the application. In this case, the manager returned is that of the managed object context for the application.
- (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window
{
    return [[self managedObjectContext] undoManager];
}

// Performs the save action for the application, which is to send the save: message to the application's managed object context. Any encountered errors are presented to the user.
- (IBAction)saveAction:(id)sender
{
    NSError *error = nil;
    
    if (![[self managedObjectContext] commitEditing]) {
        [logger error:@"%@:%@ unable to commit editing before saving", [self class], NSStringFromSelector(_cmd)];
    }
    
    if (![[self managedObjectContext] save:&error]) {
        [[NSApplication sharedApplication] presentError:error];
    }
}
*/

- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
	XT_DEF_SELNAME;

	if (self.gameWindowController != nil) {
		
		if (self.gameWindowController.isSleeping) {
			XT_TRACE_0(@"not while game VM thread is sleeping");
			return NSTerminateCancel;
		}

		BOOL quitGameConfirmed = YES;
		if (self.prefs.askForConfirmationOnGameQuit.boolValue) {
			quitGameConfirmed = [self.gameWindowController confirmQuitTerpIfGameRunning:@"A game is currently running. Do you really want to quit XTads?"];
		}
		if (! quitGameConfirmed) {
			return NSTerminateCancel;
		}
	}

	/*
	// Save changes in the application's managed object context before the application terminates.
    
    if (!_managedObjectContext) {
        return NSTerminateNow;
    }
    
    if (![[self managedObjectContext] commitEditing]) {
        [logger error:@"%@:%@ unable to commit editing to terminate", [self class], NSStringFromSelector(_cmd)];
        return NSTerminateCancel;
    }
    
    if (![[self managedObjectContext] hasChanges]) {
        return NSTerminateNow;
    }
    
    NSError *error = nil;
    if (![[self managedObjectContext] save:&error]) {

        // Customize this code block to include application-specific recovery steps.              
        BOOL result = [sender presentError:error];
        if (result) {
            return NSTerminateCancel;
        }

        NSString *question = NSLocalizedString(@"Could not save changes while quitting. Quit anyway?", @"Quit without saves error question message");
        NSString *info = NSLocalizedString(@"Quitting now will lose any changes you have made since the last successful save", @"Quit without saves error question info");
        NSString *quitButton = NSLocalizedString(@"Quit anyway", @"Quit anyway button title");
        NSString *cancelButton = NSLocalizedString(@"Cancel", @"Cancel button title");
        NSAlert *alert = [[NSAlert alloc] init];
        [alert setMessageText:question];
        [alert setInformativeText:info];
        [alert addButtonWithTitle:quitButton];
        [alert addButtonWithTitle:cancelButton];

        NSInteger answer = [alert runModal];
        
        if (answer == NSAlertAlternateReturn) {
            return NSTerminateCancel;
        }
    }
	*/

    return NSTerminateNow;
}


@end
