//
// File: VLKeyValueUndo.mm - Automatically handle undo functionality for 
//                          key-value paths
//
// Author(s):
//
//      (MN)    Matthias Neeracher
//
// Copyright © 2007-2011 Matthias Neeracher
//

#import "VLKeyValueUndo.h"
#import "VLDocument.h"

@implementation VLKeyValueUndo

- (id)initWithOwner:(id)o keysAndNames:(NSDictionary *)kn update:(VLKeyValueUpdateHook)hook
{
	owner			= o;
	keysAndNames	= [kn retain];
    updateHook      = Block_copy(hook);

	for (NSEnumerator * e = [keysAndNames keyEnumerator];
		 NSString * key = [e nextObject];
	)
		[owner addObserver:self forKeyPath:key 
			   options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew
			   context:[keysAndNames objectForKey:key]];
		
	return self;
}

- (id)initWithOwner:(id)o keysAndNames:(NSDictionary *)kn
{
    return [self initWithOwner:o keysAndNames:kn update:nil];
}

- (void) dealloc
{
	for (NSEnumerator * e = [keysAndNames keyEnumerator];
		 NSString * key = [e nextObject];
    )
		[owner removeObserver:self forKeyPath:key];
	[keysAndNames release];
    [updateHook release];
	[super dealloc];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
	id	oldVal	= [change objectForKey:NSKeyValueChangeOldKey];
	id 	newVal = [change objectForKey:NSKeyValueChangeNewKey];

	if (![oldVal isEqual:newVal]) {	
		NSUndoManager * undo = [owner undoManager];
		NSString *		name = [keysAndNames objectForKey:keyPath];
		[undo registerUndoWithTarget:owner selector:@selector(setValuesForKeysWithDictionary:) 
			object: [NSDictionary dictionaryWithObjectsAndKeys: oldVal, keyPath, nil]];
		[undo setActionName: name];
        if (updateHook)
            updateHook(keyPath);
	}
}

@end