package gov.va.vinci.dart.biz;

import java.util.List;
import java.util.Set;

import gov.va.vinci.dart.common.SingletonShim;
import gov.va.vinci.dart.common.exception.ObjectNotFoundException;
import gov.va.vinci.dart.common.exception.ValidationException;
import gov.va.vinci.dart.common.test.BusinessIntegrationTest;
import gov.va.vinci.dart.service.DartObjectFactory;

import org.testng.Assert;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

public class TestPerson extends BusinessIntegrationTest {
	@BeforeTest
	public void setup() {
		SingletonShim.getBean(DartObjectFactory.class);
	}

	@Test
	public void testOne() throws Exception {
		try {
			Person.findById(0);
			Assert.fail("Expected ObjectNotFoundException");
		}
		catch (ObjectNotFoundException e) {}

		List<Person> personList = Person.listAll();
		 
		Assert.assertNotNull(personList);
		Assert.assertTrue(personList.size() > 0);
	}
	
	@Test
	public void testTwo() throws Exception {
		try {
			Person.findById(-1);
			Assert.fail("Expected ObjectNotFoundException");
		} catch (ObjectNotFoundException e) {}


		// find somebody to search for
		 List<Person> personList = Person.listAll();
		 
		 Assert.assertNotNull(personList);
		 Assert.assertTrue(personList.size() > 0);
		 
		 Person pers = personList.get(0);
		 Assert.assertNotNull(pers);
		 Assert.assertTrue(pers.getId() > 0);
		 
		Person pers2 = Person.findById(pers.getId());
		Assert.assertNotNull(pers2);
		Assert.assertEquals(pers2, pers);
	}
	
	@Test
	public void testThree() throws Exception {
		try {
			Person.findByName(null);
			Assert.fail("Expected ObjectNotFoundException");
		} catch (ValidationException e) {}

		try {
			Person.findByName("");
			Assert.fail("Expected ObjectNotFoundException");
		} catch (ValidationException e) {}

		try {
			Person.findByName("123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890");
			Assert.fail("Expected ObjectNotFoundException");
		} catch (ValidationException e) {}

		// find somebody to search for
		 List<Person> personList = Person.listAll();
		 
		 Assert.assertNotNull(personList);
		 Assert.assertTrue(personList.size() > 0);
		 
		 Person pers = personList.get(0);
		 Assert.assertNotNull(pers);
		 Assert.assertNotNull(pers.getName());
		 Assert.assertTrue(pers.getName().length() > 0);
		 
		Person pers2 = Person.findByName(pers.getName());
		Assert.assertNotNull(pers2);
		Assert.assertEquals(pers2, pers);
	}

	@Test
	public void testFour() throws Exception {
		List<Person> personList = Person.list(null);
		Assert.assertNotNull(personList);
		Assert.assertTrue(personList.size() > 0);

		personList = Person.list("");
		Assert.assertNotNull(personList);
		Assert.assertTrue(personList.size() > 0);

		// assume nobody found with ~ in their name
		personList = Person.list("~");
		Assert.assertNotNull(personList);
		Assert.assertFalse(personList.size() > 0);

		// assume somebody found with a in their name
		personList = Person.list("a");
		Assert.assertNotNull(personList);
		Assert.assertTrue(personList.size() > 0);

	}

	@Test
	public void testFive() throws Exception {

		// find somebody to search for
		 List<Person> personList = Person.listAll();
		 
		 Assert.assertNotNull(personList);
		 Assert.assertTrue(personList.size() > 0);

		 Group testGroup = null;
		 
		 for (Person pers : personList) {
			 Assert.assertNotNull(pers.getGroups());
			 if (pers.getGroups().size() > 0) {
				 testGroup = (Group)pers.getGroups().iterator().next();
				 break;
			 }
		 }

		 Assert.assertNotNull(testGroup);

		 // got all the people in that group
		 personList = Person.listByGroup(testGroup.getId());

		 Assert.assertNotNull(personList);
		 Assert.assertTrue(personList.size() > 0);

		 // do all of the people listed have the correct group in their group list?
		 for (Person pers : personList) {
			 Assert.assertTrue(pers.getGroups().contains(testGroup));
		 }

		 // does the selected group have all the listed people?
		 for (Person pers : testGroup.getMembers()) {
			 Assert.assertTrue(personList.contains(pers));
		 }
		 
	}

	@Test
	public void testSix() throws Exception {

		// find somebody to search for
		 List<Person> personList = Person.listAll();
		 
		 Assert.assertNotNull(personList);
		 Assert.assertTrue(personList.size() > 0);

		 Role testRole = null;
		 
		 for (Person pers : personList) {
			 Assert.assertNotNull(pers.getGroups());
			 if (pers.getRoles().size() > 0) {
				 testRole = (Role)pers.getRoles().iterator().next();
				 break;
			 }
		 }

		 Assert.assertNotNull(testRole);

		 // got all the people in that group
		 personList = Person.listAllWithRole(testRole.getId());

		 Assert.assertNotNull(personList);
		 Assert.assertTrue(personList.size() > 0);

		 // do all of the people listed have the correct group in their group list?
		 for (Person pers : personList) {
			 Assert.assertTrue(pers.getRoles().contains(testRole));
		 }
	}
	
	@Test
	public void testSeven() throws Exception {

		Person pers = Person.findById(1006);
		 Assert.assertNotNull(pers);

		 Assert.assertNotNull(pers.getLocation());
		 Assert.assertNotNull(pers.getGroups());
		 Assert.assertNotNull(pers.getRoles());
		 Assert.assertNotNull(pers.listRoles());
		 Assert.assertNotNull(pers.getFullName());
		 
		 Assert.assertNotNull(pers.getTasks());
		 
		 Assert.assertTrue(pers.getRoles().size() > 0);
		 Role role = pers.getRoles().iterator().next();
		 Assert.assertTrue(pers.hasRole(role));
		 Assert.assertFalse(pers.hasRole(null));
		 
		 Assert.assertTrue(pers.getGroups().size() > 0);
		 Group group = pers.getGroups().iterator().next();
		 Assert.assertTrue(pers.inGroup(group));
		 Assert.assertFalse(pers.inGroup(null));

		 Set<Person> pSet = Person.findAllWithRole(role);
		 Assert.assertNotNull(pSet);
		 Assert.assertTrue(pSet.size() > 0);
		 Assert.assertTrue(pSet.contains(pers));
	}	

	@Test
	public void testEight() throws Exception {
		Location loc = Location.findById(1);
		
		try {
			Person.create(null, "fullname", loc);
			Assert.fail("Expected ValidationException");
		}
		catch (ValidationException e) {}
		
		try {
			Person.create("", "fullname", loc);
			Assert.fail("Expected ValidationException");
		}
		catch (ValidationException e) {}

		try {
			Person.create(TestResearchStudy.longString(1025), "fullname", loc);
			Assert.fail("Expected ValidationException");
		}
		catch (ValidationException e) {}

		try {
			Person.create("name", null, loc);
			Assert.fail("Expected ValidationException");
		}
		catch (ValidationException e) {}
		
		try {
			Person.create("name", "", loc);
			Assert.fail("Expected ValidationException");
		}
		catch (ValidationException e) {}

		try {
			Person.create("name", TestResearchStudy.longString(1025), loc);
			Assert.fail("Expected ValidationException");
		}
		catch (ValidationException e) {}

		try {
			Person.create("name", "fullname", null);
			Assert.fail("Expected ValidationException");
		}
		catch (ValidationException e) {}

		Person pers = Person.create("name", "fullname", loc);
		Assert.assertNotNull(pers);
		Assert.assertTrue(pers.getId() > 1);
		Assert.assertEquals(pers.getName(), "name");
		Assert.assertEquals(pers.getFullName(), "fullname");
		Assert.assertEquals(pers.getLocation(), loc);
		
		Person pers2 = Person.findById(pers.getId());
		Assert.assertNotNull(pers2);
		Assert.assertEquals(pers2, pers);

		try {
			pers2.modify(null, "fullname");
			Assert.fail("Expected ValidationException");
		}
		catch (ValidationException e) {}
		
		try {
			pers2.modify("", "fullname");
			Assert.fail("Expected ValidationException");
		}
		catch (ValidationException e) {}

		try {
			pers2.modify(TestResearchStudy.longString(1025), "fullname");
			Assert.fail("Expected ValidationException");
		}
		catch (ValidationException e) {}

		try {
			pers2.modify("name", null);
			Assert.fail("Expected ValidationException");
		}
		catch (ValidationException e) {}
		
		try {
			pers2.modify("name", "");
			Assert.fail("Expected ValidationException");
		}
		catch (ValidationException e) {}

		try {
			pers2.modify("name", TestResearchStudy.longString(1025));
			Assert.fail("Expected ValidationException");
		}
		catch (ValidationException e) {}

		pers2.modify("one", "two");
		
		Person pers3 = Person.findById(pers.getId());
		Assert.assertNotNull(pers3);
		Assert.assertEquals(pers3, pers);
		Assert.assertEquals(pers3.getName(), "one");
		Assert.assertEquals(pers3.getFullName(), "two");

		// fails as a side effect of the mock implementation
//		Person pers4 = Person.findByName("one");
//		Assert.assertNotNull(pers4);
//		Assert.assertEquals(pers4, pers);

		Assert.assertTrue(pers.hashCode() > 0);
		Assert.assertEquals(pers.compareTo(pers3), 0);
		
		Person pers5 = Person.findById(1006);
		Assert.assertNotNull(pers5);
		Assert.assertNotEquals(pers5, pers);
		Assert.assertNotEquals(pers.compareTo(pers5), 0);
		
	}
	
}
