package com.spotify.heroic.ingestion;

import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;

import java.util.Collection;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import com.spotify.heroic.exceptions.BackendGroupException;
import com.spotify.heroic.metadata.MetadataBackend;
import com.spotify.heroic.metadata.MetadataManager;
import com.spotify.heroic.metric.MetricBackendGroup;
import com.spotify.heroic.metric.MetricManager;
import com.spotify.heroic.metric.model.WriteMetric;
import com.spotify.heroic.metric.model.WriteResult;
import com.spotify.heroic.statistics.IngestionManagerReporter;
import com.spotify.heroic.suggest.SuggestBackend;
import com.spotify.heroic.suggest.SuggestManager;

import eu.toolchain.async.AsyncFramework;
import eu.toolchain.async.AsyncFuture;
import eu.toolchain.async.Collector;

@RunWith(MockitoJUnitRunner.class)
public class IngestionManagerTest {
    private static final String group = "group";

    @Mock
    private AsyncFuture<WriteResult> writeResult;
    @Mock
    private AsyncFramework async;
    @Mock
    private MetricManager metricManager;
    @Mock
    private MetadataManager metadataManager;
    @Mock
    private SuggestManager suggestManager;
    @Mock
    private IngestionManagerReporter reporter;
    @Mock
    private WriteMetric write;
    @Mock
    private AsyncFuture<WriteResult> future;
    @Mock
    private MetricBackendGroup metric;
    @Mock
    private MetadataBackend metadata;
    @Mock
    private SuggestBackend suggest;

    @Before
    public void setup() throws BackendGroupException {
        doReturn(metric).when(metricManager).useGroup(group);
        doReturn(metadata).when(metadataManager).useGroup(group);
        doReturn(suggest).when(suggestManager).useGroup(group);
    }

    private IngestionManagerImpl setupIngestionManager(final boolean updateMetrics, final boolean updateMetadata,
            final boolean updateSuggestions) {
        final IngestionManagerImpl manager = new IngestionManagerImpl(updateMetrics, updateMetadata, updateSuggestions);
        manager.async = async;
        manager.metadata = metadataManager;
        manager.metric = metricManager;
        manager.suggest = suggestManager;
        manager.reporter = reporter;
        return spy(manager);
    }

    @Test
    public void testWriteEmpty() throws BackendGroupException {
        final IngestionManagerImpl manager = setupIngestionManager(true, true, true);

        doReturn(true).when(write).isEmpty();
        doReturn(future).when(async).resolved(any(WriteResult.class));

        assertEquals(future, manager.write(group, write));

        verify(async).resolved(any(WriteResult.class));
        verify(write).isEmpty();
        verify(manager, never()).doWrite(group, write);
    }

    @Test
    public void testWrite() throws BackendGroupException {
        final IngestionManagerImpl manager = setupIngestionManager(true, true, true);

        doReturn(false).when(write).isEmpty();
        doReturn(future).when(manager).doWrite(group, write);

        assertEquals(future, manager.write(group, write));

        verify(async, never()).resolved(any(WriteResult.class));
        verify(write).isEmpty();
        verify(manager).doWrite(group, write);
    }

    @SuppressWarnings("unchecked")
    @Test
    public void testDoWriteAll() throws BackendGroupException {
        final IngestionManagerImpl manager = setupIngestionManager(true, true, true);

        doReturn(future).when(manager).doMetricWrite(write, metric);
        doReturn(future).when(manager).doMetadataWrite(write, metadata, suggest);
        doReturn(future).when(async).collect(any(Collection.class), any(Collector.class));

        assertEquals(future, manager.doWrite(group, write));

        verify(manager).doMetricWrite(write, metric);
        verify(manager).doMetadataWrite(write, metadata, suggest);
        verify(async).collect(any(Collection.class), any(Collector.class));
    }

    @SuppressWarnings("unchecked")
    @Test
    public void testDoWriteNone() throws BackendGroupException {
        final IngestionManagerImpl manager = setupIngestionManager(false, false, false);

        doReturn(future).when(manager).doMetricWrite(write, metric);
        doReturn(future).when(manager).doMetadataWrite(write, metadata, suggest);
        doReturn(future).when(async).collect(any(Collection.class), any(Collector.class));

        assertEquals(future, manager.doWrite(group, write));

        verify(manager, never()).doMetricWrite(write, metric);
        verify(manager, never()).doMetadataWrite(write, metadata, suggest);
        verify(async).collect(any(Collection.class), any(Collector.class));
    }
}

@@ -117,16 +117,66 @@
 rs.any;%0A
+import static org.mockito.Matchers.anyCollection;%0A
 import s
@@ -338,38 +338,8 @@
 y;%0A%0A
-import java.util.Collection;%0A%0A
 impo
@@ -3756,32 +3756,155 @@
 , true, true);%0A%0A
+        final Collector%3CWriteResult, WriteResult%3E collector = (Collector%3CWriteResult, WriteResult%3E) any(Collector.class);%0A%0A
         doReturn
@@ -4078,33 +4078,32 @@
 ync).collect(any
-(
 Collection.class
@@ -4096,38 +4096,29 @@
 llection
-.class), any(C
+(), c
 ollector
 .class))
@@ -4101,39 +4101,32 @@
 ion(), collector
-.class)
 );%0A%0A        asse
@@ -4321,33 +4321,32 @@
 ync).collect(any
-(
 Collection.class
@@ -4339,38 +4339,29 @@
 llection
-.class), any(C
+(), c
 ollector
 .class))
@@ -4344,39 +4344,32 @@
 ion(), collector
-.class)
 );%0A    %7D%0A%0A    @S
@@ -4558,24 +4558,147 @@
 e, false);%0A%0A
+        final Collector%3CWriteResult, WriteResult%3E collector = (Collector%3CWriteResult, WriteResult%3E) any(Collector.class);%0A%0A
         doRe
@@ -4876,33 +4876,32 @@
 ync).collect(any
-(
 Collection.class
@@ -4894,38 +4894,29 @@
 llection
-.class), any(C
+(), c
 ollector
 .class))
@@ -4907,23 +4907,16 @@
 ollector
-.class)
 );%0A%0A    
@@ -5145,17 +5145,16 @@
 lect(any
-(
 Collecti
@@ -5159,30 +5159,21 @@
 tion
-.class), any(C
+(), c
 ollector
 .cla
@@ -5168,23 +5168,16 @@
 ollector
-.class)
 );%0A    %7D

fix IngestionManagerTest for java 8