//
//  NSArrayAdditions.java
//  WOGroovy
//

package wogroovy.additions;

import com.webobjects.foundation.*;
import com.webobjects.eocontrol.*;
import er.extensions.*;
import java.util.*;
import groovy.lang.*;
import org.codehaus.groovy.runtime.InvokerHelper;


public class NSArrayAdditions {

    //
    // instance creation
    //
    
    public static NSArray
        arrayByAddingObjectsFromArrayWithoutDuplicates(NSArray self,
                                                       NSArray other) {
        return
            ERXArrayUtilities.arrayByAddingObjectsFromArrayWithoutDuplicates(self, other);
    }

    public static NSDictionary dictionaryGroupedByKeyPath(NSArray self, String keyPath) {
        return ERXArrayUtilities.arrayGroupedByKeyPath(self, keyPath);
    }

    public static NSDictionary dictionaryGroupedByKeyPath(NSArray self,
                                                          String keyPath,
                                                          boolean includeNulls,
                                                          String extraKeyPathForValues) {
        return ERXArrayUtilities.arrayGroupedByKeyPath(self, keyPath, includeNulls,
                                                       extraKeyPathForValues);
    }

    public static NSDictionary dictionaryGroupedByToManyKeyPath(NSArray self,
                                                                String keyPath,
                                                                boolean includeNulls) {
        return
            ERXArrayUtilities.arrayGroupedByToManyKeyPath(self, keyPath, includeNulls);
    }

    public static NSArray arrayWithoutDuplicateKeyValue(NSArray self, String key) {
        return ERXArrayUtilities.arrayWithoutDuplicateKeyValue(self, key);
    }

    public static NSArray arrayWithoutDuplicates(NSArray self) {
        return ERXArrayUtilities.arrayWithoutDuplicates(self);
    }

    public static String friendlyDisplayForKeyPath(NSArray self,
                                                   String attribute,
                                                   String nullArrayDisplay,
                                                   String separator,
                                                   String finalSeparator) {
        return ERXArrayUtilities.friendlyDisplayForKeyPath(self, attribute,
                                                           nullArrayDisplay, separator,
                                                           finalSeparator);
    }

    public static NSArray intersectingElements(NSArray self, NSArray other) {
        return ERXArrayUtilities.intersectingElements(self, other);
    }

    public static List list(NSArray self) {
        return new ArrayList(self.vector());
    }

    public static EOArrayDataSource dataSource(NSArray self) {
        return ERXUtilities.dataSourceForArray(self);
    }

    public static NSSet set(NSArray self) {
        return ERXUtilities.setFromArray(self);
    }


    //
    // testing
    //
    
    public static boolean containsAnyObjectFromArray(NSArray self,
                                                     NSArray objects) {
        return ERXArrayUtilities.arrayContainsAnyObjectFromArray(self, objects);
    }

    public static boolean containsArray(NSArray self, NSArray objects) {
        return ERXArrayUtilities.arrayContainsArray(self, objects);
    }

    public static boolean areIdenticalSets(NSArray self, NSArray other) {
        return ERXArrayUtilities.arraysAreIdenticalSets(self, other);
    }

    
    //
    // computing
    //
    
    public static Object computeAvgForKey(NSArray self, String key) {
        return self.valueForKeyPath("@" + NSArray.AverageOperatorName + "." + key);
    }
    
    public static Object computeCountForKey(NSArray self, String key) {
        return self.valueForKeyPath("@" + NSArray.CountOperatorName + "." + key);
    }
    
    public static Object computeMaxForKey(NSArray self, String key) {
        return self.valueForKeyPath("@" + NSArray.MaximumOperatorName + "." + key);
    }
    
    public static Object computeMinForKey(NSArray self, String key) {
        return self.valueForKeyPath("@" + NSArray.MinimumOperatorName + "." + key);
    }
    
    public static Object computeSumForKey(NSArray self, String key) {
        return self.valueForKeyPath("@" + NSArray.SumOperatorName + "." + key);
    }


    //
    // accessing
    //
    
    public static Object getAt(NSArray self, int index) {
        return self.objectAtIndex(index);
    }

    public static Object getAt(NSArray self, String key) {
        return self.valueForKey(key);
    }

    public static Object getAt(NSArray self, NSArray paths) {
        return ERXArrayUtilities.valuesForKeyPaths(self, paths);
    }

    public static int count(NSArray self, Object object) {
        int count = 0;
        for (Enumeration e = self.objectEnumerator(); e.hasMoreElements();) {
            if (e.nextElement().equals(object))
                count++;
        }
        return count;
    }
    
    public static NSArray valuesForKeyPaths(NSArray self, NSArray paths) {
        return ERXArrayUtilities.valuesForKeyPaths(self, paths);
    }

    
    //
    // filtering
    //
    
    public static NSArray flatten(NSArray self) {
        return ERXArrayUtilities.flatten(self);
    }
    
    public static NSArray filteredArrayWithQualifier(NSArray self,
                                                     EOQualifier qualifier) {
        return EOQualifier.filteredArrayWithQualifier(self, qualifier);
    }
    
    public static NSArray filteredArrayWithEntityFetchSpecification(NSArray self,
                                                                    String fetchSpec,
                                                                    String entity) {
        return ERXArrayUtilities.filteredArrayWithEntityFetchSpecification(self,
                                                                           fetchSpec,
                                                                           entity);
    }

    public static NSArray
        filteredArrayWithEntityFetchSpecification(NSArray self,
                                                  String entity,
                                                  String fetchSpec,
                                                  NSDictionary bindings) {
        return ERXArrayUtilities.filteredArrayWithEntityFetchSpecification(self,
                                                                           entity,
                                                                           fetchSpec,
                                                                           bindings);
    }

    public static NSArray
        filteredArrayWithQualifierEvaluation(NSArray self,
                                             EOQualifierEvaluation qualifier) {
        return ERXArrayUtilities.filteredArrayWithQualifierEvaluation(self, qualifier);
    }


    //
    // sorting
    //
    
    public static NSArray sortedArrayUsingKeyOrderArray(NSArray self, NSArray sortOrderings) {
        return EOSortOrdering.sortedArrayUsingKeyOrderArray(self, sortOrderings);
    }
    
    public static NSArray sortedArraySortedWithKey(NSArray self,
                                                   String key,
                                                   NSSelector selector) {
        return ERXArrayUtilities.sortedArraySortedWithKey(self, key, selector);
    }

    public static NSMutableArray sortedMutableArraySortedWithKey(NSArray self,
                                                                 String key) {
        return ERXArrayUtilities.sortedMutableArraySortedWithKey(self, key);
    }

    
    //
    // arithmetic
    //
    
    public static NSArray plus(NSArray left, NSArray right) {
        return left.arrayByAddingObjectsFromArray(right);
    }
    
    public static NSArray plus(NSArray left, Object right) {
        return left.arrayByAddingObject(right);
    }
    
    public static NSArray minus(NSArray left, NSArray right) {
        return ERXArrayUtilities.arrayMinusArray(left, right);
    }
    
    public static NSArray minus(NSArray left, Object right) {
        return ERXArrayUtilities.arrayMinusObject(left, right);
    }


    //
    // copying
    //
    
    public static NSArray reverse(NSArray self) {
        return ERXArrayUtilities.reverse(self);
    }

    
    //
    // enumerating
    //
    
    public static void each(NSArray self, Closure closure) {
        for (Enumeration e = self.objectEnumerator(); e.hasMoreElements();) {
            closure.call(e.nextElement());
        }
    }

    public static void eachWithIndex(NSArray self, Closure closure) {
        int counter = 0;
        for (Enumeration e = self.objectEnumerator(); e.hasMoreElements();) {
            Object[] objects = new Object[2];
            objects[0] = e.nextElement();
            objects[1] = new Integer(counter++);
            closure.call(objects);
        }
    }
    
    public static void reverseEach(NSArray self, Closure closure) {
        for (Enumeration e = self.reverseObjectEnumerator(); e.hasMoreElements();) {
            closure.call(e.nextElement());
        }
    }
    
    public static NSArray collect(NSArray self, Closure closure) {
        NSMutableArray answer = new NSMutableArray(self);
        for (Enumeration e = self.objectEnumerator(); e.hasMoreElements();) {
            answer.addObject(closure.call(e.nextElement()));
            if (closure.getDirective() == Closure.DONE) {
            	break;
            }
        }
        return answer;
    }

    public static Object find(NSArray self, Closure closure) {
        for (Enumeration e = self.objectEnumerator(); e.hasMoreElements();) {
            Object value = e.nextElement();
            if (InvokerHelper.asBool(closure.call(value))) {
                return value;
            }
        }
        return null;
    }

    public static NSArray findAll(NSArray self, Closure closure) {
        NSMutableArray answer = new NSMutableArray(self);
        for (Enumeration e = self.objectEnumerator(); e.hasMoreElements();) {
            Object value = e.nextElement();
            if (InvokerHelper.asBool(closure.call(value))) {
                answer.addObject(value);
            }
        }
        return answer;
    }

    public static Object inject(NSArray self, Object value, Closure closure) {
        Object[] params = new Object[2];
        for (Enumeration e = self.objectEnumerator(); e.hasMoreElements();) {
            Object item = e.nextElement();
            params[0] = value;
            params[1] = item;
            value = closure.call(params);
        }
        return value;
    }


    //
    // encoding
    //

    public static NSDictionary dictionaryOfFormValues(NSArray self,
                                                      String separator,
                                                      boolean encrypt) {
        return ERXEOEncodingUtilities.
            dictionaryOfFormValuesForEnterpriseObjects(self, separator, encrypt);
    }
                                                                              
    public static String stringByEncodingPrimaryKeys(NSArray self,
                                                     String separator,
                                                     boolean encrypt) {
        return ERXEOEncodingUtilities.
            encodeEnterpriseObjectsPrimaryKeyForUrl(self, separator, encrypt);
    }

}
