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.Term;
import edu.fiu.jtlex.ITerm.NamedEntity;
import edu.fiu.jtlex.ITerm.PartOfSpeech;
import edu.fiu.jtlex.data.IInstance.Aspect;
import edu.fiu.jtlex.data.ITimex.TimexType;

/**
 * @author jjime178
 *
 */

public class TermTest {
	//Tests constructor
	@Nested
	@DisplayName("Testing Constructor")
	class testConstructor{
		//Id Test
		@Nested
		@DisplayName("If ID is")
		class TestID{
			/**
			* Test case ID: testIdNegative()
			* Purpose: Test negative id in constructor
			* Test set up: assertThrows(IllegalArgumentException.class, ()-> new Term(...));
			* Test input: -1, "month", "month.01", "The past 20 months", "1", 16, 24, PartOfSpeech.CC, "5", "P20M",
						NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2"
			* Expected output: Throws Exception
			*/
			@Test
			@DisplayName("negative")
			void testIdNegative() {
				assertThrows(IllegalArgumentException.class, ()-> new Term(-1, "month", "month.01", "The past 20 months", "1", 16, 24, PartOfSpeech.CC, "5", "P20M",
						NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2", null, Aspect.NONE));
			}
		}
		//Lemma Test
		@Nested
		@DisplayName("If Lemma is")
		class TestLemma{
			/**
			* Test case ID: testLemmaNull()
			* Purpose: Test null lemma in constructor
			* Test set up: assertThrows(IllegalArgumentException.class, ()-> new Term(...));
			* Test input: 391, null, "month.01", "The past 20 months", "1", 16, 24, PartOfSpeech.CC, "5", "P20M",
						NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2"
			* Expected output: Throws Exception
			*/
			@Test
			@DisplayName("null")
			void testLemmaNull() {
				assertThrows(IllegalArgumentException.class, ()-> new Term(391, null, "month.01", "The past 20 months", "1", 16, 24, PartOfSpeech.CC, "5", "P20M",
						NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2", null, Aspect.NONE));
			}
		}
		//Text Test
		@Nested
		@DisplayName("If Text is")
		class TestText{
			/**
			* Test case ID: testTextNull()
			* Purpose: Test null text in constructor
			* Test set up: assertThrows(IllegalArgumentException.class, ()-> new Term(...));
			* Test input: 391, "month", "month.01", null, "1", 16, 24, PartOfSpeech.CC, "5", "P20M",
						NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2"
			* Expected output: Throws Exception
			*/
			@Test
			@DisplayName("null")
			void testTextNull() {
				assertThrows(IllegalArgumentException.class, ()-> new Term(391, "month", "month.01", null, "1", 16, 24, PartOfSpeech.CC, "5", "P20M",
						NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2", null, Aspect.NONE));
			}
		}
		//Begin Index Test
		@Nested
		@DisplayName("If Begin Index is")
		class TestBeginIndex{
			/**
			* Test case ID: testBeginIndexNegative()
			* Purpose: Test negative begin index in constructor
			* Test set up: assertThrows(IllegalArgumentException.class, ()-> new Term(...));
			* Test input: 391, "month", "month.01", "The past 20 months", "1", -1, 24, PartOfSpeech.CC, "5", "P20M",
						NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2"
			* Expected output: Throws Exception
			*/
			@Test
			@DisplayName("negative")
			void testBeginIndexNegative() {
				assertThrows(IllegalArgumentException.class, ()-> new Term(391, "month", "month.01", "The past 20 months", "1", -1, 24, PartOfSpeech.CC, "5", "P20M",
						NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2", null, Aspect.NONE));
			}
		}
		//End Index Test
		@Nested
		@DisplayName("If End Index is")
		class TestEndIndex{
			/**
			* Test case ID: testEndIndexNegative()
			* Purpose: Test negative end index in constructor
			* Test set up: assertThrows(IllegalArgumentException.class, ()-> new Term(...));
			* Test input: 391, "month", "month.01", "The past 20 months", "1", 16, -1, PartOfSpeech.CC, "5", "P20M",
						NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2"
			* Expected output: Throws Exception
			*/
			@Test
			@DisplayName("negative")
			void testEndIndexNegative() {
				assertThrows(IllegalArgumentException.class, ()-> new Term(391, "month", "month.01", "The past 20 months", "1", 16, -1, PartOfSpeech.CC, "5", "P20M",
						NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2", null, Aspect.NONE));
			}
			/**
			* Test case ID: testEndIndexLessThanBegin()
			* Purpose: Test end index being less than begin index in constructor
			* Test set up: assertThrows(IllegalArgumentException.class, ()-> new Term(...));
			* Test input: 391, "month", "month.01", "The past 20 months", "1", 16, 14, PartOfSpeech.CC, "5", "P20M",
						NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2"
			* Expected output: Throws Exception
			*/
			@Test
			@DisplayName("less than begin")
			void testEndIndexLessThanBegin() {
				assertThrows(IllegalArgumentException.class, ()-> new Term(391, "month", "month.01", "The past 20 months", "1", 16, 14, PartOfSpeech.CC, "5", "P20M",
						NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2", null, Aspect.NONE));
			}
		}
		//POS Test
		@Nested
		@DisplayName("If POS is")
		class TestPOS{
			/**
			* Test case ID: testPOSNull()
			* Purpose: Test null pos tag in constructor
			* Test set up: assertThrows(IllegalArgumentException.class, ()-> new Term(...));
			* Test input: 391, "month", "month.01", "The past 20 months", "1", 16, 24, null, "5", "P20M",
						NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2"
			* Expected output: Throws Exception
			*/
			@Test
			@DisplayName("null")
			void testPOSNull() {
				assertThrows(IllegalArgumentException.class, ()-> new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, null, "5", "P20M",
						NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2", null, Aspect.NONE));
			}
		}
		//Element ID Test
		@Nested
		@DisplayName("If Element ID is")
		class TestElementID{
			/**
			* Test case ID: testElementIDNull()
			* Purpose: Test null element id in constructor
			* Test set up: assertThrows(IllegalArgumentException.class, ()-> new Term(...));
			* Test input: 391, "month", "month.01", "The past 20 months", "1", 16, 24, PartOfSpeech.CC, null, "P20M",
						NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2"
			* Expected output: Throws Exception
			*/
			@Test
			@DisplayName("null")
			void testElementIDNull() {
				assertThrows(IllegalArgumentException.class, ()-> new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, PartOfSpeech.CC, null, "P20M",
						NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2", null, Aspect.NONE));
			}
		}
	}
	
	//Tests the 12 getter methods
	@Nested
	@DisplayName("Testing getters")
	class TestGetters{
		/**
		* Test case ID: testGetID()
		* Purpose: Test ID getter
		* Test set up: Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, 
		* 				PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2")
		* Test input: 391
		* Expected output: Assert Equals
		*/
		@Test
		@DisplayName("getID method")
		void testGetID() {
			Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2", null, Aspect.NONE);
			assertEquals(term.getId(), 391);
		}
		/**
		* Test case ID: testGetLemma()
		* Purpose: Test Lemma getter
		* Test set up: Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, 
		* 				PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2")
		* Test input: "month"
		* Expected output: Assert Equals
		*/
		@Test
		@DisplayName("getLemma method")
		void testGetLemma() {
			Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2", null, Aspect.NONE);
			assertEquals(term.getLemma(), "month");
		}
		/**
		* Test case ID: testGetFrameSet()
		* Purpose: Test Frame Set getter
		* Test set up: Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, 
		* 				PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2")
		* Test input: "month.01"
		* Expected output: Assert Equals
		*/
		@Test
		@DisplayName("getFrameSet method")
		void testGetFrameSet() {
			Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2", null, Aspect.NONE);;
			assertEquals(term.getFrameSet(), "month.01");
		}
		/**
		* Test case ID: testGetText()
		* Purpose: Test Text getter
		* Test set up: Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, 
		* 				PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2")
		* Test input: "The past 20 months"
		* Expected output: Assert Equals
		*/
		@Test
		@DisplayName("getText method")
		void testGetText() {
			Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2", null, Aspect.NONE);;
			assertEquals(term.getText(), "The past 20 months");
		}
		/**
		* Test case ID: testGetSentenceID()
		* Purpose: Test Sentence ID getter
		* Test set up: Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, 
		* 				PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2")
		* Test input: "1"
		* Expected output: Assert Equals
		*/
		@Test
		@DisplayName("getSentenceID method")
		void testGetSentenceID() {
			Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2", null, Aspect.NONE);;
			assertEquals(term.getSentenceId(), "1");
		}
		/**
		* Test case ID: testGetBegin()
		* Purpose: Test Begin Index getter
		* Test set up: Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, 
		* 				PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2")
		* Test input: 16
		* Expected output: Assert Equals
		*/
		@Test
		@DisplayName("getBegin method")
		void testGetBegin() {
			Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2", null, Aspect.NONE);
			assertEquals(term.getBegin(), 16);
		}
		/**
		* Test case ID: testGetEnd()
		* Purpose: Test End Index getter
		* Test set up: Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, 
		* 				PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2")
		* Test input: 24
		* Expected output: Assert Equals
		*/
		@Test
		@DisplayName("getEnd method")
		void testGetEnd() {
			Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2", null, Aspect.NONE);
			assertEquals(term.getEnd(), 24);
		}
		/**
		* Test case ID: testGetPos()
		* Purpose: Test POS tag getter
		* Test set up: Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, 
		* 				PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2")
		* Test input: PartOfSpeech.CC
		* Expected output: Assert Equals
		*/
		@Test
		@DisplayName("getPos method")
		void testGetPos() {
			Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2", null, Aspect.NONE);
			assertEquals(term.getPos(), PartOfSpeech.CC);
		}
		/**
		* Test case ID: testGetElementID()
		* Purpose: Test Element ID getter
		* Test set up: Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, 
		* 				PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2")
		* Test input: "5"
		* Expected output: Assert Equals
		*/
		@Test
		@DisplayName("getElementID method")
		void testGetElementID() {
			Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2", null, Aspect.NONE);
			assertEquals(term.getElementId(), "5");
		}
		/**
		* Test case ID: getTimexText()
		* Purpose: Test Timex Text getter
		* Test set up: Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, 
		* 				PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2")
		* Test input: "P20M"
		* Expected output: Assert Equals
		*/
		@Test
		@DisplayName("getTimexText method")
		void testGetTimexText() {
			Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2", null, Aspect.NONE);
			assertEquals(term.getTimexText(), "P20M");
		}		
		/**
		* Test case ID: testGetNamedEntity()
		* Purpose: Test Named Entity getter
		* Test set up: Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, 
		* 				PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2")
		* Test input: NamedEntity.DURATION
		* Expected output: Assert Equals
		*/
		@Test
		@DisplayName("getNamedEntity method")
		void testGetNamedEntity() {
			Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2", null, Aspect.NONE);
			assertEquals(term.getNamedEntity(), NamedEntity.DURATION);
		}
		/**
		* Test case ID: testGetNormalizedNER()
		* Purpose: Test NormalizedNER getter
		* Test set up: Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, 
		* 				PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2")
		* Test input: "P20M"
		* Expected output: Assert Equals
		*/
		@Test
		@DisplayName("getNormalizedNER method")
		void testGetNormalizedNER() {
			Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2", null, Aspect.NONE);
			assertEquals(term.getNormalizedNER(), "P20M");
		}
		/**
		* Test case ID: testGetTimexType()
		* Purpose: Test Timex Type getter
		* Test set up: Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, 
		* 				PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2")
		* Test input: TimexType.DURATION
		* Expected output: Assert Equals
		*/
		@Test
		@DisplayName("getTimexType method")
		void testGetTimexType() {
			Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2", null, Aspect.NONE);
			assertEquals(term.getTimexType(), TimexType.DURATION);
		}
		/**
		* Test case ID: testGetTID()
		* Purpose: Test TID getter
		* Test set up: Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, 
		* 				PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2")
		* Test input: "T2"
		* Expected output: Assert Equals
		*/
		@Test
		@DisplayName("getTID method")
		void testGetTID() {
			Term term  = new Term(391, "month", "month.01", "The past 20 months", "1", 16, 24, PartOfSpeech.CC, "5", "P20M", NamedEntity.DURATION, "P20M", TimexType.DURATION, "T2", null, Aspect.NONE);
			assertEquals(term.getTid(), "T2");
		}
	}
}