package uk.ac.ebi.quickgo.annotation.service.statistics;

import uk.ac.ebi.quickgo.annotation.model.Annotation;
import uk.ac.ebi.quickgo.annotation.model.AnnotationRequest;
import uk.ac.ebi.quickgo.rest.search.SearchService;
import uk.ac.ebi.quickgo.rest.search.request.converter.FilterConverterFactory;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;

import static org.mockito.Mockito.when;

/**
 * Tests the behaviour of the {@link AnnotationStatisticsService} class.
 */
@RunWith(MockitoJUnitRunner.class)
public class AnnotationStatisticsServiceTest {
    @Rule
    public ExpectedException thrown = ExpectedException.none();

    private AnnotationStatisticsService statsService;

    @Mock
    private FilterConverterFactory filterFactoryMock;

    @Mock
    private SearchService<Annotation> searchServiceMock;

    @Mock
    private StatsConverter statsConverterMock;

    @Mock
    private RequiredStatistics requiredStatisticsForStandardUsage;

    @Mock
    private RequiredStatistics requiredStatisticsForDownloadUsage;

    @Before
    public void setUp() throws Exception {
        statsService = new AnnotationStatisticsService(filterFactoryMock, searchServiceMock,
                statsConverterMock, requiredStatisticsForStandardUsage, requiredStatisticsForDownloadUsage);
    }

    @Test
    public void nullFilterFactoryThrowsExceptionInConstructor() throws Exception {
        thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage("Filter factory cannot be null");

        statsService = new AnnotationStatisticsService(null, searchServiceMock,
                statsConverterMock, requiredStatisticsForStandardUsage, requiredStatisticsForDownloadUsage);
    }

    @Test
    public void nullSearchServiceThrowsExceptionInConstructor() throws Exception {
        thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage("Search service cannot be null");

        statsService = new AnnotationStatisticsService(filterFactoryMock, null,
                statsConverterMock, requiredStatisticsForStandardUsage, requiredStatisticsForDownloadUsage);
    }

    @Test
    public void nullStatsConverterThrowsExceptionInConstructor() throws Exception {
        thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage("Stats request converter cannot be null");

        statsService = new AnnotationStatisticsService(filterFactoryMock, searchServiceMock,
                null, requiredStatisticsForStandardUsage, requiredStatisticsForDownloadUsage);
    }

    @Test
    public void nullRequiredStatisticsForStandardUsageThrowsExceptionInConstructor() throws Exception {
        thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage("Required statistics for standard usage cannot be null.");

        statsService = new AnnotationStatisticsService(filterFactoryMock, searchServiceMock,
                statsConverterMock, null, requiredStatisticsForDownloadUsage);
    }

    @Test
    public void nullRequiredStatisticsForDownloadUsageThrowsExceptionInConstructor() throws Exception {
        thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage("Required statistics for download usage cannot be null.");

        statsService = new AnnotationStatisticsService(filterFactoryMock, searchServiceMock,
                statsConverterMock, requiredStatisticsForStandardUsage, null);
    }

    @Test
    public void calculatingRequiredStatisticsForStandardUsageWithNullAnnotationThrowsException() throws Exception {
        thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage("Annotation request cannot be null");

        statsService.calculateForStandardUsage(null);
    }

    @Test
    public void calculatingRequiredStatisticsForStandardUsageWithNullContentThrowsException() throws Exception {
        thrown.expect(IllegalStateException.class);
        thrown.expectMessage("Required statistics for standard usage cannot be null.");

        when(requiredStatisticsForStandardUsage.getStats()).thenReturn(null);
        statsService = new AnnotationStatisticsService(filterFactoryMock, searchServiceMock,
                statsConverterMock, requiredStatisticsForStandardUsage,
                requiredStatisticsForDownloadUsage);
        AnnotationRequest request = Mockito.mock(AnnotationRequest.class);

        statsService.calculateForStandardUsage(request);
    }

    @Test
    public void calculatingRequiredStatisticsForDownloadUsageWithNullContentThrowsException() throws Exception {
        thrown.expect(IllegalStateException.class);
        thrown.expectMessage("Required statistics for download cannot be null.");

        when(requiredStatisticsForDownloadUsage.getStats()).thenReturn(null);
        statsService = new AnnotationStatisticsService(filterFactoryMock, searchServiceMock,
                statsConverterMock, requiredStatisticsForStandardUsage,
                requiredStatisticsForDownloadUsage);
        AnnotationRequest request = Mockito.mock(AnnotationRequest.class);

        statsService.calculateForStandardUsage(request);
    }

}

@@ -1222,24 +1222,102 @@
 loadUsage;%0A%0A
+    @Mock%0A    private RequiredStatisticsProvider requiredStatisticsProvider;%0A%0A
     @Before%0A
@@ -1339,33 +1339,16 @@
  setUp()
- throws Exception
  %7B%0A     
@@ -1493,60 +1493,16 @@
 tics
-ForStandardUsage, requiredStatisticsForDownloadUsage
+Provider
 );%0A 
@@ -1580,33 +1580,16 @@
 ructor()
- throws Exception
  %7B%0A     
@@ -1840,60 +1840,16 @@
 tics
-ForStandardUsage, requiredStatisticsForDownloadUsage
+Provider
 );%0A 
@@ -1927,33 +1927,16 @@
 ructor()
- throws Exception
  %7B%0A     
@@ -2187,60 +2187,16 @@
 tics
-ForStandardUsage, requiredStatisticsForDownloadUsage
+Provider
 );%0A 
@@ -2275,33 +2275,16 @@
 ructor()
- throws Exception
  %7B%0A     
@@ -2543,60 +2543,16 @@
 tics
-ForStandardUsage, requiredStatisticsForDownloadUsage
+Provider
 );%0A 
@@ -2605,32 +2605,24 @@
 atistics
-ForStandardUsage
+Provider
 ThrowsEx
@@ -2643,33 +2643,16 @@
 ructor()
- throws Exception
  %7B%0A     
@@ -2922,481 +2922,8 @@
 ock,
- null, requiredStatisticsForDownloadUsage);%0A    %7D%0A%0A    @Test%0A    public void nullRequiredStatisticsForDownloadUsageThrowsExceptionInConstructor() throws Exception %7B%0A        thrown.expect(IllegalArgumentException.class);%0A        thrown.expectMessage(%22Required statistics for download usage cannot be null.%22);%0A%0A        statsService = new AnnotationStatisticsService(filterFactoryMock, searchServiceMock,%0A                statsConverterMock, requiredStatisticsForStandardUsage,
  nul
@@ -3039,33 +3039,16 @@
 eption()
- throws Exception
  %7B%0A     
@@ -3329,33 +3329,16 @@
 eption()
- throws Exception
  %7B%0A     
@@ -3516,36 +3516,49 @@
 tandardUsage.get
-Stat
+RequiredStatistic
 s()).thenReturn(
@@ -3715,76 +3715,16 @@
 tics
-ForStandardUsage,%0A                requiredStatisticsForDownloadUsage
+Provider
 );%0A 
@@ -3969,25 +3969,8 @@
 on()
- throws Exception
  %7B%0A 
@@ -4154,20 +4154,33 @@
 sage.get
-Stat
+RequiredStatistic
 s()).the
@@ -4345,76 +4345,16 @@
 tics
-ForStandardUsage,%0A                requiredStatisticsForDownloadUsage
+Provider
 );%0A 

Replace multi instances of RequiredStatisticsProvider with just the one as the source of knowledge.