package haskell.prelude;

import haskell.lang.Exp;

public abstract class AbstractOrd<A extends AbstractOrd<A>>
        extends AbstractEq<A>
        implements Ord<A> {

    protected AbstractOrd(final java.lang.String name) {
        super(name);
    }

    protected AbstractOrd(
            final java.lang.String name,
            final Internal internal) {
        super(name, internal);
    }

    protected AbstractOrd(final Exp<A> expression) {
        super(expression);
    }

    // ---- class Eq

    protected Eq.Support<A> _Eq_() {
        return _Ord_();
    }

    // ---- class Ord

    /**
     * this < x
     */
    @SuppressWarnings("unchecked")
    public final Bool _lt_(final A x) {
        return _Ord_().lt((A) this, x);
    }

    /**
     * this <= x
     */
    @SuppressWarnings("unchecked")
    public final Bool _le_(final A x) {
        return _Ord_().le((A) this, x);
    }

    /**
     * this > x
     */
    @SuppressWarnings("unchecked")
    public final Bool _gt_(final A x) {
        return _Ord_().gt((A) this, x);
    }

    /**
     * this >= x
     */
    @SuppressWarnings("unchecked")
    public final Bool _ge_(final A x) {
        return _Ord_().ge((A) this, x);
    }

    @SuppressWarnings("unchecked")
    protected Ord.Support<A> _Ord_() {
        return new Support((Class<A>) getClass());
    }

    protected static class Support<A extends Ord<A>>
            extends Ord.Support<A> {

        protected Support(final java.lang.Class<A> a) {
            super(a);
        }

        /**
         * x == y
         */
        @Override
        public Bool eq(final A x, final A y) {
            return Bool.valueOf(x.equals(y));
        }

        /**
         * compare x y
         */
        @Override
        public Ordering compare(final A x, final A y) {
            return Ordering.valueOf(x.compareTo(y));
        }

    }

}
