package org.opengroupware.jope.eocontrol;

import java.util.Comparator;

import org.opengroupware.jope.foundation.NSKeyValueCodingAdditions;
import org.opengroupware.jope.foundation.NSObject;

/*
 * EOSortOrderingComparator
 * 
 * Used by EOSortOrdering.sort to sort a list based on an array of sort
 * orderings.
 */
public class EOSortOrderingComparator extends NSObject
  implements Comparator
{
  protected EOSortOrdering[] sortOrderings = null;
  
  public EOSortOrderingComparator(EOSortOrdering[] _orderings) {
    this.sortOrderings = _orderings;
  }

  @SuppressWarnings("unchecked")
  public int compare(Object _obj1, Object _obj2) {
    // TODO: this needs a unit test
    for (int i = 0; i < this.sortOrderings.length; i++) {
      String key = this.sortOrderings[i].key();
      Object sel = this.sortOrderings[i].selector();
      int    result;
      
      Object v1 = NSKeyValueCodingAdditions.Utility.valueForKeyPath(_obj1, key);
      Object v2 = NSKeyValueCodingAdditions.Utility.valueForKeyPath(_obj2, key);
      
      boolean isAsc = (sel == EOSortOrdering.EOCompareAscending || 
                       sel == EOSortOrdering.EOCompareCaseInsensitiveAscending);
      
      if (v1 == v2)
        result = 0 /* same */;
      else if (v1 == null)
        result = isAsc ? -1 : 1;
      else if (v2 == null)
        result = isAsc ? 1 : -1;
      else {
        if (sel == EOSortOrdering.EOCompareCaseInsensitiveAscending ||
            sel == EOSortOrdering.EOCompareCaseInsensitiveDescending) {
          if (v1 instanceof String)
            v1 = ((String)v1).toLowerCase();
          if (v2 instanceof String)
            v2 = ((String)v2).toLowerCase();
        }
      
        Comparable c1 = (Comparable)v1;
        result = c1.compareTo(v2);
      }
      
      if (result != 0 /* same */)
        return result;
    }
    return 0 /* same */;
  }
}
