package uk.ac.ebi.quickgo.annotation.model;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;

/**
 * Tests the behaviour of the {@link StatisticsByType} class.
 */
public class StatisticsByTypeTest {
    @Rule
    public ExpectedException thrown = ExpectedException.none();

    @Test
    public void nullTypeThrowsException() {
        String type = null;

        thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage("Statistics type cannot be null or empty");

        new StatisticsByType(type, 0);
    }

    @Test
    public void emptyTypeThrowsException() {
        String type = "";

        thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage("Statistics type cannot be null or empty");

        new StatisticsByType(type, 0);
    }

    @Test
    public void negativeDistinctValueCountThrowsException() {
        String type = "type";

        thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage("Distinct Value Count should be be greater than zero.");

        new StatisticsByType(type, -10);
    }

    @Test
    public void nullStatisticsValueThrowsException() {
        String type = "type";
        StatisticsValue value = null;

        thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage("Stats value cannot be null");

        StatisticsByType statsType = new StatisticsByType(type, 0);
        statsType.addValue(value);
    }

    @Test
    public void zeroDistinctValueCountIsOK() {
        String type = "type";
        StatisticsByType statsType = new StatisticsByType(type, 0);

        assertThat(statsType.getDistinctValueCount(), is(0));
    }

    @Test
    public void distinctValueCountBelow10001IsUnchanged() {
        String type = "type";
        StatisticsByType statsType = new StatisticsByType(type, 10000);

        assertThat(statsType.getDistinctValueCount(), is(10000));
    }

    @Test
    public void distinctValueCountRoundedDownIfValueGreaterThan10KAndEndsWith101To499() {
        String type = "type";
        StatisticsByType statsType = new StatisticsByType(type, 10001);

        assertThat(statsType.getDistinctValueCount(), is(10000));
    }

    @Test
    public void distinctValueCountRoundedDownIfEndsWith499OrLess() {
        String type = "type";
        StatisticsByType statsType = new StatisticsByType(type, 10499);

        assertThat(statsType.getDistinctValueCount(), is(10000));
    }

    @Test
    public void distinctValueCountRoundedUpIfEndsWith500OrGreater() {
        String type = "type";
        StatisticsByType statsType = new StatisticsByType(type, 10500);

        assertThat(statsType.getDistinctValueCount(), is(11000));
    }
}

@@ -38,16 +38,51 @@
 model;%0A%0A
+import java.util.stream.IntStream;%0A
 import o
@@ -495,37 +495,8 @@
 ) %7B%0A
-        String type = null;%0A%0A
     
@@ -641,36 +641,36 @@
 tatisticsByType(
-type
+null
 , 0);%0A    %7D%0A%0A   
@@ -957,28 +957,26 @@
 negative
-DistinctValu
+Approximat
 eCountTh
@@ -1313,47 +1313,8 @@
 e%22;%0A
-        StatisticsValue value = null;%0A%0A
     
@@ -1520,21 +1520,20 @@
 ddValue(
-value
+null
 );%0A    %7D
@@ -1564,28 +1564,26 @@
 oid zero
-DistinctValu
+Approximat
 eCountIs
@@ -1716,36 +1716,34 @@
 tatsType.get
-DistinctValu
+Approximat
 eCount(), is
@@ -1777,36 +1777,34 @@
 public void 
-distinctValu
+approximat
 eCountBelow1
@@ -1954,36 +1954,34 @@
 tatsType.get
-DistinctValu
+Approximat
 eCount(), is
@@ -2019,36 +2019,34 @@
 public void 
-distinctValu
+approximat
 eCountRounde
@@ -2226,36 +2226,34 @@
 tatsType.get
-DistinctValu
+Approximat
 eCount(), is
@@ -2291,36 +2291,34 @@
 public void 
-distinctValu
+approximat
 eCountRounde
@@ -2477,36 +2477,34 @@
 tatsType.get
-DistinctValu
+Approximat
 eCount(), is
@@ -2550,20 +2550,18 @@
 oid 
-distinctValu
+approximat
 eCou
@@ -2737,38 +2737,740 @@
 .get
-DistinctValueCount(), is(11000
+ApproximateCount(), is(11000));%0A    %7D%0A%0A    @Test%0A    public void returnRealStatsSizeIfApproximateCountIsFewer() %7B%0A        StatisticsByType statsType = new StatisticsByType(%22goId%22, 20);%0A%0A        IntStream.rangeClosed(1, 25)%0A                .forEach(v -%3E statsType.addValue(new StatisticsValue(Integer.toString(v), v, v)));%0A%0A        assertThat(statsType.getApproximateCount(), is(25));%0A    %7D%0A%0A    @Test%0A    public void returnApproximateCountIfRealStatsSizeIsFewer() %7B%0A        StatisticsByType statsType = new StatisticsByType(%22goId%22, 25);%0A%0A        IntStream.rangeClosed(1, 20)%0A                .forEach(v -%3E statsType.addValue(new StatisticsValue(Integer.toString(v), v, v)));%0A%0A        assertThat(statsType.getApproximateCount(), is(25
 ));%0A

Rename distinctValueCount to approximateCount. Use the bucket size instead of count if count is less than bucket size.