#import "PPExportOperation.h"
#import "AppDelegate.h"
#import "PPRecipe.h"

@implementation PPExportOperation

@synthesize objectIDs = _objectIDs;
@synthesize saveFilePath = _saveFilePath;
@synthesize lookup = _lookup;

//START: initWithDelegate
- (id)initWithDelegate:(AppDelegate*)delegate 
             objectIDs:(NSArray*)objectIDs
          saveFilePath:(NSString*)saveFilePath;
{
  if (!(self = [super init])) return nil;
  appDelegate = delegate;
  [self setObjectIDs:objectIDs];
  [self setSaveFilePath:saveFilePath];
  [self setLookup:[NSMutableDictionary dictionary]];
  return self;
}
//END: initWithDelegate

- (void)dealloc
{
  [_lookup release], _lookup = nil;
  [_objectIDs release], _objectIDs = nil;
  [super dealloc];
}

- (NSManagedObjectModel*)managedObjectModel 
{
  NSString *path = [[NSBundle mainBundle] pathForResource:@"DataModel"
                                                   ofType:@"momd"];
  if (!path) {
    path = [[NSBundle mainBundle] pathForResource:@"DataModel" ofType:@"mom"];
  }
  NSURL *url = [NSURL fileURLWithPath:path];
  id mom = [[NSManagedObjectModel alloc] initWithContentsOfURL:url];
  return [mom autorelease];
}

- (NSPersistentStoreCoordinator*)persistentStoreCoordinator;
{
  NSManagedObjectModel *mom = [self managedObjectModel];
  id psc = [[NSPersistentStoreCoordinator alloc]
            initWithManagedObjectModel:mom];
  
  NSError *error = nil;
  NSPersistentStore *store;
  NSURL *url = [NSURL fileURLWithPath:[self saveFilePath]];
  store = [psc addPersistentStoreWithType:NSXMLStoreType
                            configuration:nil
                                      URL:url
                                  options:nil
                                    error:&error];
  if (!store) {
    [[NSApplication sharedApplication] presentError:error];
    return nil;
  }
  return [psc autorelease];
}

- (NSManagedObjectContext*)managedObjectContext
{
  NSPersistentStoreCoordinator *coord = [self persistentStoreCoordinator];
  if (!coord) return nil;
  NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init];
  [moc setPersistentStoreCoordinator: coord];
  return [moc autorelease];
}

- (NSManagedObject*)copyObject:(NSManagedObject*)object 
                     toContext:(NSManagedObjectContext*)moc 
                        parent:(NSString*)parentEntity;
{
  NSString *entityName = [[object entity] name];
  
  NSManagedObject *newObject = [NSEntityDescription 
                                insertNewObjectForEntityForName:entityName 
                                inManagedObjectContext:moc];
  [[self lookup] setObject:newObject forKey:[object objectID]];
  
  NSArray *attKeys = [[[object entity] attributesByName] allKeys];
  NSDictionary *attributes = [object dictionaryWithValuesForKeys:attKeys];
  
  [newObject setValuesForKeysWithDictionary:attributes];
  
  id oldDestObject = nil;
  id temp = nil;
  NSDictionary *relationships = [[object entity] relationshipsByName];
  for (NSString *key in [relationships allKeys]) {
    
    NSRelationshipDescription *desc = [relationships valueForKey:key];
    NSString *destEntityName = [[desc destinationEntity] name];
    if ([destEntityName isEqualToString:parentEntity]) continue;
    
    if ([desc isToMany]) {
      
      NSMutableSet *newDestSet = [NSMutableSet set];
      
      for (oldDestObject in [object valueForKey:key]) {
        temp = [[self lookup] objectForKey:[oldDestObject objectID]];
        if (!temp) {
          temp = [self copyObject:oldDestObject 
                        toContext:moc 
                           parent:entityName];
        }
        [newDestSet addObject:temp];
      }
      
      [newObject setValue:newDestSet forKey:key];
      
    } else {
      oldDestObject = [object valueForKey:key];
      if (!oldDestObject) continue;
      
      temp = [[self lookup] objectForKey:[oldDestObject objectID]];
      if (!temp && ![destEntityName isEqualToString:parentEntity]) {
        temp = [self copyObject:oldDestObject 
                      toContext:moc 
                         parent:entityName];
      }
      
      [newObject setValue:temp forKey:key];
    }
  }
  
  return newObject;
}

//START:PPExportMainPrep
- (void)main
{
  NSManagedObjectContext *exportMOC = [self managedObjectContext];
  if (!exportMOC) return;
  
  NSPersistentStoreCoordinator *sourceStore = nil;
  sourceStore = [appDelegate persistentStoreCoordinator];
  NSManagedObjectContext *sourceMOC = [[NSManagedObjectContext alloc] init];
  [sourceMOC setPersistentStoreCoordinator:sourceStore];
  //END:PPExportMainPrep

  //START:PPExportMainCopy
  for (NSManagedObjectID *objectID in [self objectIDs]) {
    NSManagedObject *object = [sourceMOC objectWithID:objectID];
    [self copyObject:object 
           toContext:exportMOC 
              parent:nil];
  }
  [sourceMOC release], sourceMOC = nil;
  //END:PPExportMainCopy
  
  //START:PPExportMainFinish
  NSError *error = nil;
  if (![exportMOC save:&error]) {
    [NSApp presentError:error];
  }
}
//END:PPExportMainFinish

@end
