/* UtilLib - Copyright (c) 2012 Vincent Calame - Exemole
 * Logiciel libre donné sous triple licence :
 * 1) selon les termes de la CeCILL V2
 * 2) selon les termes de l’EUPL V.1.1
 * 3) selon les termes de la GNU GPLv3
 * Voir le fichier licences.txt
 */


package net.mapeadores.util.primitives;

import net.mapeadores.util.exceptions.SwitchException;


/**
 *
 * @author Vincent Calame
 */
public class DecimalLongFilterFactory {

    private final static short EQUALS = 0;
    private final static short MINUS = -1;
    private final static short PLUS = 1;

    private DecimalLongFilterFactory() {
    }

    public static DecimalLongFilter newInstance(long decimalLong) {
        return newTypeInstance(decimalLong, EQUALS);
    }

    private static UniqueDecimalLongFilter newTypeInstance(long decimalLong, short equalityType) {
        return new UniqueDecimalLongFilter(decimalLong, equalityType);
    }

    public static DecimalLongFilter newInstance(long decimalLong1, long decimalLong2) {
        if (decimalLong1 == decimalLong2) {
            return newInstance(decimalLong1);
        }
        if (decimalLong1 > decimalLong2) {
            return newInstance(decimalLong2, decimalLong1);
        }
        UniqueDecimalLongFilter decimalLongFilter1 = newTypeInstance(decimalLong1, PLUS);
        UniqueDecimalLongFilter decimalLongFilter2 = newTypeInstance(decimalLong2, MINUS);
        return new DecimalLongFilterFactory.DoubleDecimalLongFilter(decimalLongFilter1, decimalLongFilter2);

    }

    public static String toString(DecimalLongFilter decimalLongFilter, char decimalSeparator) {
        if (decimalLongFilter instanceof UniqueDecimalLongFilter) {
            return DecimalLong.toString(((UniqueDecimalLongFilter) decimalLongFilter).filterDecimalLong, decimalSeparator);
        }
        if (decimalLongFilter instanceof DecimalLongFilterFactory.DoubleDecimalLongFilter) {
            DecimalLongFilterFactory.DoubleDecimalLongFilter doubleDecimalLongFilter = (DecimalLongFilterFactory.DoubleDecimalLongFilter) decimalLongFilter;
            return DecimalLong.toString(doubleDecimalLongFilter.decimalLongFilter1.filterDecimalLong, decimalSeparator) + "; " + DecimalLong.toString(doubleDecimalLongFilter.decimalLongFilter2.filterDecimalLong, decimalSeparator);
        }
        return "";
    }

    private static boolean test(short equalityType, long decimalLong, long filterDecimalLong) {
        switch (equalityType) {
            case EQUALS:
                return (decimalLong == filterDecimalLong);
            case PLUS:
                return (decimalLong >= filterDecimalLong);
            case MINUS:
                return (decimalLong <= filterDecimalLong);
            default:
                throw new SwitchException("Unkonw type: " + equalityType);
        }
    }


    private static class UniqueDecimalLongFilter implements DecimalLongFilter {

        private long filterDecimalLong;
        private short equalityType;

        private UniqueDecimalLongFilter(long filterDecimalLong, short equalityType) {
            this.filterDecimalLong = filterDecimalLong;
            this.equalityType = equalityType;
        }

        public boolean containsDecimalLong(long decimalLong) {
            return test(equalityType, decimalLong, filterDecimalLong);
        }

    }


    private static class DoubleDecimalLongFilter implements DecimalLongFilter {

        private UniqueDecimalLongFilter decimalLongFilter1;
        private UniqueDecimalLongFilter decimalLongFilter2;

        private DoubleDecimalLongFilter(UniqueDecimalLongFilter decimalLongFilter1, UniqueDecimalLongFilter decimalLongFilter2) {
            this.decimalLongFilter1 = decimalLongFilter1;
            this.decimalLongFilter2 = decimalLongFilter2;
        }

        public boolean containsDecimalLong(long decimalLong) {
            return (decimalLongFilter1.containsDecimalLong(decimalLong)) && (decimalLongFilter2.containsDecimalLong(decimalLong));
        }

    }

}
