#import "DocumentPreferences.h"

@interface DocumentPreferences ()

- (NSManagedObject*)findParameter:(NSString*)key;
- (NSManagedObject*)createParameter:(NSString*)name;

@end

@implementation DocumentPreferences

@synthesize associatedDocument = _associatedDocument;
@synthesize defaults = _defaults;

- (id)initWithDocument:(NSPersistentDocument*)associatedDocument;
{
  if (!(self = [super init])) return nil;
  
  _associatedDocument = associatedDocument;
  
  return self;
}

//START:valueForUndefinedKey
- (id)valueForUndefinedKey:(NSString*)key
{
  id parameter = [self findParameter:key];
  if (!parameter && [[self defaults] objectForKey:key]) {
    return [[self defaults] objectForKey:key];
  }
  return [parameter valueForKey:@"value"];
}
//END:valueForUndefinedKey

//START:setValueForKey
- (void)setValue:(id)value forUndefinedKey:(NSString*)key
{
  [self willChangeValueForKey:key];
  NSManagedObject *parameter = [self findParameter:key];
  if (!parameter) {
    if ([[self defaults] valueForKey:key] && 
        [value isEqualTo:[[self defaults] valueForKey:key]]) {
      [self didChangeValueForKey:key];
      return;
    }
    parameter = [self createParameter:key];
  } else {
    if ([[self defaults] valueForKey:key] && 
        [value isEqualTo:[[self defaults] valueForKey:key]]) {
      [self didChangeValueForKey:key];
      [[[self associatedDocument] managedObjectContext] deleteObject:parameter];
      [self didChangeValueForKey:key];
      return;
    }
  }
      
  if ([value isKindOfClass:[NSNumber class]]) {
    [parameter setValue:[value stringValue] forKey:@"value"];
  } else if ([value isKindOfClass:[NSDate class]]) {
    [parameter setValue:[value description] forKey:@"value"];
  } else {
    [parameter setValue:value forKey:@"value"];
  }
  [self didChangeValueForKey:key];
}
//END:setValueForKey

//START:findParameter
- (NSManagedObject*)findParameter:(NSString*)name;
{
  NSManagedObjectContext *moc;
  NSManagedObject *param;
  NSError *error = nil;
  moc = [[self associatedDocument] managedObjectContext];
  NSFetchRequest *request = [[NSFetchRequest alloc] init];
  [request setEntity:[NSEntityDescription entityForName:@"Parameter"
                                 inManagedObjectContext:moc]];
  [request setPredicate:[NSPredicate predicateWithFormat:@"name == %@", name]];
  
  param = [[moc executeFetchRequest:request error:&error] lastObject];
  if (error) {
    NSLog(@"%@:%s Error fetching parameter: %@", [self class], _cmd, error);
    return nil;
  }
  [request release], request = nil;
  return param;
}
//END:findParameter

//START:createParameter
- (NSManagedObject*)createParameter:(NSString*)name
{
  NSManagedObject *param;
  NSManagedObjectContext *moc;
  moc = [[self associatedDocument] managedObjectContext];
  param = [NSEntityDescription insertNewObjectForEntityForName:@"Parameter"
                                        inManagedObjectContext:moc];
  [param setValue:name forKey:@"name"];
  return param;
}
//END:createParameter

//START:allParameterNames
- (NSArray*)allParameterNames;
{
  NSManagedObjectContext *moc;
  NSError *error = nil;
  moc = [[self associatedDocument] managedObjectContext];
  NSFetchRequest *request = [[NSFetchRequest alloc] init];
  [request setEntity:[NSEntityDescription entityForName:@"Parameter"
                                 inManagedObjectContext:moc]];
  NSArray *params = [moc executeFetchRequest:request error:&error];
  if (error) {
    NSLog(@"%@:%s Error fetching parameter: %@", [self class], _cmd, error);
    return nil;
  }
  
  NSMutableArray *keys = [[[self defaults] allKeys] mutableCopy];
  for (NSManagedObject *param in params) {
    NSString *name = [param valueForKey:@"name"];
    [keys addObject:name];
  }
  return keys;
}
//END:allParameterNames

//START:allParameters
- (NSDictionary*)allParameters;
{
  NSManagedObjectContext *moc;
  NSError *error = nil;
  moc = [[self associatedDocument] managedObjectContext];
  NSFetchRequest *request = [[NSFetchRequest alloc] init];
  [request setEntity:[NSEntityDescription entityForName:@"Parameter"
                                 inManagedObjectContext:moc]];
  NSArray *params = [moc executeFetchRequest:request error:&error];
  if (error) {
    NSLog(@"%@:%s Error fetching parameter: %@", [self class], _cmd, error);
    return nil;
  }
  
  NSMutableDictionary *dict = [[self defaults] mutableCopy];
  for (NSManagedObject *param in params) {
    NSString *name = [param valueForKey:@"name"];
    NSString *value = [param valueForKey:@"value"];
    [dict setValue: value forKey:name];
  }
  return dict;
}
//END:allParameters

@end
