package org.reactfx;

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.junit.Test;

public class RecursionTest {

    @Test
    public void allowRecursionWithOneSubscriber() {
        List<Integer> emitted = new ArrayList<>();
        List<Throwable> errors = new ArrayList<>();
        EventSource<Integer> source = new EventSource<>();
        source.hook(emitted::add).subscribe(
                i -> { if(i > 0) source.push(i-1); },
                errors::add);
        source.push(5);
        assertEquals(Arrays.asList(5, 4, 3, 2, 1, 0), emitted);
        assertEquals(0, errors.size());
    }

    @Test
    public void preventRecursionWithTwoSubscribers() {
        List<Integer> emitted = new ArrayList<>();
        List<Throwable> errors = new ArrayList<>();
        EventSource<Integer> source = new EventSource<>();
        source.subscribe(emitted::add);
        source.subscribe(i -> {
            if(i > 0) source.push(i-1);
        });
        source.monitor(errors::add);
        source.push(5);
        assertTrue("At most one event got emitted", emitted.size() <= 1);
        assertEquals(1, errors.size());
    }

    @Test
    public void onRecurseQueueTest() {
        EventSource<Integer> source = new EventSource<>();
        EventStream<Integer> stream = source.onRecurseQueue();
        List<Integer> emitted1 = new ArrayList<>();
        List<Integer> emitted2 = new ArrayList<>();

        stream.subscribe(x -> {
            emitted1.add(x);
            if(x > 0) source.push(x - 1);
        });
        stream.subscribe(emitted2::add);

        source.push(5);
        assertEquals(Arrays.asList(5, 4, 3, 2, 1, 0), emitted1);
        assertEquals(Arrays.asList(5, 4, 3, 2, 1, 0), emitted2);
    }

    @Test
    public void onRecurseRetainLatestTest() {
        EventSource<Integer> source = new EventSource<>();
        EventStream<Integer> stream = source.onRecurseRetainLatest();
        List<Integer> emitted1 = new ArrayList<>();
        List<Integer> emitted2 = new ArrayList<>();

        stream.subscribe(x -> {
            emitted1.add(x);
            if(x > 0) source.push(x - 1);
        });
        stream.subscribe(emitted2::add);

        source.push(5);
        assertTrue(Arrays.asList(5, 4, 3, 2, 1, 0).equals(emitted1)
                && (Arrays.asList(0).equals(emitted2) || Arrays.asList(5, 4, 3, 2, 1, 0).equals(emitted2)));
    }
}

@@ -1833,26 +1833,20 @@
 ecurseRe
-tainLatest
+duce
 Test() %7B
@@ -1965,19 +1965,28 @@
 seRe
-tainLatest(
+duce((a, b) -%3E a + b
 );%0A 
@@ -2284,20 +2284,22 @@
   assert
-True
+Equals
 (Arrays.
@@ -2318,32 +2318,26 @@
  3, 2, 1, 0)
-.equals(
+, 
 emitted1)%0A  
@@ -2333,29 +2333,26 @@
 mitted1)
+;
 %0A
-    
         
     && (
@@ -2347,48 +2347,33 @@
     
-    && (Arrays.asList(0).e
+assertE
 quals(
+15, 
 emitted2
 ) %7C%7C
@@ -2372,61 +2372,54 @@
 ted2
-) %7C%7C Arrays.asList(5, 4, 3, 2, 1, 0).equals(emitted2)
+.stream().reduce(0, (a, b) -%3E a + b).intValue(
 ));%0A

Fix a test case.