package fr.umlv.datastruct2;

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.NoSuchElementException;

import org.junit.Test;

@SuppressWarnings("static-method")
public class SeqTest {
  @Test
  public void testNil() {
    Seq<String> seq = Seq.nil();
  }
  
  @Test
  public void testNil2() {
    Seq<Integer> seq = Seq.nil();
  }
  
  @Test
  public void testNilIdentity() {
    assertSame(Seq.nil(), Seq.nil());
  }
  
  @Test
  public void testPrepend() {
    Seq<String> seq = Seq.nil();
    Seq<String> seq2 = seq.prepend("foo");
    seq2.forEach(element -> {
      assertEquals("foo", element);
    });
  }
  
  @Test(expected = NullPointerException.class)
  public void testPrependNull() {
    Seq.nil().prepend(null);
  }
  
  @Test
  public void testForEach() {
    Seq<Integer> seq = Seq.nil();
    seq = seq.prepend(3).prepend(2).prepend(1);
    ArrayList<Integer> list = new ArrayList<>();
    seq.forEach(list::add);
    assertEquals(Arrays.asList(1, 2, 3), list);
  }
  
  @Test
  public void testForEachEmpty() {
    Seq<Object> seq = Seq.nil();
    seq.forEach(__ -> fail());
  }
  
  @Test(expected = NullPointerException.class)
  public void testForEachNull() {
    Seq.nil().forEach(null);
  }
  
  
  /*
  @Test
  public void testIteratorNil() {
    Iterator<Object> it = Seq.nil().iterator();
    assertFalse(it.hasNext());
  }
  
  @Test(expected = NoSuchElementException.class)
  public void testIteratorNil2() {
    Seq.nil().iterator().next();
  }
  
  @Test
  public void testIterator() {
    Iterator<Object> it = Seq.nil().prepend("foo").iterator();
    assertTrue(it.hasNext());
    assertEquals("foo", it.next());
    assertFalse(it.hasNext());
  }
  
  @Test
  public void testIterator2() {
    Iterator<Object> it = Seq.nil().prepend("bar").iterator();
    assertEquals("bar", it.next());
    try {
      it.next();
      fail();
    } catch(NoSuchElementException e) {
      // ok
    }
  }
  
  @Test
  public void testIterator3hasNext() {
    Iterator<Object> it = Seq.nil().prepend("baz").iterator();
    assertTrue(it.hasNext());
    assertTrue(it.hasNext());
    assertTrue(it.hasNext());
  }
  
  @Test(expected = UnsupportedOperationException.class)
  public void testIteratorRemove() {
    Iterator<Object> it = Seq.nil().prepend("boo").iterator();
    assertEquals("boo", it.next());
    it.remove();
  }
  
  @Test
  public void testIteratorALot() {
    Seq<Integer> seq = Seq.nil();
    for(int i = 0; i < 10_000; i++) {
      seq = seq.prepend(i);
    }
    
    Iterator<Integer> it = seq.iterator();
    for(int i = 10_000; --i>= 0;) {
      assertTrue(it.hasNext());
      assertEquals(i, (int)it.next());
    }
    assertFalse(it.hasNext());
  }
  */
}
