/*
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.test.analytics.sensors;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
import static org.apache.edgent.analytics.sensors.utils.Java7Helper.*;

import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Comparator;

import org.apache.edgent.analytics.sensors.Range;
import org.apache.edgent.analytics.sensors.Ranges;
import org.apache.edgent.function.Function;
import org.apache.edgent.function.Predicate;
import org.junit.Test;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

/**
 * Test Range and Ranges
 */
public class RangeTest {
  
  private <T extends Comparable<?>> void testOutsideOf(Range<T> range, T v) {
      Predicate<T> notPredicate = Ranges.outsideOf(range); 
      assertEquals("outsideOf-"+range+".test("+v+")", !range.test(v), notPredicate.test(v));
  }
    
    private <T extends Comparable<?>> void testContains(Range<T> range, T v, Boolean expected) {
        assertEquals("range"+range+".contains("+v+")", expected, range.contains(v));
    }
    
    private <T extends Comparable<?>> void testPredicate(Range<T> range, T v, Boolean expected) {
        assertEquals("range"+range+".test("+v+")", expected, range.test(v));
    }
    
    private <T extends Comparable<?>> void testToString(Range<T> range, String expected) {
        assertEquals("range.toString()", expected, range.toString());
    }
    
    private <T extends Comparable<?>> void testToStringUnsigned(Range<T> range, String expected) {
        assertEquals("range.toString()", expected, range.toStringUnsigned());
    }

    private <T extends Comparable<?>> void testValueOf(Function<String,Range<T>> valueOf, Range<T> expected) {
        assertEquals("Ranges.valueOf(\""+expected.toString()+"\")", 
                valueOf.apply(expected.toString()), expected);
    }
    
    private <T extends Comparable<?>> void testEquals(Range<T> r1, Range<T> r2, Boolean expected) {
        assertEquals("range"+r1+".equals(range"+r2+")", expected, r1.equals(r2));
    }
    
    private <T extends Comparable<?>> void testHashCode(Range<T> range, int hashCode, Boolean expected) {
        if (expected)
            assertEquals("range"+range+".hashCode()", hashCode, range.hashCode());
        else
            assertFalse("range"+range+".hashCode()", hashCode == range.hashCode());
    }
    
    private <T extends Comparable<?>> void testJson(Range<T> r1, Type typeOfT) {
        String json = new Gson().toJson(r1);
        Range<T> r2 = new Gson().fromJson(json, typeOfT);
        assertEquals("json="+json+" typeOfT="+typeOfT, r1, r2);
    }
    
    /*
     * Thoroughly test all aspects of Range/Ranges for Integers
     */
    
    @Test
    public void testContainsOpen() {
        testContains(Ranges.open(2,4), 1, false);
        testContains(Ranges.open(2,4), 2, false);
        testContains(Ranges.open(2,4), 3, true);
        testContains(Ranges.open(2,4), 4, false);
        testContains(Ranges.open(2,4), 5, false);
    }

    @Test
    public void testContainsClosed() {
        testContains(Ranges.closed(2,4), 1, false);
        testContains(Ranges.closed(2,4), 2, true);
        testContains(Ranges.closed(2,4), 3, true);
        testContains(Ranges.closed(2,4), 4, true);
        testContains(Ranges.closed(2,4), 5, false);
    }

    @Test
    public void testContainsOpenClosed() {
        testContains(Ranges.openClosed(2,4), 1, false);
        testContains(Ranges.openClosed(2,4), 2, false);
        testContains(Ranges.openClosed(2,4), 3, true);
        testContains(Ranges.openClosed(2,4), 4, true);
        testContains(Ranges.openClosed(2,4), 5, false);
    }

    @Test
    public void testContainsClosedOpen() {
        testContains(Ranges.closedOpen(2,4), 1, false);
        testContains(Ranges.closedOpen(2,4), 2, true);
        testContains(Ranges.closedOpen(2,4), 3, true);
        testContains(Ranges.closedOpen(2,4), 4, false);
        testContains(Ranges.closedOpen(2,4), 5, false);
    }

    @Test
    public void testContainsGreaterThan() {
        testContains(Ranges.greaterThan(2), 1, false);
        testContains(Ranges.greaterThan(2), 2, false);
        testContains(Ranges.greaterThan(2), 3, true);
    }

    @Test
    public void testContainsAtLeast() {
        testContains(Ranges.atLeast(2), 1, false);
        testContains(Ranges.atLeast(2), 2, true);
        testContains(Ranges.atLeast(2), 3, true);
    }

    @Test
    public void testContainsLessThan() {
        testContains(Ranges.lessThan(2), 1, true);
        testContains(Ranges.lessThan(2), 2, false);
        testContains(Ranges.lessThan(2), 3, false);
    }

    @Test
    public void testContainsAtMost() {
        testContains(Ranges.atMost(2), 1, true);
        testContains(Ranges.atMost(2), 2, true);
        testContains(Ranges.atMost(2), 3, false);
    }

    @Test
    public void testContainsSingleton() {
        testContains(Ranges.singleton(2), 1, false);
        testContains(Ranges.singleton(2), 2, true);
        testContains(Ranges.singleton(2), 3, false);
    }
    
    @Test
    public void testPredicate() {
        testPredicate(Ranges.closed(2,4), 1, false);
        testPredicate(Ranges.closed(2,4), 2, true);
        testPredicate(Ranges.closed(2,4), 3, true);
        testPredicate(Ranges.closed(2,4), 4, true);
        testPredicate(Ranges.closed(2,4), 5, false);
    }
    
    @Test
    public void testOutsideOf() {
        testOutsideOf(Ranges.closed(2,4), 1);
        testOutsideOf(Ranges.closed(2,4), 2);
        testOutsideOf(Ranges.closed(2,4), 3);
        testOutsideOf(Ranges.closed(2,4), 4);
        testOutsideOf(Ranges.closed(2,4), 5);
    }

    @Test
    public void testEquals() {
        testEquals(Ranges.closed(2,4), Ranges.closed(2,4), true);
        testEquals(Ranges.closed(2,4), Ranges.closed(2,3), false);
        testEquals(Ranges.closed(3,4), Ranges.closed(2,4), false);
        testEquals(Ranges.atMost(2), Ranges.atMost(2), true);
        testEquals(Ranges.atMost(2), Ranges.atMost(3), false);
        testEquals(Ranges.atLeast(2), Ranges.atLeast(2), true);
        testEquals(Ranges.atLeast(2), Ranges.atLeast(3), false);
        testEquals(Ranges.closed(2,2), Ranges.singleton(2), true);
    }

    @Test
    public void testHashCode() {
        testHashCode(Ranges.atMost(2), Ranges.atMost(2).hashCode(), true);
        testHashCode(Ranges.atMost(2), 0, false);
        testHashCode(Ranges.atMost(2), Ranges.atMost(3).hashCode(), false);
        testHashCode(Ranges.atLeast(2), Ranges.atMost(2).hashCode(), false);
    }
    
    @Test
    public void testEndpointAccess() {
        // {lower,upper}Endpoint(),
        // has{Lower,Upper}Endpoint()
        // {lower,upper}BoundType()
        Range<Integer> r1 = Ranges.openClosed(2,4);
        assertEquals(Range.BoundType.OPEN, r1.lowerBoundType());
        assertTrue(r1.hasLowerEndpoint());
        assertEquals(2, r1.lowerEndpoint().intValue());
        assertTrue(r1.hasUpperEndpoint());
        assertEquals(4, r1.upperEndpoint().intValue());
        assertEquals(Range.BoundType.CLOSED, r1.upperBoundType());

        Range<Integer> r2 = Ranges.openClosed(2,4);
        assertNotSame(r1, r2);
        
        Range<Integer> r3 = Ranges.atMost(2);
        assertFalse(r3.hasLowerEndpoint());
        try {
            r3.lowerEndpoint();
            assertTrue(false);
        }
        catch (IllegalStateException e) {
            // expected
        }
        
        r3 = Ranges.atLeast(2);
        assertFalse(r3.hasUpperEndpoint());
        try {
            r3.upperEndpoint();
            assertTrue(false);
        }
        catch (IllegalStateException e) {
            // expected
        }
    }

    @Test
    public void testToString() {
        testToString(Ranges.open(2,4), "(2..4)");
        testToString(Ranges.closed(2,4), "[2..4]");
        testToString(Ranges.openClosed(2,4), "(2..4]");
        testToString(Ranges.closedOpen(2,4), "[2..4)");
        testToString(Ranges.greaterThan(2), "(2..*)");
        testToString(Ranges.atLeast(2), "[2..*)");
        testToString(Ranges.lessThan(2), "(*..2)");
        testToString(Ranges.atMost(2), "(*..2]");
    }

    @Test
    public void testValueOf() {
        testValueOf(s -> Ranges.valueOfInteger(s), Ranges.open(2, 4));
        testValueOf(s -> Ranges.valueOfInteger(s), Ranges.closed(2, 4));
        testValueOf(s -> Ranges.valueOfInteger(s), Ranges.openClosed(2, 4));
        testValueOf(s -> Ranges.valueOfInteger(s), Ranges.closedOpen(2, 4));
        testValueOf(s -> Ranges.valueOfInteger(s), Ranges.greaterThan(2));
        testValueOf(s -> Ranges.valueOfInteger(s), Ranges.atLeast(2));
        testValueOf(s -> Ranges.valueOfInteger(s), Ranges.lessThan(2));
        testValueOf(s -> Ranges.valueOfInteger(s), Ranges.atMost(2));
    }

    
    /*
     * Thoroughly test contains() and valueOf() for other types of T
     */

    @Test
    public void testContainsOtherByte() {
        testContains(Ranges.open((byte)2,(byte)4), (byte)1, false);
        testContains(Ranges.open((byte)2,(byte)4), (byte)2, false);
        testContains(Ranges.open((byte)2,(byte)4), (byte)3, true);
        testContains(Ranges.open((byte)2,(byte)4), (byte)4, false);
        testContains(Ranges.open((byte)2,(byte)4), (byte)5, false);
    }

    @Test
    public void testContainsOtherShort() {
        testContains(Ranges.open((short)2,(short)4), (short)1, false);
        testContains(Ranges.open((short)2,(short)4), (short)2, false);
        testContains(Ranges.open((short)2,(short)4), (short)3, true);
        testContains(Ranges.open((short)2,(short)4), (short)4, false);
        testContains(Ranges.open((short)2,(short)4), (short)5, false);
    }

    @Test
    public void testContainsOtherLong() {
        testContains(Ranges.open(2L,4L), 1L, false);
        testContains(Ranges.open(2L,4L), 2L, false);
        testContains(Ranges.open(2L,4L), 3L, true);
        testContains(Ranges.open(2L,4L), 4L, false);
        testContains(Ranges.open(2L,4L), 5L, false);
    }

    @Test
    public void testContainsOtherFloat() {
        testContains(Ranges.open(2f,4f), 1f, false);
        testContains(Ranges.open(2f,4f), 2f, false);
        testContains(Ranges.open(2f,4f), 2.001f, true);
        testContains(Ranges.open(2f,4f), 3.999f, true);
        testContains(Ranges.open(2f,4f), 4f, false);
        testContains(Ranges.open(2f,4f), 5f, false);
    }

    @Test
    public void testContainsOtherDouble() {
        testContains(Ranges.open(2d,4d), 1d, false);
        testContains(Ranges.open(2d,4d), 2d, false);
        testContains(Ranges.open(2d,4d), 2.001d, true);
        testContains(Ranges.open(2d,4d), 3.999d, true);
        testContains(Ranges.open(2d,4d), 4d, false);
        testContains(Ranges.open(2d,4d), 5d, false);
    }

    @Test
    public void testContainsOtherBigInteger() {
        testContains(Ranges.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(1), false);
        testContains(Ranges.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(2), false);
        testContains(Ranges.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(3), true);
        testContains(Ranges.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(4), false);
        testContains(Ranges.open(BigInteger.valueOf(2),BigInteger.valueOf(4)), BigInteger.valueOf(5), false);
    }

    @Test
    public void testContainsOtherBigDecimal() {
        testContains(Ranges.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(1), false);
        testContains(Ranges.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(2), false);
        testContains(Ranges.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(2.001), true);
        testContains(Ranges.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(3.999), true);
        testContains(Ranges.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(4), false);
        testContains(Ranges.open(new BigDecimal(2),new BigDecimal(4)), new BigDecimal(5), false);
    }

    @Test
    public void testContainsOtherString() {
        testContains(Ranges.open("b","d"), "a", false);
        testContains(Ranges.open("b","d"), "b", false);
        testContains(Ranges.open("b","d"), "bc", true);
        testContains(Ranges.open("b","d"), "c", true);
        testContains(Ranges.open("b","d"), "cd", true);
        testContains(Ranges.open("b","d"), "d", false);
        testContains(Ranges.open("b","d"), "de", false);
        testContains(Ranges.open("b","d"), "e", false);
    }

    @Test
    public void testContainsOtherCharacter() {
        testContains(Ranges.open('b','d'), 'a', false);
        testContains(Ranges.open('b','d'), 'b', false);
        testContains(Ranges.open('b','d'), 'c', true);
        testContains(Ranges.open('b','d'), 'd', false);
        testContains(Ranges.open('b','d'), 'e', false);
    }

    @Test
    public void testValueOfOtherT() {
        testValueOf(s -> Ranges.valueOfShort(s), Ranges.open((short)2, (short)4));
        testValueOf(s -> Ranges.valueOfByte(s), Ranges.open((byte)2, (byte)4));
        testValueOf(s -> Ranges.valueOfLong(s), Ranges.open(2L, 4L));
        testValueOf(s -> Ranges.valueOfFloat(s), Ranges.open(2.128f, 4.25f));
        testValueOf(s -> Ranges.valueOfDouble(s), Ranges.open(2.128d, 4.25d));
        testValueOf(s -> Ranges.valueOfBigInteger(s), Ranges.open(BigInteger.valueOf(2), BigInteger.valueOf(4)));
        testValueOf(s -> Ranges.valueOfBigDecimal(s), Ranges.open(new BigDecimal(2.5), new BigDecimal(4.25)));
        testValueOf(s -> Ranges.valueOfString(s), Ranges.open("ab", "fg"));
        testValueOf(s -> Ranges.valueOfString(s), Ranges.open("ab", "."));
        testValueOf(s -> Ranges.valueOfString(s), Ranges.open(".", "ab"));
        testValueOf(s -> Ranges.valueOfCharacter(s), Ranges.open('a', 'f'));
        testValueOf(s -> Ranges.valueOfCharacter(s), Ranges.open('a', '.'));
        testValueOf(s -> Ranges.valueOfCharacter(s), Ranges.open('.', '.'));
        testValueOf(s -> Ranges.valueOfCharacter(s), Ranges.open('.', 'f'));

        // problem cases Range<String> with embedded ".."
        try { 
            testValueOf(s -> Ranges.valueOfString(s), Ranges.open("ab..c", "fg"));
            assertTrue(false);
        } catch (IllegalArgumentException e) { /* expected */ }
        try { 
            testValueOf(s -> Ranges.valueOfString(s), Ranges.open("ab", "fg..h"));
            assertTrue(false);
        } catch (IllegalArgumentException e) { /* expected */ }
        try { 
            testValueOf(s -> Ranges.valueOfString(s), Ranges.open("ab..c", "fg..h"));
            assertTrue(false);
        } catch (IllegalArgumentException e) { /* expected */ }
    }
    
    /*
     * Test unsigned handling.
     * toUnsignedString() and compare(T, Comparator<T>)
     */
    @Test
    public void testToUnsignedString() {
        testToStringUnsigned(Ranges.open((byte)0,(byte)255), "(0..255)");
        testToStringUnsigned(Ranges.closed((byte)0,(byte)255), "[0..255]");
        testToStringUnsigned(Ranges.open((short)0,(short)0xFFFF), "(0..65535)");
        testToStringUnsigned(Ranges.open(0,0xFFFFFFFF), "(0.."+ intToUnsignedString(0xFFFFFFFF)+")");
        testToStringUnsigned(Ranges.open(0L,0xFFFFFFFFFFFFFFFFL), "(0.."+longToUnsignedString(0xFFFFFFFFFFFFFFFFL)+")");
    }

    @Test
    public void testContainsUnsigned() {
        // Unsigned Byte ======================
        Comparator<Byte> unsignedByteComparator = new Comparator<Byte>() {
            public int compare(Byte v1, Byte v2) {
                return intCompareUnsigned(byteToUnsignedInt(v1), byteToUnsignedInt(v2));
            }
            public boolean equals(Object o2) { return o2==this; }
            };
            
        Range<Byte> byteRange = Ranges.closed((byte)5, (byte)255); // intend unsigned
        assertFalse(byteRange.contains((byte)6));  // not <= -1
        assertTrue(byteRange.contains((byte)6, unsignedByteComparator));
        assertFalse(byteRange.contains((byte)0xF0)); // not >= 5
        assertTrue(byteRange.contains((byte)0xF0, unsignedByteComparator));
        
        // Unsigned Short ======================
        Comparator<Short> unsignedShortComparator = new Comparator<Short>() {
            public int compare(Short v1, Short v2) {
                return intCompareUnsigned(shortToUnsignedInt(v1), shortToUnsignedInt(v2));
            }
            public boolean equals(Object o2) { return o2==this; }
            };
        Range<Short> shortRange = Ranges.closed((short)5, (short)0xFFFF); // intend unsigned
        assertFalse(shortRange.contains((short)6));  // not <= -1
        assertTrue(shortRange.contains((short)6, unsignedShortComparator));
        assertFalse(shortRange.contains((short)0xFFF0)); // not >= 5
        assertTrue(shortRange.contains((short)0xFFF0, unsignedShortComparator));
        
        // Unsigned Integer ======================
        Comparator<Integer> unsignedIntegerComparator = new Comparator<Integer>() {
            public int compare(Integer v1, Integer v2) {
                return intCompareUnsigned(v1, v2);
            }
            public boolean equals(Object o2) { return o2==this; }
            };
        Range<Integer> intRange = Ranges.closed(5, 0xFFFFFFFF); // intend unsigned
        assertFalse(intRange.contains(6));  // not <= -1
        assertTrue(intRange.contains(6, unsignedIntegerComparator));
        assertFalse(intRange.contains(0xFFFFFFF0)); // not >= 5
        assertTrue(intRange.contains(0xFFFFFFF0, unsignedIntegerComparator));
        
        // Unsigned Long ======================
        Comparator<Long> unsignedLongComparator = new Comparator<Long>() {
            public int compare(Long v1, Long v2) {
                return longCompareUnsigned(v1, v2);
            }
            public boolean equals(Object o2) { return o2==this; }
            };
        Range<Long> longRange = Ranges.closed(5L, 0xFFFFFFFFFFFFFFFFL); // intend unsigned
        assertFalse(longRange.contains(6L));  // not <= -1
        assertTrue(longRange.contains(6L, unsignedLongComparator));
        assertFalse(longRange.contains(0xFFFFFFFFFFFFFFF0L));  // not >= 5
        assertTrue(longRange.contains(0xFFFFFFFFFFFFFFF0L, unsignedLongComparator));
    }

    @Test
    public void testJsonAllTypes() {
        // json = new Gson().toJson(Range<T>);
        // range = new Gson().fromJson(json, typeOfT);
        testJson(Ranges.closed(1, 10), new TypeToken<Range<Integer>>(){}.getType());
        testJson(Ranges.closed((short)1, (short)10), new TypeToken<Range<Short>>(){}.getType());
        testJson(Ranges.closed((byte)1, (byte)10), new TypeToken<Range<Byte>>(){}.getType());
        testJson(Ranges.closed(1L, 10L), new TypeToken<Range<Long>>(){}.getType());
        testJson(Ranges.closed(1f, 10f), new TypeToken<Range<Float>>(){}.getType());
        testJson(Ranges.closed(1d, 10d), new TypeToken<Range<Double>>(){}.getType());
        testJson(Ranges.closed(BigInteger.valueOf(1), BigInteger.valueOf(10)), new TypeToken<Range<BigInteger>>(){}.getType());
        testJson(Ranges.closed(BigDecimal.valueOf(1), BigDecimal.valueOf(10)), new TypeToken<Range<BigDecimal>>(){}.getType());
        testJson(Ranges.closed("ab", "fg"), new TypeToken<Range<String>>(){}.getType());
        testJson(Ranges.closed("ab..c", "fg"), new TypeToken<Range<String>>(){}.getType());
        testJson(Ranges.closed('a', 'f'), new TypeToken<Range<Character>>(){}.getType());
        testJson(Ranges.closed('.', 'f'), new TypeToken<Range<Character>>(){}.getType());
        testJson(Ranges.closed('.', '.'), new TypeToken<Range<Character>>(){}.getType());
        testJson(Ranges.closed('a', '.'), new TypeToken<Range<Character>>(){}.getType());
    }

}
