/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.edgent.analytics.sensors;

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

import org.apache.edgent.function.Function;
import org.apache.edgent.function.Predicate;

/**
 * A generic immutable range of values and a way to 
 * check a value for containment in the range.
 * <p>
 * Useful in filtering in predicates.
 * <p> 
 * A Range consists of a lower and upper endpoint and a {@link BoundType}
 * for each endpoint.
 * <p>
 * {@link BoundType#CLOSED} includes the endpoint's value in the range and
 * is represented as "[" or "]" in the string form for a lower and upper bound
 * type respectively.
 * {@link BoundType#OPEN} excludes the endpoint's value in the range and 
 * is represented as "(" or ")" in the string form for a lower and upper bound
 * type respectively.  e.g. {@code "[2..5)"}
 * <p>
 * Typically, the convenience methods in {@link Ranges} are used to
 * construct a Range.
 * <p>
 * {@link #contains(Comparable) contains()} is used to check for containment:
 * e.g.
 * <pre>{@code
 * Ranges.closed(2,4).contains(2);    // returns true
 * Ranges.open(2,4).contains(2);      // returns false
 * Ranges.atLeast(2).contains(2);     // returns true
 * Ranges.greaterThan(2).contains(2); // returns false
 * Ranges.atMost(2).contains(2);      // returns true
 * Ranges.lessThan(2).contains(2);    // returns false
 * }</pre>
 * 
 * {@link #toString()} yields a convenient string representation and a
 * Range may be created from the string representation.
 * <pre>{@code
 * String s = Ranges.closed(2,4).toString(); // yields "[2..4]"
 * Range<Integer> range = Ranges.valueOfInteger(s); // yields a Range<Integer>(2,4)
 * }</pre>
 * <p>
 * Range works with Gson ({@code new Gson().toJson(Range<T>)}.
 * As as documented by Gson, for generic types you must use
 * {@code Gson.fromJson(String, java.lang.reflect.Type)} to
 * create a Range from its json.
 * <p>
 * Sample use in a TStream context:
 * <pre>{@code
 * TStream<JsonObject> jStream = ...;
 * TStream<JsonObject> filtered = Filters.deadband(jStream,
 *                     json -> json.getProperty("pressureReading").asInteger(),
 *                     Ranges.closed(10, 30));
 * }</pre>
 * 
 * @param <T> a {@link Comparable} value type
 */
public final class Range<T extends Comparable<?>> implements Predicate<T>, Serializable {
    /*
     * Useful in understanding some of the motivations/issues:
     * 
     * This is a lightweight implementation of a subset of the Guava Range.
     * Guava Range is great, but...
     * 
     * Compared to Guava Range:
     * - Guava Range isn't easily separable from the "bulky" Guave package.
     *   Guava Range itself isn't particularly lightweight (depends on numerous
     *   other Guava classes).
     *   This Range is very lightweight.
     * - Guava Range has a large set of static convenience constructors,
     *   whereas we've chosen to make them members of our Ranges class
     *   (along with "Range from Range.toString()" methods)
     * - Guava Range doesn't support unsigned byte/short/int/long type ranges.
     *     This Range adds {@link #contains(Comparable, Comparator)}
     *     and {@link #toStringUnsigned()}.
     * - Guava Range lacks a "Range from Range.toString()" function: https://github.com/google/guava/issues/1911.
     *     Ranges has valueOf*() for convenience with commonly used numeric types,
     *     and Range has valueOf() for general use. 
     * - Guava Range has issues with to/from Json with Gson: 
     *     https://github.com/google/guava/issues/1911.
     *     This Range works but as doc'd by Gson, you must use
     *     {@code Gson#fromJson(String, java.lang.reflect.Type)}</li>
     * - Guava Range's {@code apply(T value)} is documented as deprecated. 
     *     None the less there was a desire that our Range "implement Predicate"
     *     so we do.
     * - Guava Range.toString()
     *   - Guava uses some unprintable characters.
     *     Up to the latest Guava release - 19.0, Range.toString() uses \u2025 for
     *     the ".." separator and uses +/-\u221E for infinity.  That's caused problems:
     *     https://github.com/google/guava/issues/2376.
     *     Guava Range.toString() has been change to use ".." instead of \u2025.
     *     It still uses the unicode char for infinity.
     *     This Range uses ".." for the separator like the not-yet-released Guava change.
     *     For convenience to users, this Range uses "*" and no leading +/- for infinity.</li>
     *   - Guava does not decorate String or Character values with \" or \' respectively.
     *     It does not generate an escaped encoding of the
     *     range separator if it is present in a value.
     *     Hard to guess whether this may change if/when Guava adds a
     *     "Range from Range.toString()" capability.
     */
    
    private static final long serialVersionUID = 1L;
    
    private final T lowerEndpoint;  // null for infinity
    private final T upperEndpoint;  // null for infinity
    private final BoundType lbt;
    private final BoundType ubt;
    private transient int hashCode;
    
    /**
     * Exclude or include an endpoint value in the range.
     */
    public static enum BoundType {/** exclusive */ OPEN, /** inclusive */ CLOSED};
    
    /**
     * Create a new Range<T>.  Private like Guava Range.
     * <p>
     * See {@link Ranges} for a collection of convenience constructors.
     * @param lowerEndpoint null for an infinite value (and lbt must be OPEN)
     * @param lbt {@link BoundType} for the lowerEndpoint
     * @param upperEndpoint null for an infinite value (and ubt must be OPEN)
     * @param ubt {@link BoundType} for the upperEndpoint
     */
    private Range(T lowerEndpoint, BoundType lbt, T upperEndpoint, BoundType ubt) {
        this.lowerEndpoint = lowerEndpoint;
        this.upperEndpoint = upperEndpoint;
        this.lbt = lbt;
        this.ubt = ubt;
        if (lowerEndpoint != null && upperEndpoint != null) {
            if (lowerEndpoint.getClass() != upperEndpoint.getClass())
                throw new IllegalArgumentException("lowerEndpoint and upperEndpoint are not the same type");
        }
        if (lowerEndpoint == null && lbt != BoundType.OPEN)
            throw new IllegalArgumentException("endpoint is null and BoundType != OPEN");
        if (upperEndpoint == null && ubt != BoundType.OPEN)
            throw new IllegalArgumentException("endpoint is null and BoundType != OPEN");
    }

    /**
     * Create a new Range&lt;T&gt;
     * <p>
     * See {@link Ranges} for a collection of convenience constructors.
     * 
     * @param <T> a Comparable type
     * @param lowerEndpoint null for an infinite value (and lbt must be OPEN)
     * @param lbt {@link BoundType} for the lowerEndpoint
     * @param upperEndpoint null for an infinite value (and ubt must be OPEN)
     * @param ubt {@link BoundType} for the upperEndpoint
     * @return the Range
     */
    public static <T extends Comparable<?>> Range<T> range(T lowerEndpoint, BoundType lbt, T upperEndpoint, BoundType ubt) {
        // matchs Guava Range.range param order
        return new Range<T>(lowerEndpoint, lbt, upperEndpoint, ubt);
    }

    /**
     * Returns true if o is a Range having equal endpoints and bound types to this Range.
     */
    @Override
    public boolean equals(Object o) {
        if (o == this) return true;
        if (o instanceof Range) {
            Range<?> r = (Range<?>) o;
            return r.lbt.equals(lbt)
                   && r.ubt.equals(ubt)
                   && (r.lowerEndpoint==null ? r.lowerEndpoint == lowerEndpoint
                                          : r.lowerEndpoint.equals(lowerEndpoint))
                   && (r.upperEndpoint==null ? r.upperEndpoint == upperEndpoint
                                          : r.upperEndpoint.equals(upperEndpoint));
        }
        return false;
    }
    
    @Override
    public int hashCode() {
        if (hashCode == 0)
            hashCode = Objects.hash(lbt, lowerEndpoint, ubt, upperEndpoint);
        return hashCode;
    }

    /**
     * @return true iff the Range's lower endpoint isn't unbounded/infinite
     */
    public boolean hasLowerEndpoint() {
        return lowerEndpoint != null;
    }
    
    /**
     * Get the range's lower endpoint.
     * @return the endpoint
     * @throws IllegalStateException if hasLowerEndpoint()==false
     */
    public T lowerEndpoint() {
        if (hasLowerEndpoint())
            return lowerEndpoint;
        throw new IllegalStateException("unbounded");
    }
    
    /**
     * @return true iff the Range's upper endpoint isn't unbounded/infinite
     */
    public boolean hasUpperEndpoint() {
        return upperEndpoint != null;
    }
    
    /**
     * Get the range's upper endpoint.
     * @return the endpoint
     * @throws IllegalStateException if hasUpperEndpoint()==false
     */
    public T upperEndpoint() {
        if (hasUpperEndpoint())
            return upperEndpoint;
        throw new IllegalStateException("unbounded");
    }
    
    /**
     * Get the BoundType for the lowerEndpoint.
     * @return the BoundType
     */
    public BoundType lowerBoundType() {
        return lbt;
    }
    
    /**
     * Get the BoundType for the upperEndpoint.
     * @return the BoundType
     */
    public BoundType upperBoundType() {
        return ubt;
    }
    
    /**
     * Determine if the Region contains the value.
     * <p>
     * {@code contains(v)} typically suffices.  This
     * can be used in cases where it isn't sufficient.
     * E.g., for unsigned byte comparisons
     * <pre>
     * Comparator&lt;Byte&gt; unsignedByteComparator = new Comparator&lt;Byte&gt;() {
     *     public int compare(Byte b1, Byte b2) {
     *         return Integer.compareUnsigned(Byte.toUnsignedInt(b1), Byte.toUnsignedInt(b2));
     *     }
     *     public boolean equals(Object o2) { return o2==this; }
     *     };
     * Range&lt;Byte&gt; unsignedByteRange = Ranges.valueOfByte("[0..255]");
     * unsignedByteRange.contains(byteValue, unsignedByteComparator);
     * </pre>
     * 
     * @param v the value to check for containment
     * @param cmp the Comparator to use
     * @return true if the Region contains the value
     */
    public boolean contains(T v, Comparator<T> cmp) {
        // N.B. Guava Range lacks such a method.
        if (lowerEndpoint==null) {
            int r = cmp.compare(v, upperEndpoint);
            return ubt == BoundType.OPEN ? r < 0 : r <= 0; 
        }
        if (upperEndpoint==null) {
            int r = cmp.compare(v, lowerEndpoint);
            return lbt == BoundType.OPEN ? r > 0 : r >= 0; 
        }
        int r = cmp.compare(v, upperEndpoint);
        boolean ok1 = ubt == BoundType.OPEN ? r < 0 : r <= 0;
        if (!ok1) 
            return false;
        r = cmp.compare(v, lowerEndpoint);
        return lbt == BoundType.OPEN ? r > 0 : r >= 0; 
    }
    
    /**
     * Determine if the Region contains the value.
     * <p>
     * The Comparable's compareTo() is used for the comparisons.
     * <p>
     * @param v the value to check for containment
     * @return true if the Region contains the value
     * @see #contains(Comparable, Comparator)
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public boolean contains(T v) {
        if (lowerEndpoint==null) {
            int r = ((Comparable)v).compareTo(upperEndpoint);
            return ubt == BoundType.OPEN ? r < 0 : r <= 0; 
        }
        if (upperEndpoint==null) {
            int r = ((Comparable)v).compareTo(lowerEndpoint);
            return lbt == BoundType.OPEN ? r > 0 : r >= 0; 
        }
        int r = ((Comparable)v).compareTo(upperEndpoint);
        boolean ok1 = ubt == BoundType.OPEN ? r < 0 : r <= 0;
        if (!ok1) 
            return false;
        r = ((Comparable)v).compareTo(lowerEndpoint);
        return lbt == BoundType.OPEN ? r > 0 : r >= 0; 
    }

    /**
     * Predicate.test() implementation. Identical to contains(value).
     */
    @Override
    public boolean test(T value) {
        return contains(value);
    }
    
    /**
     * Parse a String from {@link #toString()}
     * 
     * @param str the String
     * @return Four element array with the range's component Strings
     * @throws IllegalArgumentException
     */
    private static String[] parse(String s) {
        char lbc = s.charAt(0);
        if (lbc != '[' && lbc != '(')
            throw new IllegalArgumentException(s);
        String lbs = lbc=='[' ? "[" : "(";
        char ubc = s.charAt(s.length()-1);
        if (ubc != ']' && ubc != ')')
            throw new IllegalArgumentException(s);
        String ubs = ubc==']' ? "]" : ")";
        
        s = s.substring(1,s.length()-1);
        // problematic case: String endpoint with embedded ".."
        // special case Character endpoint with value "."
        String[] parts = new String[2];
        if (s.length() == "....".length()) {
            parts[0] = String.valueOf(s.charAt(0));
            parts[1] = String.valueOf(s.charAt(3));
        }
        else {
            parts = s.split("\\.\\.");
            if (parts.length != 2)
                throw new IllegalArgumentException("A range string endpoint value contains the separator sequence \"..\": " + s);
            if (parts[0].isEmpty() && parts[1].length() > 1) {
                // handles the case Range<String>(".", "anythingElse")
                // Range<String>("anything", ".") falls out OK from split
                parts[0] = parts[1].substring(0, 1);
                parts[1] = parts[1].substring(1);
            }
        }
        
        String les = parts[0];
        String ues = parts[1];

        return new String[]{ lbs, les, ues, ubs };
    }
    
    /**
     * Create a Range from a String produced by toString().
     * <p>
     * See {@link Ranges} for a collection of valueOf methods
     * for several types of {@code T}.
     *
     * @param <T> a Comparable type
     * @param toStringValue value from toString() or has the same syntax.
     * @param fromString function to create a T from its String value from
     *        the parsed toStringValue.  Should throw an IllegalArgumentException
     *        if unable to perform the conversion.
     * @return the Range
     * @throws IllegalArgumentException if unable to parse or convert to 
     *         endpoint in toStringValue to a T.
     */
    public static <T extends Comparable<?>> Range<T> valueOf(String toStringValue, Function<String,T> fromString) {
        // N.B. See note in classdoc wrt Guava Range behavior. i.e., it
        // currently lacks a "Range from Range.toString() analog".
        
        String[] parts = parse(toStringValue);
        BoundType lbt = parts[0] == "[" ? BoundType.CLOSED : BoundType.OPEN;
        String les = parts[1];
        String ues = parts[2];
        BoundType ubt = parts[3] == "]" ? BoundType.CLOSED : BoundType.OPEN;

        T lowerEndpoint = les.equals("*") ? null : fromString.apply(les);
        T upperEndpoint = ues.equals("*") ? null : fromString.apply(ues);
        
        return new Range<T>(lowerEndpoint, lbt, upperEndpoint, ubt);
    }
    
    /**
     * Yields {@code "<lowerBoundType><lowerEndpoint>..<upperEndpoint><upperBoundType>"}.
     * <p>
     * lowerBoundType is either "[" or "(" for BoundType.CLOSED or OPEN respectively.
     * upperBoundType is either "]" or ")" for BoundType.CLOSED or OPEN respectively.
     * <p>
     * The endpoint value "*" is used to indicate an infinite value.
     * Otherwise, endpoint.toString() is used to get the endpoint's value.
     * <p>
     * Likely yields an undesirable result when wanting to treat
     * a Byte, Short, Integer, or Long T in an unsigned fashion.
     * See toStringUnsigned().
     * <p>
     * No special processing is performed to escape/encode a "." present
     * in an endpoint.toString() value.  Hence Range&lt;T&gt;.toString() for
     * a {@code T} of {@code String} (of value "." or with embedded ".."),
     * or some other non-numeric type may yield values that are not amenable
     * to parsing by {@link #valueOf(String, Function)}.
     * <br>
     * .e.g.,
     * <pre>
     * "[120..156)"  // lowerEndpoint=120 inclusive, upperEndpoint=156 exclusive
     * "[120..*)"    // an "atLeast" 120 range
     * </pre> 
     */
    @Override
    public String toString() {
        return toString(endpoint -> endpoint.toString());
    }

    /**
     * Return a String treating the endpoints as an unsigned value.
     * @return String with same form as {@link #toString()}
     * @throws IllegalArgumentException if the Range is not one of
     *         Byte, Short, Integer, Long
     */
    public String toStringUnsigned() {
        return toString(endpoint -> toUnsignedString(endpoint));
    }
    
    private String toString(Function<T,String> toStringFn) {
        // N.B. See note in classdoc wrt Guava Range behavior.
        String[] parts = { "(", "*", "*", ")" };
        if (lowerEndpoint!=null) {
            parts[0] = lbt==BoundType.CLOSED ? "[" : "(";
            parts[1] = toStringFn.apply(lowerEndpoint);
        }
        if (upperEndpoint!=null) {
            parts[2] = toStringFn.apply(upperEndpoint);
            parts[3] = ubt==BoundType.CLOSED ? "]" : ")";
        }
            
        return parts[0]+parts[1]+".."+parts[2]+parts[3];
    }
    
    private static <T> String toUnsignedString(T v) {
        if (v instanceof Byte)
            return Integer.toUnsignedString(Byte.toUnsignedInt((Byte)v));
        else if (v instanceof Short)
            return Integer.toUnsignedString(Short.toUnsignedInt((Short)v));
        else if (v instanceof Integer)
            return Integer.toUnsignedString((Integer)v);
        else if (v instanceof Long)
            return Long.toUnsignedString((Long)v);
        throw new IllegalArgumentException("Not Range of Byte,Short,Integer, or Long"+v.getClass());
    }
    
}
