package fr.umlv.graph;

import static org.junit.Assert.*;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

import org.junit.Test;

@SuppressWarnings("static-method")
public class GraphEdgesTest {
  private static List<Graph> graphes() {
    return Arrays.asList(new MatrixGraph(77), new NodeListGraph(77), new NodeMapGraph(77));
  }
  
  @Test
  public void testEmptyEdges() {
    for(Graph graph: graphes()) {
      Iterator<Edge> edges = graph.edges(2);
      assertFalse(edges.hasNext());
    }
  }
  
  @Test
  public void testEmptyEdges2() {
    for(Graph graph: graphes()) {
      Iterator<Edge> edges = graph.edges(2);
      try {
        edges.next();
        fail();
      } catch(NoSuchElementException e) {
        // ok
      }
    }
  }
  
  @Test
  public void testEdges() {
    for(Graph graph: graphes()) {
      graph.addEdge(0, 1, 3);
      Iterator<Edge> edges = graph.edges(0);
      assertTrue(edges.hasNext());
      Edge edge = edges.next();
      assertEquals(0, edge.getSource());
      assertEquals(1, edge.getDestination());
      assertEquals(3, edge.getWeight());
      assertFalse(edges.hasNext());
    }
  }
  
  @Test
  public void testEdgesALot() {
    for(Graph graph: graphes()) {
      HashSet<Integer> expected = new HashSet<>();
      for(int i = 0; i < 77; i++) {
        expected.add(i);
        graph.addEdge(2, i, i);  
      }
      
      HashSet<Integer> result = new HashSet<>();
      Iterator<Edge> edges = graph.edges(2);
      while(edges.hasNext()) {
        Edge edge = edges.next();
        assertEquals(2, edge.getSource());
        int dst = edge.getDestination();
        result.add(dst);
        assertEquals(dst, edge.getWeight());
      }
      
      assertEquals(expected, result);
    }
  }
  
  @Test
  public void testEdgesView() {
    for(Graph graph: graphes()) {
      graph.addEdge(0, 1, 3);
      Edge edge = graph.edges(0).next();
      assertEquals(3, edge.getWeight());
      graph.addEdge(0, 1, -4);
      assertEquals(-4, edge.getWeight());
    }
  }
  
  @Test
  public void testEdgesRemoveInvalid() {
    for(Graph graph: graphes()) {
      graph.addEdge(7, 7, 7);
      Iterator<Edge> edges = graph.edges(7);
      try {
        edges.remove();
      } catch(IllegalStateException e) {
        // ok
      }
    }
  }
  
  @Test
  public void testEdgesRemoveInvalidTwice() {
    for(Graph graph: graphes()) {
      graph.addEdge(7, 7, 7);
      Iterator<Edge> edges = graph.edges(7);
      edges.next();
      edges.remove();
      try {
        edges.remove();
      } catch(IllegalStateException e) {
        // ok
      }
    }
  }
  
  @Test
  public void testEdgesRemove() {
    for(Graph graph: graphes()) {
      graph.addEdge(0, 1, 3);
      Iterator<Edge> edges = graph.edges(0);
      edges.next();
      edges.remove();
      assertFalse(graph.hasEdge(0, 1));
      assertEquals(Graph.NO_EDGE, graph.getWeight(0, 1));
    }
  }
}
