package edu.fiu.jtlex.data;


import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Map;

import org.junit.Before;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import edu.fiu.jtlex.data.Graph;
import edu.fiu.jtlex.data.INode;
import edu.fiu.jtlex.data.IEvent.EventClass;
import edu.fiu.jtlex.data.IInstance.Aspect;
import edu.fiu.jtlex.data.IInstance.Polarity;
import edu.fiu.jtlex.data.IInstance.Pos;
import edu.fiu.jtlex.data.IInstance.Tense;

/**
 * 
 * @author luisrobaina
 *
 */


class GraphTest {

	Graph TimeML;

	@Before
	void clean() {
		TimeML = null;
	}

	// Test the TimeML Graph Constructor
	/**
	 * Test case ID: TestGraphConstructor Purpose: Test: Verify a Graph object is
	 * returned with 0 nodes and 0 edges. Test set up: None Test input: Graph TimeML
	 * = new Graph(); Expected output: A new instance of IGraph with 0 nodes and 0
	 * links.
	 */
	@Test
	void testGraphContructor() {
		Graph TimeML = new Graph();
		Assertions.assertTrue(TimeML != null && TimeML.getLinksCount() == 0 && TimeML.getNodesCount() == 0);
	}

	// Test the adding a Node to the TimeML Graph.
	/**
	 * Test case ID: testAddNode Purpose: Test: Verify a Graph object is returned
	 * with 0 nodes and 0 edges. Test set up: None Test input: Graph TimeML = new
	 * Graph(); Expected output: A new instance of IGraph with 0 nodes and 0 links.
	 */

	@Test
	void testAddNode() {
		TimeML = new Graph();
		IEvent Event = new Event(1, EventClass.REPORTING, "Example");
		ISignal Signal = new Signal(1, "Example");

		INode node = new Instance(1, Event, Tense.FUTURE, Aspect.NONE, Pos.ADJECTIVE, Polarity.POS, "Example", Signal,
				"Example");

		TimeML.addNode(node);
		Assertions.assertTrue(TimeML.getNodesCount() == 1 && containsNode(node) == true);

	}

	boolean containsNode(INode node) {
		for (INode n : TimeML.getNodes()) {
			if (node == n) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Functional Test creating Graphs from TimeML files.
	 * 
	 * Test case ID: testExtractGraphFromFiles Purpose: Test: Print the graph data
	 * structure generated from each TimeML file in /data/The TimeBank Corpus".
	 * Expected output: Graph Data Structure information is printed to the console.
	 */
	@Test
	void testExtractGraphFromFiles() {

		TimeMLParser parser = new TimeMLParser();
		Graph graph;

		File TimeMLFolder = new File(System.getProperty("user.dir") + "/data/The TimeBank Corpus");

		File[] tmlFiles = TimeMLFolder.listFiles();

		System.out.println("Number of TimeML files: " + tmlFiles.length);

		for (File file : tmlFiles) {

			if (file.getName().equals(".DS_Store")) {
				System.out.println(file.getName());
			} else {
				System.out.println("TimeML File: " + file.getName());
				FileInputStream tmlFile = null;
				try {
					tmlFile = new FileInputStream(file);
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				}
				IText txtObject = parser.parse(tmlFile);

				graph = new Graph();

				// Add TimeX Nodes
				for (ITimex T : txtObject.getTimexes()) {
					graph.addNode(T);
				}
				// Add Instance Nodes.
				for (IInstance I : txtObject.getInstances()) {
					graph.addNode(I);
				}
				// Add Links
				for (ILink L : txtObject.getLinks()) {
					graph.addLink(L);
				}

				printGraph(graph);
			}
		} // end for each file iteration.
		assertTrue(true);
	}

	void printGraph(IGraph graph) {
		
		System.out.println("Nodes Count = " + graph.getNodesCount());
		System.out.println("Links Count = " + graph.getLinksCount());
		System.out.println("\nLinks Count: (Type = Count");
		for (Map.Entry<String, Integer> tuple : graph.getLinkTypesCount().entrySet()) {
			System.out.println(tuple.getKey() + ": " + tuple.getValue());
		}

		System.out.println("Nodes:");
		for (INode N : graph.getNodes()) {
			System.out.print(N.getIdStr() + ", ");
		}
		System.out.println("\nLinks: (From -> To)");
		for (ILink L : graph.getLinks()) {
			System.out.println("(" + (L.getEventInstance().getIdStr() + " " + L.getRelType().toString() + " "
					+ (L.getRelatedToEvent()).getIdStr() + ")"));
		}
	}
}
