#import "AppDelegate.h"

@interface AppDelegate()

- (NSString*)applicationSupportFolder;

@end

@implementation AppDelegate

- (IBAction)addImage:(id)sender;
{
  NSManagedObject *recipe = [[recipeArrayController selectedObjects] lastObject];
  if (!recipe) return;
  
  NSOpenPanel *openPanel = [NSOpenPanel openPanel];
  
  [openPanel setCanChooseDirectories:NO];
  [openPanel setCanCreateDirectories:NO];
  [openPanel setAllowsMultipleSelection:NO];
  
  [openPanel beginSheetForDirectory:nil
                               file:nil
                     modalForWindow:window
                      modalDelegate:self
                     didEndSelector:@selector(addImageSheetDidEnd:returnCode:contextInfo:)
                        contextInfo:recipe];
}

- (void)addImageSheetDidEnd:(NSOpenPanel*)openPanel 
                 returnCode:(NSInteger)returnCode 
                contextInfo:(NSManagedObject*)recipe
{
  if (returnCode == NSCancelButton) return;
  NSString *path = [openPanel filename];
  
  //Build the path we want the file to be at
  NSString *destPath = [self applicationSupportFolder];
  destPath = [destPath stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]];
  [[NSFileManager defaultManager] copyPath:path toPath:destPath handler:nil];
  [recipe setValue:destPath forKey:@"imagePath"];
}

- (NSString *)applicationSupportFolder
{
  NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
  NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : NSTemporaryDirectory();
  return [basePath stringByAppendingPathComponent:@"GrokkingRecipes"];
}

- (NSManagedObjectModel *)managedObjectModel
{
  if (managedObjectModel) return managedObjectModel;
  
  NSString *path = [[NSBundle mainBundle] pathForResource:@"DataModel"
                                                   ofType:@"momd"];
  if (!path) {
    path = [[NSBundle mainBundle] pathForResource:@"DataModel"
                                           ofType:@"mom"];
  }
  NSAssert(path != nil, @"Unable to find DataModel in main bundle");
  NSURL *url = [NSURL fileURLWithPath:path];
  managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:url];
  return managedObjectModel;
}

- (void)deadCodeForBookExample
{
  
  NSString *applicationSupportFolder = [self applicationSupportFolder];
  NSError *error = nil;
  NSURL *url = [NSURL fileURLWithPath:[applicationSupportFolder 
                                       stringByAppendingPathComponent:@"GrokkingRecipes.xml"]];
  NSManagedObjectModel *mom = [self managedObjectModel];
  persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] 
                                initWithManagedObjectModel:mom];
  
  //START:criticalErrorDisplay
  if (![persistentStoreCoordinator addPersistentStoreWithType:NSXMLStoreType 
                                                configuration:nil 
                                                          URL:url 
                                                      options:nil 
                                                        error:&error]) {
    NSDictionary *ui = [error userInfo];
    if (ui) {
      NSLog(@"%@:%s %@", [self class], _cmd, [error localizedDescription]);
      for (NSError *suberror in [ui valueForKey:NSDetailedErrorsKey]) {
        NSLog(@"\t%@", [suberror localizedDescription]);
      }
    } else {
      NSLog(@"%@:%s %@", [self class], _cmd, [error localizedDescription]);
    }
    NSAlert *alert = [[NSAlert alloc] init];
    [alert setAlertStyle:NSCriticalAlertStyle];
    [alert setMessageText:@"Unable to load the recipes database."];
    NSString *msgText = nil;
    msgText = [NSString stringWithFormat:@"The recipes database %@%@%@\n%@",
               @"is either corrupt or was created by a newer ",
               @"version of Grokking Recipes.  Please contact ",
               @"support to assist with this error.\n\nError: ",
               [error localizedDescription]];
    [alert setInformativeText:msgText];
    [alert addButtonWithTitle:@"Quit"];
    [alert runModal];
    [alert release];
    exit(1);
  }
  //END:criticalErrorDisplay
  
}

//START:persistentStoreCoordinator
- (NSPersistentStoreCoordinator*)persistentStoreCoordinator;
{
  if (persistentStoreCoordinator) return persistentStoreCoordinator;
  
  NSFileManager *fileManager = [NSFileManager defaultManager];
  NSString *applicationSupportFolder = [self applicationSupportFolder];
  if ( ![fileManager fileExistsAtPath:applicationSupportFolder 
                          isDirectory:NULL] ) {
    [fileManager createDirectoryAtPath:applicationSupportFolder 
                            attributes:nil];
  }
  
  NSURL *url = [NSURL fileURLWithPath:[applicationSupportFolder 
                                       stringByAppendingPathComponent:@"GrokkingRecipes.xml"]];
  NSManagedObjectModel *mom = [self managedObjectModel];
  persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] 
                                initWithManagedObjectModel:mom];
  
  //END:persistentStoreCoordinator
  //START:turnOnAutomaticMigration
  NSMutableDictionary *dict = [NSMutableDictionary dictionary];
  [dict setObject:[NSNumber numberWithBool:YES] 
           forKey:NSMigratePersistentStoresAutomaticallyOption];
  
  NSError *error = nil;
  if (![persistentStoreCoordinator addPersistentStoreWithType:NSXMLStoreType 
                                                configuration:nil 
                                                          URL:url 
                                                      options:dict 
                                                        error:&error]) {
    //END:turnOnAutomaticMigration
    NSDictionary *ui = [error userInfo];
    if (ui) {
      NSLog(@"%@:%s %@", [self class], _cmd, [error localizedDescription]);
      for (NSError *suberror in [ui valueForKey:NSDetailedErrorsKey]) {
        NSLog(@"\t%@", [suberror localizedDescription]);
      }
    } else {
      NSLog(@"%@:%s %@", [self class], _cmd, [error localizedDescription]);
    }
    NSAlert *alert = [[NSAlert alloc] init];
    [alert setAlertStyle:NSCriticalAlertStyle];
    [alert setMessageText:@"Unable to load the recipes database."];
    NSString *msgText = nil;
    msgText = [NSString stringWithFormat:@"The recipes database %@%@%@\n%@",
               @"is either corrupt or was created by a newer ",
               @"version of Grokking Recipes.  Please contact ",
               @"support to assist with this error.\n\nError: ",
               [error localizedDescription]];
    [alert setInformativeText:msgText];
    [alert addButtonWithTitle:@"Quit"];
    [alert runModal];
    [alert release];
    exit(1);
  }
  //START:persistentStoreCoordinator
  return persistentStoreCoordinator;
}
//END:persistentStoreCoordinator

- (NSManagedObjectContext *) managedObjectContext
{
  if (managedObjectContext) return managedObjectContext;
  
  NSPersistentStoreCoordinator *coord = [self persistentStoreCoordinator];
  
  if (!coord) return nil;
  
  managedObjectContext = [[NSManagedObjectContext alloc] init];
  [managedObjectContext setPersistentStoreCoordinator: coord];
  
  NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
  [request setEntity:[NSEntityDescription entityForName:@"Type"
                                 inManagedObjectContext:managedObjectContext]];
  
  NSError *error = nil;
  NSArray *result = [managedObjectContext executeFetchRequest:request 
                                                        error:&error];
  NSAssert(error == nil, [error localizedDescription]);
  if ([result count]) return managedObjectContext;
  
  //The types table has not been populated
  NSArray *types;
  types = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"RecipeTypes"];
  
  for (NSString *type in types) {
    NSManagedObject *object = [NSEntityDescription 
                               insertNewObjectForEntityForName:@"Type" 
                               inManagedObjectContext:managedObjectContext];
    [object setValue:type forKey:@"name"];
  }
  
  return managedObjectContext;
}

- (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window
{
  return [[self managedObjectContext] undoManager];
}

- (IBAction) saveAction:(id)sender
{
  NSError *error = nil;
  if (![[self managedObjectContext] save:&error]) {
    [[NSApplication sharedApplication] presentError:error];
  }
}

- (NSApplicationTerminateReply)applicationShouldTerminate:(id)sender 
{
  NSError *error = nil;
  
  if (!managedObjectContext) return NSTerminateNow;
  if (![managedObjectContext commitEditing]) {
    //Failed to commit editing.
    return NSTerminateCancel;
  }
  if (![managedObjectContext hasChanges]) return NSTerminateNow;
  if (![managedObjectContext save:&error]) {
    int alertReturn = NSRunAlertPanel(nil, @"Could not save changes while quitting. Quit anyway?" , @"Quit anyway", @"Cancel", nil);
    if (alertReturn == NSAlertAlternateReturn) NSTerminateCancel;	
  }
  return NSTerminateNow;
}

- (void) dealloc 
{
  [managedObjectContext release], managedObjectContext = nil;
  [persistentStoreCoordinator release], persistentStoreCoordinator = nil;
  [managedObjectModel release], managedObjectModel = nil;
  [super dealloc];
}

@end
