// GraphTest.cpp
//
//     Created on: 21. 01. 2018
//         Author: Jan Uhlik
//    Modified by:
//
// Copyright (c) 2017 Czech Technical University in Prague | Faculty of Information Technology. All rights reserved.
// Git repository: https://gitlab.fit.cvut.cz/algorithms-library-toolkit/automata-library

#include <catch2/catch.hpp>
#include <graph/GraphClasses.hpp>

using namespace graph;

TEST_CASE ( "Graph", "[unit][graph][graph]" ) {
	SECTION ( "Undirected Graphs" ) {
		graph::UndirectedGraph<int, ext::pair<int, int> > graph;

		graph.addNode(1);
		graph.addNode(2);
		graph.addNode(3);
		graph.addNode(4);
		graph.addNode(5);
		graph.addNode(6);

		graph.addEdge(ext::make_pair(1, 2));
		graph.addEdge(2, 3);
		graph.addEdge(3, 4);
		graph.addEdge(5, 1);

		CHECK(graph.nodeCount() == 6);
		CHECK(graph.edgeCount() == 4);

		ext::set<int> ref1 = {2, 5};
		CHECK(graph.successors(1) == ref1);

		ext::vector<ext::pair<int, int>> ref2 = {ext::make_pair(1, 2), ext::make_pair(5, 1)};
		ext::vector<ext::pair<int, int>> res2 = graph.successorEdges(1);
		std::sort(ref2.begin(), ref2.end());
		std::sort(res2.begin(), res2.end());
		CHECK(res2.size() == ref2.size());
		CHECK(res2 == ref2);

		ext::set<int> ref3 = {1, 3};
		CHECK(graph.predecessors(2) == ref3);

		ext::vector<ext::pair<int, int>> ref4 = {ext::make_pair(1, 2), ext::make_pair(2, 3)};
		ext::vector<ext::pair<int, int>> res4 = graph.predecessorEdges(2);
		std::sort(ref4.begin(), ref4.end());
		std::sort(res4.begin(), res4.end());
		CHECK(res4.size() == ref4.size());
		CHECK(res4 == ref4);
	}

	// ---------------------------------------------------------------------------------------------------------------------

	SECTION ( "Directed Graph" ) {
		graph::DirectedGraph<int, ext::pair<int, int> > graph;

		graph.addNode(1);
		graph.addNode(2);
		graph.addNode(3);
		graph.addNode(4);
		graph.addNode(5);
		graph.addNode(6);

		graph.addEdge(ext::make_pair(1, 2));
		graph.addEdge(2, 3);
		graph.addEdge(3, 4);
		graph.addEdge(5, 1);

		CHECK(graph.nodeCount() == 6);
		CHECK(graph.edgeCount() == 4);

		ext::set<int> ref1 = {2};
		CHECK(graph.successors(1) == ref1);

		ext::vector<ext::pair<int, int>> ref2 = {ext::make_pair(1, 2)};
		ext::vector<ext::pair<int, int>> res2 = graph.successorEdges(1);
		std::sort(ref2.begin(), ref2.end());
		std::sort(res2.begin(), res2.end());
		CHECK(res2.size() == ref2.size());
		CHECK(res2 == ref2);

		ext::set<int> ref3 = {1};
		CHECK(graph.predecessors(2) == ref3);

		ext::vector<ext::pair<int, int>> ref4 = {ext::make_pair(1, 2)};
		ext::vector<ext::pair<int, int>> res4 = graph.predecessorEdges(2);
		std::sort(ref4.begin(), ref4.end());
		std::sort(res4.begin(), res4.end());
		CHECK(res4.size() == ref4.size());
		CHECK(res4 == ref4);
	}

	// ---------------------------------------------------------------------------------------------------------------------

	SECTION ( "Mixed Graph" ) {
		graph::MixedGraph<int, ext::pair<int, int>> graph;
		graph.addNode(1);
		graph.addNode(2);
		graph.addNode(3);
		graph.addNode(4);
		graph.addNode(5);
		graph.addNode(6);

		graph.addEdge(ext::make_pair(1, 2));
		graph.addEdge(2, 3);
		graph.addEdge(3, 4);
		graph.addArc(5, 1);

		CHECK(graph.nodeCount() == 6);
		CHECK(graph.edgeCount() == 4);

		ext::set<int> ref1 = {1};
		CHECK(graph.successors(5) == ref1);

		ext::vector<ext::pair<int, int>> ref2 = {ext::make_pair(1, 2)};
		ext::vector<ext::pair<int, int>> res2 = graph.successorEdges(1);
		std::sort(ref2.begin(), ref2.end());
		std::sort(res2.begin(), res2.end());
		CHECK(res2.size() == ref2.size());
		CHECK(res2 == ref2);

		ext::set<int> ref3 = {1, 3};
		CHECK(graph.predecessors(2) == ref3);

		ext::vector<ext::pair<int, int>> ref4 = {ext::make_pair(1, 2), ext::make_pair(2, 3)};
		ext::vector<ext::pair<int, int>> res4 = graph.predecessorEdges(2);
		std::sort(ref4.begin(), ref4.end());
		std::sort(res4.begin(), res4.end());
		CHECK(res4.size() == ref4.size());
		CHECK(res4 == ref4);
	}
}
