package edu.fiu.jtlex.data;

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

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import edu.fiu.jtlex.data.ITimex.TimexType;
import edu.fiu.jtlex.data.ITimex.TimexMod;
import edu.fiu.jtlex.data.ITimex.FunctionInDocument;



public class TimexTest {
	//Tests constructor
	@Nested
	@DisplayName("Testing Constructor")
	class testConstructor{
		//Timex Id Test
		@Nested
		@DisplayName("if TimeID is")
		class TestTID{
			@Test
			@DisplayName("negative")
			void testIdNegative() {
				assertThrows(IllegalArgumentException.class, ()-> new Timex(-1, TimexType.DATE, "0", TimexMod.APPROX, true, 0, FunctionInDocument.NONE, 0, 0,"every", "0", "something"));
			}
		}
		
		//Type Test
		@Nested
		@DisplayName("if TimexType is")
		class TestTimexType{
			@Test
			@DisplayName("null")
			void testClass() {
				assertThrows(NullPointerException.class, ()-> new Timex(1, null, "0", TimexMod.APPROX, false, 0, FunctionInDocument.NONE, 0, 0, "every", "0", "something"));
			}
		}
		
		//Value Test
		@Nested
		@DisplayName("if Value is")
		class TestValue{
			@Test
			@DisplayName("null")
			void testClass() {
				assertThrows(NullPointerException.class, ()-> new Timex(1, TimexType.DATE, null, TimexMod.APPROX, false, 0, FunctionInDocument.NONE, 0, 0, "every", "0", "something"));
			}
		}
		
		
		//Anchor Id Test
		@Nested
		@DisplayName("if AnchorID is")
		class TestAnchorID{
			@Test
			@DisplayName("negative")
			void testIdNegative() {
				assertThrows(IllegalArgumentException.class, ()-> new Timex(1, TimexType.DATE, "0", TimexMod.APPROX, false, -1, FunctionInDocument.NONE, 0, 0, "every", "0", "something"));
			}
		}
		
		
		//BeginPoint Id Test
		@Nested
		@DisplayName("if BeginPointID is")
		class TestBeginPointID{
			@Test
			@DisplayName("negative")
			void testIdNegative() {
				assertThrows(IllegalArgumentException.class, ()-> new Timex(1, TimexType.DATE, "0", TimexMod.APPROX, false, 0, FunctionInDocument.NONE, -1, 0, "every", "0", "something"));
			}
		}
		
		//EndPoint Id Test
		@Nested
		@DisplayName("if EndPointID is")
		class TestEndPointID{
			@Test
			@DisplayName("negative")
			void testIdNegative() {
				assertThrows(IllegalArgumentException.class, ()-> new Timex(1, TimexType.DATE, "0", TimexMod.APPROX, false, 0, FunctionInDocument.NONE, 0, -1, "every", "0", "something"));
			}
		}	
	}
	
    //tests getter methods of which there are 14.
	@Nested
	@DisplayName("Testing getters")
	class TestGetters{
		
		//Timex id getter test
		@Nested
		@DisplayName("getTimeId methods")
		class TestGetId{
			@Test
			@DisplayName("returning int")
			void testGetTimexId() {
				Timex timex = new Timex(1, TimexType.DATE, "0d", TimexMod.APPROX, false, 0, FunctionInDocument.NONE, 2, 3, "every", "w", "something");
				assertEquals(timex.getId(), 1);
				}
			@Test
			@DisplayName("returning string")
			void testGetTimexIdStr() {
				Timex timex = new Timex(1, TimexType.DATE, "0d", TimexMod.APPROX, false, 0, FunctionInDocument.NONE, 2, 3, "every", "w", "something");
				assertEquals(timex.getIdStr(), "t1");
				}
		
		}
		
		
		//Timex type getter test
		@Test
		@DisplayName("getTimexType method")
		void testGetTimexType() {
			Timex timex = new Timex(1, TimexType.DATE, "0d", TimexMod.APPROX, false, 0, FunctionInDocument.NONE, 2, 3, "every", "w", "something");
			assertEquals(timex.getType(), TimexType.DATE);
		}
		
		
		//Value getter test
		@Test
		@DisplayName("getValue method")
		void testGetValue() {
			Timex timex = new Timex(1, TimexType.DATE, "0d", TimexMod.APPROX, false, 0, FunctionInDocument.NONE, 2, 3, "every", "w", "something");
			assertEquals(timex.getValue(), "0d");
		}
		
		
		//TimexMod getter test
		@Test
		@DisplayName("getMod method")
		void testGetMod() {
			Timex timex = new Timex(1, TimexType.DATE, "0d", TimexMod.APPROX, false, 0, FunctionInDocument.NONE, 2, 3, "every", "w", "something");
			assertEquals(timex.getMod(), TimexMod.APPROX);
		}
		
		
		//AnchorId getter test
		@Nested
		@DisplayName("getAnchorId methods")
		class TestGetAnchor{
			@Test
			@DisplayName("returning int")
			void testGetAnchorId() {
				Timex timex = new Timex(1, TimexType.DATE, "0d", TimexMod.APPROX, false, 0, FunctionInDocument.NONE, 2, 3, "every", "w", "something");
				assertEquals(timex.getAnchorTimeId(), 0);
				}
			@Test
			@DisplayName("returning string")
			void testGetAnchorIdStr() {
				Timex timex = new Timex(1, TimexType.DATE, "0d", TimexMod.APPROX, false, 0, FunctionInDocument.NONE, 2, 3,"every", "w", "something");
				assertEquals(timex.getAnchorTimeIdStr(), "t0");
				}
		}
		
		
		//function in document getter test
		@Test
		@DisplayName("getFunction method")
		void testGetFunction() {
			Timex timex = new Timex(1, TimexType.DATE, "0d", TimexMod.APPROX, false, 0, FunctionInDocument.NONE, 2, 3, "every", "w", "something");
			assertEquals(timex.getFunction(), FunctionInDocument.NONE);
		}

		
		//Beginpoint id getter test
		@Nested
		@DisplayName("getBeginPointId methods")
		class TestGetBeginPoint{
			@Test
			@DisplayName("returning int")
			void testGetBeginPointId() {
				Timex timex = new Timex(1, TimexType.DATE, "0d", TimexMod.APPROX, false, 0, FunctionInDocument.NONE, 2, 3, "every", "w", "something");
				assertEquals(timex.getBeginPoint(), 2);
				}
			@Test
			@DisplayName("returning string")
			void testGetBeginPointIdStr() {
				Timex timex = new Timex(1, TimexType.DATE, "0d", TimexMod.APPROX, false, 0, FunctionInDocument.NONE, 2, 3, "every", "w", "something");
				assertEquals(timex.getBeginPointStr(), "t2");
				}
		}
			
		
		//Endpoint id getter test
		@Nested
		@DisplayName("getEndPointId methods")
		class TestGetEndPoint{
			@Test
			@DisplayName("returning int")
			void testGetEndPointId() {
				Timex timex = new Timex(1, TimexType.DATE, "0d", TimexMod.APPROX, false, 0, FunctionInDocument.NONE, 2, 3, "every", "w", "something");
				assertEquals(timex.getEndPoint(), 3);
				}
			@Test
			@DisplayName("returning string")
			void testGetEndPointIdStr() {
				Timex timex = new Timex(1, TimexType.DATE, "0d", TimexMod.APPROX, false, 0, FunctionInDocument.NONE, 2, 3, "every", "w", "something");
				assertEquals(timex.getEndPointStr(), "t3");
				}
		}
		
		
		//Quant getter test
		@Test
		@DisplayName("getQuant method")
		void testGetQuant() {
			Timex timex = new Timex(1, TimexType.DATE, "0d", TimexMod.APPROX, false, 0, FunctionInDocument.NONE, 2, 3, "every", "w", "something");
			assertEquals(timex.getQuant(), "every");
		}
		
		
		//Freq getter test
		@Test
		@DisplayName("getFreq method")
		void testGetFreq() {
			Timex timex = new Timex(1, TimexType.DATE, "0d", TimexMod.APPROX, false, 0, FunctionInDocument.NONE, 2, 3, "every", "w", "something");
			assertEquals(timex.getFreq(), "w");
		}
	}	
	

}
