//
//  KVCArrayHack.m
//
//  Created by Andy Lee on 8/16/11.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import <Foundation/Foundation.h>

// See <http://lists.apple.com/archives/Cocoa-dev/2011/Aug/msg00690.html>.
// This file contains two classes and a category. See the comments.

//-------------------------------------------------------------
// Class KAHArrayWrapper
//-------------------------------------------------------------

/*!
 * Used by KAHObjectWrapper. Overrides valueForKey: and setValue:forKey:
 * to treat the key as an array index into [self baseArray]. For example,
 * [myArrayWrapper valueForKey:@"0"] returns the 0th element of baseArray.
 *
 * "KAH" stands for "KVC Array Hack".
 */
@interface KAHArrayWrapper : NSObject
{
@private
	NSMutableArray *_baseArray;
}

@property (readwrite, retain) NSMutableArray *baseArray;

@end


@implementation KAHArrayWrapper

@synthesize baseArray = _baseArray;

- (void)dealloc
{
    [_baseArray release];
	
	[super dealloc];
}

- (id)valueForKey:(NSString *)key
{
	return [_baseArray objectAtIndex:[key integerValue]];
}

- (void)setValue:(id)value forKey:(NSString *)key
{
	[_baseArray replaceObjectAtIndex:[key integerValue] withObject:value];
}

@end

//-------------------------------------------------------------
// Class KAHObjectWrapper
//-------------------------------------------------------------

/*!
 * Overrides valueForKey: to assume the value is an NSArray, and returns
 * a KAHArrayWrapper with that NSArray.
 */
@interface KAHObjectWrapper : NSObject
{
@private
	id _baseObject;
}

@property (readwrite, retain) id baseObject;

@end


@implementation KAHObjectWrapper

@synthesize baseObject = _baseObject;

- (void)dealloc
{
    [_baseObject release];
	
	[super dealloc];
}

- (id)valueForKey:(NSString *)key
{
	id realArray = [_baseObject valueForKey:key];
	KAHArrayWrapper *arrayWrapper = [[[KAHArrayWrapper alloc] init] autorelease];
	
	[arrayWrapper setBaseArray:realArray];
	
	return arrayWrapper;
}

- (void)setValue:(id)value forKey:(NSString *)key
{
	[_baseObject setValue:value forKey:key];
}

@end

//-------------------------------------------------------------
// Category NSObject (KAH)
//-------------------------------------------------------------

/*!
 * Implements a method called ARR that returns a KAHObjectWrapper containing
 * self. So you can do
 *
 * Employee *anEmployee = [aManager valueForKey:@"department.ARR.employees.2"];
 *
 * and this will give you the same as
 *
 * Department *aDepartment = [aManager department];
 * NSArray *employees = [aDepartment employees];
 * Employee *anEmployee = [employees objectAtIndex:2];
 */
@implementation NSObject (KAH)

- (KAHObjectWrapper *)ARR
{
	KAHObjectWrapper *objectWrapper = [[[KAHObjectWrapper alloc] init] autorelease];
	
	[objectWrapper setBaseObject:self];
	
	return objectWrapper;
}

@end
