/*
 * @author Ranides Atterwim {@literal <ranides@gmail.com>}
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */
package net.ranides.assira.collection;

import java.io.Serializable;
import java.util.Comparator;

/**
 * An abstract class for comparison primitive int values.
 *
 * @see java.util.Comparator
 */
public interface IntComparator extends Comparator<Integer>, Serializable {

    /**
     * Default comparator: ascending ordering
     */
    IntComparator ASC = Integer::compare;

    /**
     * Default comparator: descending ordering
     */
    IntComparator DESC = ASC.reversed();

    /**
     * non-generic version of {@link #compare(Integer, Integer)}
     * @param a a
     * @param b b
     * @return int
     */
    int compare(int a, int b);

    @Override
    default int compare(Integer a, Integer b) {
        return compare(a.intValue(), b.intValue());
    }
    
    @Override
    default IntComparator reversed() {
        IntComparator that = this;
        return (int a, int b) -> -that.compare(a, b);
    }

    /**
     * Wraps generic comparator into a type-specific.
     *
     * <P>This method wraps a standard comparator into a type-specific one which
     * will handle the type conversions for you. Of course, any attempt to wrap
     * an comparator comparing the instances of the wrong class will generate a
     * {@link ClassCastException} (possibly very late).
     *
     * <P>If {@code comparator} is already type-specific, it will be returned and no new
     * object will be generated.
     *
     * @param comparator comparator
     * @return a type-specific comparator backed by {@code comparator}.
     */
    static IntComparator wrap(Comparator<? super Integer> comparator) {
        if (comparator == null || comparator instanceof IntComparator) {
            return (IntComparator) comparator;
        } else {
            return (int a, int b) -> comparator.compare(a, b);
        }
    }

    /**
     * Wraps generic comparator into a type-specific comparator.
     * It is type unsafe version which accepts any comparator, not only correct ones (Integer).
     * @param comparator comparator
     * @return a type-specific comparator
     */
    @SuppressWarnings("unchecked")
    static IntComparator $wrap(Comparator<?> comparator) {
        return wrap((Comparator)comparator);
    }
    
}
