//
//  NSArray+CocoaDevUsersAdditions.m
//  Dockyard
//

#import "NSArray+CocoaDevUsersAdditions.h"

/*!
 * Some handy addenda to NSArray, everybody's favorite Cocoa OrderedCollection.
 * Some are for symmetry, some are for kicks, all are for free. Enjoy.
 * (docs taken from CocoaDev)
 *
 * @see <a href="http://www.cocoadev.com/index.pl?NSArrayCategory">NSArrayCategory (CocoaDev)</a>
 */
@implementation NSArray (CocoaDevUsersAdditions)
/*!
 * Sends the <code>aSelector</code> message to each object in the array, starting with the first
 * object and continuing through the array to the last object. The <code>aSelector</code> method
 * must not take any arguments. It shouldn't have the side effect of modifying the receiving array.
 * This method raises an NSInvalidArgumentException if <code>aSelector</code> is <code>NULL</code>
 * (docs taken from ADC). The resulting NSArray contains the results of the method calls, using
 * <code>NSNull</code> in place of <code>nil</code>. It has a one-to-one correspondence with the
 * items in this array.
 *
 * @functiongroup Sending messages to elements
 * @see <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Objc_classic/Classes/NSArray.html#//apple_ref/doc/uid/20000137-BABCBHFG" class="classLink">
 *			makeObjectsPerformSelector:</a> (NSArray)
 * @see <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Objc_classic/Classes/NSArray.html#//apple_ref/doc/uid/20000137-BABCJEGJ" class="classLink">
 *			makeObjectsPerformSelector:withObject:</a> (NSArray)
 * @see #resultsOfMakeObjectsPerformSelector:withObject:
 * @see #makeObjectsPerformSelector:withRespectiveObjectsFrom:
 * @see #resultsOfMakeObjectsPerformSelector:withRespectiveObjectsFrom:
 */
- (NSArray *)resultsOfMakeObjectsPerformSelector:(SEL)aSelector
{
    NSMutableArray *result = [NSMutableArray arrayWithCapacity:[self count]];
    NSEnumerator *objectEnumerator;
    id obj;
    id objResult;

    if (aSelector == NULL)
    {
        [NSException raise:NSInvalidArgumentException format:@"aSelector cannot be NULL."];
    }

    objectEnumerator = [self objectEnumerator];
    while (obj = [objectEnumerator nextObject])
    {
        objResult = [obj performSelector:aSelector];
        if (objResult == nil)
            objResult = [NSNull null];
        [result addObject:objResult];
    }

    return result;
}

/*!
 * Sends the <code>aSelector</code> message to each object in the array, starting with the first
 * object and continuing through the array to the last object. The message is sent each time with
 * <code>anObject</code> as an argument, so the <code>aSelector</code> method must take a single
 * argument of type <code>id</code>. The <code>aSelector</code> method shouldn't, as a side effect,
 * modify the receiving array. This method raises an NSInvalidArgumentException if <code>aSelector</code>
 * is <code>NULL</code> (docs taken from ADC). The resulting NSArray contains the results of the
 * method calls, using <code>NSNull</code> in place of <code>nil</code>. It has a one-to-one
 * correspondence with the items in this array.
 *
 * @see <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Objc_classic/Classes/NSArray.html#//apple_ref/doc/uid/20000137-BABCBHFG" class="classLink">
 *			makeObjectsPerformSelector:</a> (NSArray)
 * @see #resultsOfMakeObjectsPerformSelector:
 * @see <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Objc_classic/Classes/NSArray.html#//apple_ref/doc/uid/20000137-BABCJEGJ" class="classLink">
 *			makeObjectsPerformSelector:withObject:</a> (NSArray)
 * @see #makeObjectsPerformSelector:withRespectiveObjectsFrom:
 * @see #resultsOfMakeObjectsPerformSelector:withRespectiveObjectsFrom:
 */
- (NSArray *)resultsOfMakeObjectsPerformSelector:(SEL)aSelector withObject:(id)anObject
{
    NSMutableArray *result = [NSMutableArray arrayWithCapacity:[self count]];
    NSEnumerator *objectEnumerator;
    id obj;
    id objResult;

    if (aSelector == NULL)
    {
        [NSException raise:NSInvalidArgumentException format:@"aSelector cannot be NULL."];
    }

    objectEnumerator = [self objectEnumerator];
    while (obj = [objectEnumerator nextObject])
    {
        objResult = [obj performSelector:aSelector withObject:anObject];
        if (objResult == nil)
            objResult = [NSNull null];
        [result addObject:objResult];
    }

    return result;
}

/*!
 * Sends the <code>aSelector</code> message to each object in the array, starting with the first
 * object and continuing through the array to the last object. The message is sent each time with
 * progressive objects from <code>collection</code> as an argument, so the <code>aSelector</code>
 * method must take a single argument of type <code>id</code>. The <code>aSelector</code> method
 * shouldn't, as a side effect, modify the receiving array. This method raises an NSInvalidArgumentException
 * if <code>aSelector</code> is <code>NULL</code> (modified from ADC docs). <code>collection</code>
 * is any object that responds to <code>objectEnumerator:</code>, and must have the same number of
 * objects as this array.
 *
 * @see <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Objc_classic/Classes/NSArray.html#//apple_ref/doc/uid/20000137-BABCBHFG" class="classLink">
 *			makeObjectsPerformSelector:</a> (NSArray)
 * @see #resultsOfMakeObjectsPerformSelector:
 * @see <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Objc_classic/Classes/NSArray.html#//apple_ref/doc/uid/20000137-BABCJEGJ" class="classLink">
 *			makeObjectsPerformSelector:withObject:</a> (NSArray)
 * @see #resultsOfMakeObjectsPerformSelector:withObject:
 * @see #resultsOfMakeObjectsPerformSelector:withRespectiveObjectsFrom:
 */
- (void)makeObjectsPerformSelector:(SEL)aSelector
         withRespectiveObjectsFrom:(id)collection
{
    NSEnumerator *targetEnumerator = [self objectEnumerator];
    NSEnumerator *argumentEnumerator = [collection objectEnumerator];
    id target;

    while (target = [targetEnumerator nextObject])
    {
        [target performSelector:aSelector withObject:[argumentEnumerator nextObject]];
    }
}

/*!
 * Sends the <code>aSelector</code> message to each object in the array, starting with the first
 * object and continuing through the array to the last object. The message is sent each time with
 * progressive objects from <code>collection</code> as an argument, so the <code>aSelector</code>
 * method must take a single argument of type <code>id</code>. The <code>aSelector</code> method
 * shouldn't, as a side effect, modify the receiving array. This method raises an NSInvalidArgumentException
 * if <code>aSelector</code> is <code>NULL</code> (modified from ADC docs). <code>collection</code>
 * is any object that responds to <code>objectEnumerator:</code>, and must have the same number of
 * objects as this array. The resulting NSArray contains the results of the method calls, using
 * <code>NSNull</code> in place of <code>nil</code>. It has a one-to-one correspondence with the
 * items in this array.
 *
 * @see <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Objc_classic/Classes/NSArray.html#//apple_ref/doc/uid/20000137-BABCBHFG" class="classLink">
 *			makeObjectsPerformSelector:</a> (NSArray)
 * @see #resultsOfMakeObjectsPerformSelector:
 * @see <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Objc_classic/Classes/NSArray.html#//apple_ref/doc/uid/20000137-BABCJEGJ" class="classLink">
 *			makeObjectsPerformSelector:withObject:</a> (NSArray)
 * @see #resultsOfMakeObjectsPerformSelector:withObject:
 * @see #resultsOfMakeObjectsPerformSelector:withRespectiveObjectsFrom:
 */
- (NSArray *)resultsOfMakeObjectsPerformSelector:(SEL)aSelector
                       withRespectiveObjectsFrom:(id)collection
{
    NSEnumerator *targetEnumerator = [self objectEnumerator];
    NSEnumerator *argumentEnumerator = [collection objectEnumerator];
    NSMutableArray *results = [NSMutableArray arrayWithCapacity:[self count]];
    id target;
    id result;

    while (target = [targetEnumerator nextObject])
    {
        result = [target performSelector:aSelector withObject:[argumentEnumerator nextObject]];
        if (result == nil)
            result = [NSNull null];
        [results addObject:result];
    }

    return results;
}

@end
