import graphlib.util.Graphs;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import graphlib.graphs.UndirectedGraph;
import graphlib.nodes.Node;

public class SimpleTest {

    private static CollatzGraphMaker cgm;

    @BeforeClass
    public static void init() {
        cgm = new CollatzGraphMaker();
    }


    @Test
    public void testSingle() {
        UndirectedGraph<Long> graph = new UndirectedGraph<>();
        graph.addNode(5L);
        Assert.assertEquals(
                1,
                cgm.connectedComponents(Graphs.unmodifiableUndirectedGraph(graph))
        );
    }

    @Test
    public void testPair() {
        UndirectedGraph<Long> graph = new UndirectedGraph<>();
        Node<Long> a = graph.addNode(0L),
             b = graph.addNode(1L);
        graph.addEdge(a, b);
        Assert.assertEquals(
                1,
                cgm.connectedComponents(Graphs.unmodifiableUndirectedGraph(graph))
        );
    }

    @Test
    public void testTriangle() {
        UndirectedGraph<Long> graph = new UndirectedGraph<>();
        Node<Long> a = graph.addNode(4L),
             b = graph.addNode(2L),
             c = graph.addNode(9L);
        graph.addEdge(a, b);
        graph.addEdge(b, c);
        graph.addEdge(c, a);
        Assert.assertEquals(1, cgm.connectedComponents(Graphs.unmodifiableUndirectedGraph(graph)));
    }

    @Test
    public void testTwoPair() {
        UndirectedGraph<Long> graph = new UndirectedGraph<>();
        Node<Long> a = graph.addNode(17L),
             b = graph.addNode(8L),
             c = graph.addNode(4L),
             d = graph.addNode(-3L);
        graph.addEdge(a, b);
        graph.addEdge(c, d);

        Assert.assertEquals(2, cgm.connectedComponents(Graphs.unmodifiableUndirectedGraph(graph)));
    }

    @Test
    public void testMore() {
        UndirectedGraph<String> graph = new UndirectedGraph<>();
        Node<String> a = graph.addNode("alice"),
             b = graph.addNode("bob"),
             c = graph.addNode("carol"),
             d1 = graph.addNode("dave"),
             e = graph.addNode("eunice"),
             f = graph.addNode("frank");
        graph.addEdge(a, d1);
        graph.addEdge(c, e);

        Assert.assertEquals(4, cgm.connectedComponents(Graphs.unmodifiableUndirectedGraph(graph)));
    }

    @Test
    public void testCollatz() {
        UndirectedGraph<Long> collatz = cgm.makeCollatzGraph(1);

        Assert.assertEquals(8, collatz.numNodes());
        Assert.assertEquals(8, collatz.numEdges());
    }

    @Test
    public void testCollatz2() {
        UndirectedGraph<Long> collatz = cgm.makeCollatzGraph(10);

        Assert.assertEquals(21, collatz.numNodes());
        Assert.assertEquals(21, collatz.numEdges());
    }

    @Test
    public void testConjecture() {
        Assert.assertEquals(4, cgm.connectedCollatzComponents(100));
    }

}