package cgeo.geocaching.sorting;

import cgeo.geocaching.connector.gc.GCConstants;
import cgeo.geocaching.models.Geocache;
import cgeo.geocaching.utils.Log;

import java.util.Collections;
import java.util.List;

import org.apache.commons.lang3.StringUtils;

/**
 * abstract super implementation for all cache comparators
 *
 */
abstract class AbstractCacheComparator implements CacheComparator {

    @Override
    public final int compare(final Geocache cache1, final Geocache cache2) {
        try {
            final boolean canCompare1 = canCompare(cache1);
            final boolean canCompare2 = canCompare(cache2);
            if (!canCompare1) {
                return canCompare2 ? 1 : fallbackToGeocode(cache1, cache2);
            }
            return canCompare2 ? compareCaches(cache1, cache2) : -1;
        } catch (final Exception e) {
            Log.e("AbstractCacheComparator.compare", e);
            // This may violate the Comparator interface if the exception is not systematic.
            return fallbackToGeocode(cache1, cache2);
        }
    }

    private static int fallbackToGeocode(final Geocache cache1, final Geocache cache2) {
        final int comparePrefix = StringUtils.compareIgnoreCase(StringUtils.substring(cache1.getGeocode(), 0, 2), StringUtils.substring(cache2.getGeocode(), 0, 2));
        if (comparePrefix == 0) {
            return (int) (GCConstants.gccodeToGCId(cache1.getGeocode())
                    - GCConstants.gccodeToGCId(cache2.getGeocode()));
        }
        return comparePrefix;
    }

    /**
     * Check necessary preconditions (like missing fields) before running the comparison itself.
     * Caches not filling the conditions will be placed last, sorted by Geocode.
     *
     * The default implementation returns {@code true} and can be overridden if needed in sub classes.
     *
     * @param cache
     *            the cache to be sorted
     *
     * @return {@code true} if the cache holds the necessary data to be compared meaningfully
     */
    protected boolean canCompare(final Geocache cache) {
        return true;
    }

    /**
     * Compares two caches. Logging and exception handling is implemented outside this method already.
     * <p/>
     * A cache is smaller than another cache if it is desirable to show it first when presented to the user.
     * For example, a highly rated cache must be considered smaller than a poorly rated one.
     *
     * @return an integer < 0 if cache1 is less than cache2, 0 if they are equal, and > 0 if cache1 is greater than
     *         cache2.
     */
    protected abstract int compareCaches(Geocache cache1, Geocache cache2);

    /** Can optinally be overridden to perform preparation (e.g. caching of values) before sort of a list via {@link #sort(List)} */
    protected void beforeSort(final List<Geocache> list) {
        //by default, do nothing
    }

    /** Can optinally be overridden to perform cleanup (e.g. deleting cached values) before sort of a list via {@link #sort(List)} */
    protected void afterSort(final List<Geocache> list) {
        //by default, do nothing
    }

    /** Sorts the given list of caches using this comparator. Respects implementations of {@link #beforeSort(List)} and{@link #afterSort(List)} */
    public void sort(final List<Geocache> list) {
        beforeSort(list);
        Collections.sort(list, this);
        afterSort(list);
    }

}

@@ -119,42 +119,8 @@
 che;
-%0Aimport cgeo.geocaching.utils.Log;
 %0A%0Aim
@@ -451,26 +451,8 @@
 ) %7B%0A
-        try %7B%0A    
     
@@ -507,28 +507,24 @@
 1);%0A        
- 
-   
 final boolea
@@ -563,28 +563,24 @@
 2);%0A        
-    
 if (!canComp
@@ -591,36 +591,32 @@
 ) %7B%0A            
-  
-  
 return canCompar
@@ -671,25 +671,18 @@
     
-    %7D%0A   
+%7D%0A
         
  ret
@@ -669,33 +669,32 @@
       %7D%0A        
- 
 return canCompar
@@ -738,260 +738,8 @@
 -1;%0A
-        %7D catch (final Exception e) %7B%0A            Log.e(%22AbstractCacheComparator.compare%22, e);%0A            // This may violate the Comparator interface if the exception is not systematic.%0A            return fallbackToGeocode(cache1, cache2);%0A        %7D%0A
     
@@ -1045,22 +1045,24 @@
     
-return (int) (
+final long l1 = 
 GCCo
@@ -1102,16 +1102,17 @@
 ocode())
+;
 %0A       
@@ -1120,17 +1120,23 @@
     
-        -
+final long l2 =
  GCC
@@ -1177,18 +1177,100 @@
 ocode())
-)
 ;
+%0A            if (l1 != l2) %7B%0A                return l1 %3E l2 ? 1 : -1;%0A            %7D
 %0A       

fix #12803: remove suspicious code in comparator, prevent overflow on long compare