package uk.ac.aber.cs31920.assignment.tests.solvers;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import uk.ac.aber.cs31920.assignment.implementation.datastructures.Edge;
import uk.ac.aber.cs31920.assignment.implementation.datastructures.GraphNode;
import uk.ac.aber.cs31920.assignment.implementation.datastructures.MaxFlowGraph;
import uk.ac.aber.cs31920.assignment.implementation.solvers.Cap1EdmondsKarpMaxFlowSolver;

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

public class Cap1EdmondsKarpMaxFlowSolverTests { @Test
    public void testSolverWithMaxMatchingGraph(){
            /*
                    graph
                     ┌─┐       ┌─┐
                 ┌──►│2├───┐   │5├───┐
                 │   └─┘   │┌─►└─┘   │
                 │       ┌─┼┘        ▼
                ┌┴┐  ┌─┐ │ └──►┌─┐  ┌─┐
                │1├─►│3├─┼────►│6├─►│8│
                └┬┘  └─┘ │ ┌──►└─┘  └▲┘
                 │       └─┼┐        │
                 │   ┌─┐   │└─►┌─┐   │
                 └──►│4├───┘   │7├───┘
                     └─┘       └─┘
            */

        // arrange
        GraphNode node1 = new GraphNode(null, null, 1);
        GraphNode node2 = new GraphNode(null, null, 2);
        GraphNode node3 = new GraphNode(null, null, 3);
        GraphNode node4 = new GraphNode(null, null, 4);
        GraphNode node5 = new GraphNode(null, null, 5);
        GraphNode node6 = new GraphNode(null, null, 6);
        GraphNode node7 = new GraphNode(null, null, 7);
        GraphNode node8 = new GraphNode(null, null, 8);
        node1.addNetworkChildren(new GraphNode[]{node2, node3, node4});node1.setAsSource();
        node2.addNetworkChild(node6);
        node3.addNetworkChildren(new GraphNode[]{node5, node6, node7});
        node4.addNetworkChild(node6);
        node5.addNetworkChild(node8);
        node6.addNetworkChild(node8);
        node7.addNetworkChild(node8);node8.setAsSink();
        MaxFlowGraph graph = new MaxFlowGraph(node1, node8, List.of(node1, node2, node3, node4, node5, node6, node8));

        // act
        List<Edge> result1 = Cap1EdmondsKarpMaxFlowSolver.Solve(graph);

        // assert
        List<Edge> expected1 = new ArrayList<>();
        Assertions.assertEquals(expected1, result1);
    }

    @Test
    public void testSolverWithRealisticProblem(){
    /*
              ┌─┐      ┌─┐
          ┌──►│2├─────►│4├───┐
          │   └┬┘   ┌─►└─┘   ▼
         ┌┴┐   └───┐│       ┌─┐
        s│1│   ┌───┼┘       │6│t
         └┬┘   │   │        └─┘
          │   ┌┴┐  └──►┌─┐   ▲
          └──►│3├─────►│5├───┘
              └─┘      └─┘
    */

        // arrange
        GraphNode node1 = new GraphNode(null, null, 1);
        GraphNode node2 = new GraphNode(null, null, 2);
        GraphNode node3 = new GraphNode(null, null, 3);
        GraphNode node4 = new GraphNode(null, null, 4);
        GraphNode node5 = new GraphNode(null, null, 5);
        GraphNode node6 = new GraphNode(null, null, 6);
        node1.addNetworkChildren(new GraphNode[]{node2, node3});node1.setAsSource();
        node2.addNetworkChildren(new GraphNode[]{node5, node4});
        node3.addNetworkChildren(new GraphNode[]{node5, node4});
        node4.addNetworkChild(node6);
        node5.addNetworkChild(node6);
        node6.setAsSink();
        MaxFlowGraph graph = new MaxFlowGraph(node1, node6, List.of(node1, node2, node3, node4, node5, node6));

        // act
        List<Edge> result1 = Cap1EdmondsKarpMaxFlowSolver.Solve(graph);

        // assert
        List<Edge> expected1 = new ArrayList<>();
        Assertions.assertEquals(expected1, result1);
    }
}
