package gov.va.vinci.dart.biz;

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

import java.util.Date;
import java.util.List;

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

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

	@Test
	public void testOne() throws Exception {
		
		Request req = DartRequest.findById(-1);
		Assert.assertNull(req);
	}

	@Test
	public void testTwo() throws Exception {
		
		DartRequest req = DartRequest.findById(1);
		Assert.assertNotNull(req);
		
		Person requestor = req.getRequestor();
		Assert.assertNotNull(requestor);
		Assert.assertTrue(requestor.getId() > 0);

		List<DartRequest> reqlist = DartRequest.listByName(requestor.getId(), "e");
		Assert.assertNotNull(reqlist);
	}

	@Test
	public void testThree() throws Exception {

		Person pers = Person.findById(1006);
		ResearchStudy activity = ResearchStudy.findById(1);
		
		// create request 1 so we'll have something to work with
		DartRequest req = DartRequest.create("test request 1", new Date(), new Date(), pers, activity, "DNS");
		req.setWorkflowTypeId(WorkflowResolver.WF_RESEARCH_REQUEST);

		Assert.assertNotNull(req);
		Assert.assertTrue(req.getId() > 0);
		Assert.assertNotNull(req.getChangesRequestedGroups(null));
		Assert.assertNotNull(req.getComments());
		Assert.assertNotNull(req.getDataSources());
		Assert.assertNotNull(req.getDocuments());
		Assert.assertNotNull(req.getEvents());
		Assert.assertNotNull(req.getNarratives());
		Assert.assertNotNull(req.getParticipants());
		
//		Assert.assertNotNull(req.getReviews());
		Assert.assertNotNull(req.getAllReviews());
		
		Assert.assertNotNull(req.getSites());
		
		DartRequest req2 = DartRequest.findById(req.getId());
		Assert.assertNotNull(req2);
		Assert.assertEquals(req2, req);
	}

	@Test
	public void testFour() throws Exception {

		DartRequest req = DartRequest.findById(1);
		Assert.assertNotNull(req);
		
		List<DartRequest> reqList = DartRequest.listAll();
		Assert.assertNotNull(reqList);
		Assert.assertTrue(reqList.size() > 0);
		Assert.assertTrue(reqList.contains(req));
	}

	@Test
	public void testFive() throws Exception {

		Person pers = Person.findById(1006);
		ResearchStudy activity = ResearchStudy.findById(1);
		
		// create request 1 so we'll have something to work with
		DartRequest req = DartRequest.create("test request 1", new Date(), new Date(), pers, activity, "DNS");
		req.setWorkflowTypeId(WorkflowResolver.WF_RESEARCH_REQUEST);

		Assert.assertNotNull(req);
		Assert.assertTrue(req.getId() > 0);
		Assert.assertEquals(req.getActivity(), activity);
		
		List<DartRequest> reqList = DartRequest.listByActivityId(activity.getId());
		Assert.assertNotNull(reqList);
		Assert.assertTrue(reqList.size() > 0);
		Assert.assertTrue(reqList.contains(req));
	}

	@Test
	public void testSix() throws Exception {

		Person pers = Person.findById(1006);
		ResearchStudy activity = ResearchStudy.findById(1);
		
		// create request 1 so we'll have something to work with
		DartRequest req = DartRequest.create("test request 1", new Date(), new Date(), pers, activity, "DNS");
		req.setWorkflowTypeId(WorkflowResolver.WF_RESEARCH_REQUEST);

		Assert.assertNotNull(req);
		Assert.assertTrue(req.getId() > 0);
		Assert.assertEquals(req.getActivity(), activity);
		
		List<DartRequest> reqList = DartRequest.listByRequestor(pers.getId());
		Assert.assertNotNull(reqList);
		Assert.assertTrue(reqList.size() > 0);
		Assert.assertTrue(reqList.contains(req));
	}

	@Test
	public void testSeven() throws Exception {

		Person pers = Person.findById(1006);
		ResearchStudy activity = ResearchStudy.findById(1);
		
		// create request 1 so we'll have something to work with
		DartRequest req = DartRequest.create("test request 1", new Date(), new Date(), pers, activity, "DNS");
		req.setWorkflowTypeId(WorkflowResolver.WF_RESEARCH_REQUEST);

		Assert.assertNotNull(req);
		Assert.assertTrue(req.getId() > 0);
		Assert.assertEquals(req.getActivity(), activity);

		try {
			DartRequest.listRecentByRequestor(pers.getId(), 1000);
			Assert.fail("Expected ValidationException");
		} catch (ValidationException e) {}
		
		List<DartRequest> reqList = DartRequest.listRecentByRequestor(pers.getId(), 10);
		Assert.assertNotNull(reqList);
		Assert.assertTrue(reqList.size() > 0);
		Assert.assertTrue(reqList.contains(req));
	}

	@Test
	public void testEight() throws Exception {

		Person pers = Person.findById(1006);
		ResearchStudy activity = ResearchStudy.findById(1);

		Assert.assertNotNull(pers);
		Assert.assertNotNull(pers.getName());
		Assert.assertTrue(pers.getName().length() > 0);
		
		// create request 1 so we'll have something to work with
		DartRequest req = DartRequest.create("test request 1", new Date(), new Date(), pers, activity, "DNS");
		req.setWorkflowTypeId(WorkflowResolver.WF_RESEARCH_REQUEST);

		Assert.assertNotNull(req);
		Assert.assertTrue(req.getId() > 0);
		Assert.assertEquals(req.getActivity(), activity);
		
		DartRequest amendment = DartRequest.findMostRecentAmendment(req.getId());
		Assert.assertNull(amendment);
		
		req.approve(null, pers.getName());
		
		// now how do you propose to test when it has an amendment?
	}

	@Test
	public void testNine() throws Exception {

		Person pers = Person.findById(1006);
		ResearchStudy activity = ResearchStudy.findById(1);
		
		// create request 1 so we'll have something to work with
		DartRequest req = DartRequest.create("test request 1", new Date(), new Date(), pers, activity, "DNS");
		req.setWorkflowTypeId(WorkflowResolver.WF_RESEARCH_REQUEST);

		Assert.assertNotNull(req);
		Assert.assertTrue(req.getId() > 0);
		Assert.assertEquals(req.getActivity(), activity);
		
		// need to submit that request to guarantee there is something to see in the list
		req.submit(pers.getName()); 

		Assert.assertEquals(req.getStatus(), RequestStatus.SUBMITTED);
		
		List<RequestSummary> rsList = DartRequest.listAllButInitiated();
		Assert.assertNotNull(rsList);

		boolean foundIt = false;
		for (RequestSummary rs : rsList) {
			if (rs.getRequestId() == req.getId()) {
				foundIt = true;
				break;
			}
		}

		Assert.assertTrue(foundIt);
		
		List<DartRequest> reqList2 = DartRequest.listAllSubmitted();
		Assert.assertNotNull(reqList2);
		Assert.assertTrue(reqList2.contains(req));

	}

	@Test
	public void testTen() throws Exception {

		Person pers = Person.findById(1006);
		ResearchStudy activity = ResearchStudy.findById(1);

		Assert.assertNotNull(pers);
		Assert.assertNotNull(pers.getName());
		Assert.assertTrue(pers.getName().length() > 0);
		
		// create request 1 so we'll have something to work with
		DartRequest req = DartRequest.create("test request 1", new Date(), new Date(), pers, activity, "DNS");
		req.setWorkflowTypeId(WorkflowResolver.WF_RESEARCH_REQUEST);

		Assert.assertNotNull(req);
		Assert.assertTrue(req.getId() > 0);
		Assert.assertEquals(req.getActivity(), activity);
		Assert.assertFalse(req.isAmendment());
		Assert.assertEquals(req.getHeadId(), 0);
		
		DartRequest amendment = DartRequest.findMostRecentAmendment(req.getId());
		Assert.assertNull(amendment);
		
		req.approve(null, pers.getName());

		DartRequest amendmentReq = DartRequest.create("test amendment 1", new Date(), new Date(), pers, activity, "DNS");
		req.setWorkflowTypeId(WorkflowResolver.WF_RESEARCH_REQUEST);

		// try the amendment creation method in Request.java
		amendmentReq.createAmendment(req);

		Assert.assertFalse(req.isAmendment());

		DartRequest req2 = DartRequest.findMostRecentAmendment(req.getId());
		Assert.assertNotNull(req2);

		Assert.assertNotEquals(req2, req);
		Assert.assertEquals(req2, amendmentReq);
		Assert.assertTrue(req2.isAmendment());
	}

	@Test
	public void testEleven() throws Exception {

		Person pers = Person.findById(1006);
		ResearchStudy activity = ResearchStudy.findById(1);

		Assert.assertNotNull(pers);
		Assert.assertNotNull(pers.getName());
		Assert.assertTrue(pers.getName().length() > 0);
		
		// create request 1 so we'll have something to work with
		DartRequest req = DartRequest.create("test request 1", new Date(), new Date(), pers, activity, "DNS");
		req.setWorkflowTypeId(WorkflowResolver.WF_RESEARCH_REQUEST);

		Assert.assertNotNull(req);
		Assert.assertTrue(req.getId() > 0);
		Assert.assertEquals(req.getActivity(), activity);
		Assert.assertFalse(req.isAmendment());
		Assert.assertEquals(req.getHeadId(), 0);
		
		DartRequest amendment = DartRequest.findMostRecentAmendment(req.getId());
		Assert.assertNull(amendment);
		
		req.approve(null, pers.getName());

		// try the amendment creation method in DartRequest.java
		DartRequest amendmentReq = req.createAmendment("DNS");

		Assert.assertFalse(req.isAmendment());

		DartRequest req2 = DartRequest.findMostRecentAmendment(req.getId());
		Assert.assertNotNull(req2);

		Assert.assertNotEquals(req2, req);
		Assert.assertEquals(req2, amendmentReq);
		Assert.assertTrue(req2.isAmendment());
	}

	@Test
	public void testTwelve() throws Exception {

		Person pers = Person.findById(1006);
		ResearchStudy activity = ResearchStudy.findById(1);

		Assert.assertNotNull(pers);
		Assert.assertNotNull(pers.getName());
		Assert.assertTrue(pers.getName().length() > 0);
		
		// create request 1 so we'll have something to work with
		DartRequest req = DartRequest.create("test request 1", new Date(), new Date(), pers, activity, "DNS");
		req.setWorkflowTypeId(WorkflowResolver.WF_RESEARCH_REQUEST);

		Assert.assertNotNull(req);
		Assert.assertTrue(req.getId() > 0);
		
		req.modify("test", req.getDataSourceStartDate(), req.getDataSourceEndDate(), req.getIrbNumber(), req.getIrbExpiration(), req.getUpdatedBy());
		
		DartRequest req2 = DartRequest.findById(req.getId());
				
		Assert.assertNotNull(req2);
		Assert.assertEquals(req2.getName(), "test");

		Date newStart = new Date();
		req.modify("test", newStart, req.getDataSourceEndDate(), req.getIrbNumber(), req.getIrbExpiration(), req.getUpdatedBy());
		
		req2 = DartRequest.findById(req.getId());
		Assert.assertNotNull(req2);
		Assert.assertEquals(req.getDataSourceStartDate(), newStart);

		req.modify("test", req.getDataSourceStartDate(), newStart, req.getIrbNumber(), req.getIrbExpiration(), req.getUpdatedBy());
		
		req2 = DartRequest.findById(req.getId());
		Assert.assertNotNull(req2);
		Assert.assertEquals(req.getDataSourceEndDate(), newStart);

		req.modify("test", req.getDataSourceStartDate(), req.getDataSourceEndDate(), "irb", req.getIrbExpiration(), req.getUpdatedBy());
		
		req2 = DartRequest.findById(req.getId());
		Assert.assertNotNull(req2);
		Assert.assertEquals(req.getIrbNumber(), "irb");

		req.modify("test", req.getDataSourceStartDate(), req.getDataSourceEndDate(), req.getIrbNumber(), newStart, req.getUpdatedBy());
		
		req2 = DartRequest.findById(req.getId());
		Assert.assertNotNull(req2);
		Assert.assertEquals(req.getIrbExpiration(), newStart);

		req.modify("test", req.getDataSourceStartDate(), req.getDataSourceEndDate(), req.getIrbNumber(), req.getIrbExpiration(), "updated");
		
		req2 = DartRequest.findById(req.getId());
		Assert.assertNotNull(req2);
		Assert.assertEquals(req.getUpdatedBy(), "updated");

		Assert.assertFalse(req.isHipaaConsent());
		req.setHipaaConsent(true);
		
		req2 = DartRequest.findById(req.getId());
		Assert.assertNotNull(req2);
		Assert.assertTrue(req2.isHipaaConsent());

		Assert.assertFalse(req.isHipaaWaiver());
		req.setHipaaWaiver(true);
		
		req2 = DartRequest.findById(req.getId());
		Assert.assertNotNull(req2);
		Assert.assertTrue(req2.isHipaaWaiver());

		Assert.assertFalse(req.isLocalServer());
		req.setLocalServer(true);
		
		req2 = DartRequest.findById(req.getId());
		Assert.assertNotNull(req2);
		Assert.assertTrue(req2.isLocalServer());

		Assert.assertFalse(req.isDataMart());
		req.setDataMart(true);
		
		req2 = DartRequest.findById(req.getId());
		Assert.assertNotNull(req2);
		Assert.assertTrue(req2.isDataMart());

		Assert.assertFalse(req.isRealSSN());
		req.setRealSSN(true);
		
		req2 = DartRequest.findById(req.getId());
		Assert.assertNotNull(req2);
		Assert.assertTrue(req2.isRealSSN());

		Assert.assertFalse(req.isScrambledSSN());
		req.setScrambledSSN(true);
		
		req2 = DartRequest.findById(req.getId());
		Assert.assertNotNull(req2);
		Assert.assertTrue(req2.isScrambledSSN());

		Assert.assertFalse(req.isPhiData());
		req.setPhiData(true);
		
		req2 = DartRequest.findById(req.getId());
		Assert.assertNotNull(req2);
		Assert.assertTrue(req2.isPhiData());

		Assert.assertNull(req.getDataSourceLocation());
		req.setDataSourceLocation("one");
		
		req2 = DartRequest.findById(req.getId());
		Assert.assertNotNull(req2);
		Assert.assertEquals(req2.getDataSourceLocation(), "one");

		Assert.assertNull(req.getLocalServerLocation());
		req.setLocalServerLocation("two");
		
		req2 = DartRequest.findById(req.getId());
		Assert.assertNotNull(req2);
		Assert.assertEquals(req2.getLocalServerLocation(), "two");

		Assert.assertNull(req.getLocalServerAddress());
		req.setLocalServerAddress("three");
		
		req2 = DartRequest.findById(req.getId());
		Assert.assertNotNull(req2);
		Assert.assertEquals(req2.getLocalServerAddress(), "three");
		
		Assert.assertNull(req.getLocalServerBuilding());
		req.setLocalServerBuilding("four");
		
		req2 = DartRequest.findById(req.getId());
		Assert.assertNotNull(req2);
		Assert.assertEquals(req2.getLocalServerBuilding(), "four");

		Assert.assertNull(req.getLocalServerRoomNumber());
		req.setLocalServerRoomNumber("five");
		
		req2 = DartRequest.findById(req.getId());
		Assert.assertNotNull(req2);
		Assert.assertEquals(req2.getLocalServerRoomNumber(), "five");
		
		
		Assert.assertNotNull(req.getDataSources());
		Assert.assertEquals(req.getDataSources().size(), 0);

		DataSource ds = DataSource.findById(1);
		Assert.assertNotNull(ds);
		Assert.assertEquals(ds.getId(), 1);
		req.getDataSources().add(ds);

		req2 = DartRequest.findById(req.getId());
		Assert.assertNotNull(req2);
		Assert.assertNotNull(req2.getDataSources());
		Assert.assertTrue(req2.getDataSources().contains(ds));

		
		WorkflowResolver workflowResolver = DartObjectFactory.getInstance().getWorkflowResolver();
		
		workflowResolver.resolve(req).initialize(null, req, "DNS");
		
		Assert.assertFalse(workflowResolver.resolve(req).isReadyForInitialReview(null, req));
		Assert.assertFalse(workflowResolver.resolve(req).isInitialReviewCompleted(null, req));
		Assert.assertFalse(workflowResolver.resolve(req).isReadyForFinalReview(null, req));
		Assert.assertFalse(workflowResolver.resolve(req).isFinalReviewCompleted(null, req));
	}
	
	@Test
	public void testThirteen() throws Exception {

		Person pers = Person.findById(1006);
		ResearchStudy activity = ResearchStudy.findById(1);

		Assert.assertNotNull(pers);
		Assert.assertNotNull(pers.getName());
		Assert.assertTrue(pers.getName().length() > 0);
		
		// create request 1 so we'll have something to work with
		DartRequest req = DartRequest.create("test request 1", new Date(), new Date(), pers, activity, "DNS");
		req.setWorkflowTypeId(WorkflowResolver.WF_RESEARCH_REQUEST);

		Assert.assertNotNull(req);
		Assert.assertTrue(req.getId() > 0);

		DataSource ds = DataSource.findById(1);
		Assert.assertNotNull(ds);
		Assert.assertEquals(ds.getId(), 1);
		Assert.assertNotNull(ds.getEvaluator());
		req.getDataSources().add(ds);

		// request needs a primary site
		req.getSites().add(pers.getLocation());
		req.setPrimaryLocation(pers.getLocation());

		// request needs a participant
		Participant part = Participant.create(pers, req, pers.getLocation(), true, true, true);
		Assert.assertNotNull(part);
		Assert.assertTrue(part.getId() > 0);
		
		Assert.assertNotNull(req.getDocuments());
		Assert.assertEquals(req.getDocuments().size(), 0);
		
		// call the document rule evaluator
		req.createDocuments("DNS");
		
		Assert.assertNotNull(req.getDocuments());
		Assert.assertTrue(req.getDocuments().size() > 0);
		
		List<RequestLocationDocument> rldList = RequestLocationDocument.listByRequestId(req.getId());
		Assert.assertNotNull(rldList);
		Assert.assertTrue(rldList.size() > 0);

		List<RequestParticipantDocument> rpdList = RequestParticipantDocument.listByRequestId(req.getId());
		Assert.assertNotNull(rpdList);
		Assert.assertTrue(rpdList.size() >= 0);
	}

	@Test
	public void testFourteen() throws Exception {

		Person pers = Person.findById(1006);
		ResearchStudy activity = ResearchStudy.findById(1);

		Assert.assertNotNull(pers);
		Assert.assertNotNull(pers.getName());
		Assert.assertTrue(pers.getName().length() > 0);
		
		// create request 1 so we'll have something to work with
		DartRequest req = DartRequest.create("test request 1", new Date(), new Date(), pers, activity, "DNS");
		req.setWorkflowTypeId(WorkflowResolver.WF_NDS);  // required for the workflow engine (top-level workflow type)
		
		Assert.assertNotNull(req);
		Assert.assertTrue(req.getId() > 0);

		WorkflowResolver workflowResolver = DartObjectFactory.getInstance().getWorkflowResolver();
		workflowResolver.resolve(req).initialize(null, req, "DNS");
		
		DataSource ds = DataSource.findById(1);
		Assert.assertNotNull(ds);
		Assert.assertEquals(ds.getId(), 1);
		Assert.assertNotNull(ds.getEvaluator());
		req.getDataSources().add(ds);

		// request needs a primary site
		req.getSites().add(pers.getLocation());
		req.setPrimaryLocation(pers.getLocation());
		
		// request needs a participant
		Participant part = Participant.create(pers, req, pers.getLocation(), true, true, true);
		Assert.assertNotNull(part);
		Assert.assertTrue(part.getId() > 0);
		
		Assert.assertNotNull(req.getDocuments());
		Assert.assertEquals(req.getDocuments().size(), 0);
		
		// call the document rule evaluator
		req.createDocuments("DNS");
		
		Assert.assertNotNull(req.getDocuments());
		Assert.assertTrue(req.getDocuments().size() > 0);

		Assert.assertFalse(workflowResolver.resolve(req).isReadyForInitialReview(null, req));	//top-level workflow

		workflowResolver.resolve(req).submit(null, req, "DNS");
		
		req.submit("DNS");
	
		Assert.assertFalse(workflowResolver.resolve(req).isReadyForFinalReview(null, req));
		Assert.assertFalse(workflowResolver.resolve(req).isInitialReviewCompleted(null, req));

		req.approve(null, "DNS");

		workflowResolver.resolve(req).approve(null, null, req, "DNS");

		// why doesn't the approve transition go to the final state?
	}
		
	@Test
	public void testFifteen() throws Exception {

		Person pers = Person.findById(1006);
		ResearchStudy activity = ResearchStudy.findById(1);

		Assert.assertNotNull(pers);
		Assert.assertNotNull(pers.getName());
		Assert.assertTrue(pers.getName().length() > 0);
		
		// create request 1 so we'll have something to work with
		DartRequest req = DartRequest.create("test request 1", new Date(), new Date(), pers, activity, "DNS");
		req.setWorkflowTypeId(WorkflowResolver.WF_RESEARCH_REQUEST);

		Assert.assertNotNull(req);
		Assert.assertTrue(req.getId() > 0);
		Assert.assertEquals(req.getActivity(), activity);
		Assert.assertFalse(req.isAmendment());
		Assert.assertEquals(req.getHeadId(), 0);

		DataSource ds = DataSource.findById(1);
		Assert.assertNotNull(ds);
		Assert.assertEquals(ds.getId(), 1);
		Assert.assertNotNull(ds.getEvaluator());
		req.getDataSources().add(ds);

		Assert.assertNotNull(req.getDataSources());
		Assert.assertEquals(req.getDataSources().size(), 1);
		Assert.assertTrue(req.getDataSources().contains(ds));
		
		DartRequest amendment = DartRequest.findMostRecentAmendment(req.getId());
		Assert.assertNull(amendment);
		
		req.approve(null, pers.getName());

		// create an amendment
		DartRequest amendmentReq = req.createAmendment("DNS");

		DartRequest req2 = DartRequest.findMostRecentAmendment(req.getId());
		Assert.assertNotNull(req2);

		Assert.assertNotEquals(req2, req);
		Assert.assertEquals(req2, amendmentReq);
		Assert.assertTrue(req2.isAmendment());

		Assert.assertNotNull(req2.getDataSources());
		Assert.assertEquals(req2.getDataSources().size(), 1);
		Assert.assertTrue(req2.getDataSources().contains(ds));  // data sources are copied from the original request

		DataSource ds2 = DataSource.findById(2);
		Assert.assertNotNull(ds2);
		Assert.assertEquals(ds2.getId(), 2);
		amendmentReq.getDataSources().clear();
		amendmentReq.getDataSources().add(ds2);

		amendmentReq.approve(null, pers.getName());

		// create an amendment of the amendment
		DartRequest amendmentReq2 = amendmentReq.createAmendment("DNS");

		DartRequest req3 = DartRequest.findMostRecentAmendment(req.getId());
		Assert.assertNotNull(req3);

		Assert.assertNotEquals(req3, req);
		Assert.assertEquals(req3, amendmentReq2);
		Assert.assertTrue(req3.isAmendment());

		// VINCI-298  data sources in the amendment of an amendment

		Assert.assertNotNull(req3.getDataSources());
		Assert.assertEquals(req3.getDataSources().size(), 1);
		Assert.assertTrue(req3.getDataSources().contains(ds2));  // data sources are copied from the recent amendment
		Assert.assertFalse(req3.getDataSources().contains(ds));  // data sources are *NOT* copied from the original request
	}

	@Test
	public void testSixteen() throws Exception {

		Person pers = Person.findById(1006);
		ResearchStudy activity = ResearchStudy.findById(1);

		Assert.assertNotNull(pers);
		Assert.assertNotNull(pers.getName());
		Assert.assertTrue(pers.getName().length() > 0);
		
		// create request 1 so we'll have something to work with
		DartRequest req = DartRequest.create("test request 1", new Date(), new Date(), pers, activity, "DNS");
		req.setWorkflowTypeId(WorkflowResolver.WF_RESEARCH_REQUEST);

		Assert.assertNotNull(req);
		Assert.assertTrue(req.getId() > 0);
		Assert.assertEquals(req.getActivity(), activity);
		Assert.assertFalse(req.isAmendment());
		Assert.assertEquals(req.getHeadId(), 0);

		Location loc = Location.findById(1);
		Assert.assertNotNull(loc);
		Assert.assertEquals(loc.getId(), 1);
		req.getSites().add(loc);
		req.setPrimaryLocation(loc);

		Assert.assertNotNull(req.getSites());
		Assert.assertEquals(req.getSites().size(), 1);
		Assert.assertTrue(req.getSites().contains(loc));
		Assert.assertEquals(req.getPrimaryLocation(), loc);
		
		DartRequest amendment = DartRequest.findMostRecentAmendment(req.getId());
		Assert.assertNull(amendment);
		
		req.approve(null, pers.getName());

		// create an amendment
		DartRequest amendmentReq = req.createAmendment("DNS");

		DartRequest req2 = DartRequest.findMostRecentAmendment(req.getId());
		Assert.assertNotNull(req2);

		Assert.assertNotEquals(req2, req);
		Assert.assertEquals(req2, amendmentReq);
		Assert.assertTrue(req2.isAmendment());

		Assert.assertNotNull(req2.getSites());
		Assert.assertEquals(req2.getSites().size(), 1);
		Assert.assertTrue(req2.getSites().contains(loc));  // data sources are copied from the original request

		Location loc2 = Location.findById(26);
		Assert.assertNotNull(loc2);
		Assert.assertEquals(loc2.getId(), 26);
		amendmentReq.getSites().clear();
		amendmentReq.getSites().add(loc2);
		amendmentReq.setPrimaryLocation(loc2);
		Assert.assertEquals(req.getPrimaryLocation(), loc);
		Assert.assertEquals(amendmentReq.getPrimaryLocation(), loc2);
		
		amendmentReq.approve(null, pers.getName());

		// create an amendment of the amendment
		DartRequest amendmentReq2 = amendmentReq.createAmendment("DNS");

		DartRequest req3 = DartRequest.findMostRecentAmendment(req.getId());
		Assert.assertNotNull(req3);

		Assert.assertNotEquals(req3, req);
		Assert.assertEquals(req3, amendmentReq2);
		Assert.assertTrue(req3.isAmendment());

		// sites in the amendment of an amendment

		Assert.assertNotNull(req3.getSites());
		Assert.assertEquals(req3.getSites().size(), 1);
		Assert.assertTrue(req3.getSites().contains(loc2));  // site locations are copied from the recent amendment
		Assert.assertFalse(req3.getSites().contains(loc));  // site locations are *NOT* copied from the original request
		
		Assert.assertEquals(req.getPrimaryLocation(), loc);
		Assert.assertEquals(amendmentReq.getPrimaryLocation(), loc2);
		Assert.assertEquals(amendmentReq2.getPrimaryLocation(), loc2);

	}
	
	@Test
	public void testSeventeen() throws Exception {

		Person pers = Person.findById(1006);
		ResearchStudy activity = ResearchStudy.findById(1);

		Assert.assertNotNull(pers);
		Assert.assertNotNull(pers.getName());
		Assert.assertTrue(pers.getName().length() > 0);
		
		// create request 1 so we'll have something to work with
		DartRequest req = DartRequest.create("test request 1", new Date(), new Date(), pers, activity, "DNS");
		req.setWorkflowTypeId(WorkflowResolver.WF_RESEARCH_REQUEST);

		Assert.assertNotNull(req);
		Assert.assertTrue(req.getId() > 0);
		Assert.assertEquals(req.getActivity(), activity);
		Assert.assertFalse(req.isAmendment());
		Assert.assertEquals(req.getHeadId(), 0);

		Location loc = Location.findById(1);
		Assert.assertNotNull(loc);
		Assert.assertEquals(loc.getId(), 1);
		
		// request needs a primary investigator
		Participant part = Participant.create(pers, req, pers.getLocation(), true, true, true);
		Assert.assertNotNull(part);
		Assert.assertTrue(part.getId() > 0);

		Assert.assertNotNull(req.getParticipants());
		Assert.assertEquals(req.getParticipants().size(), 1);
		
		DartRequest amendment = DartRequest.findMostRecentAmendment(req.getId());
		Assert.assertNull(amendment);
		
		req.approve(null, pers.getName());

		// create an amendment
		DartRequest amendmentReq = req.createAmendment("DNS");

		DartRequest req2 = DartRequest.findMostRecentAmendment(req.getId());
		Assert.assertNotNull(req2);

		Assert.assertNotEquals(req2, req);
		Assert.assertEquals(req2, amendmentReq);
		Assert.assertTrue(req2.isAmendment());

		// amendment gets a copy of original request participants
		Assert.assertNotNull(amendmentReq.getParticipants());
		Assert.assertEquals(amendmentReq.getParticipants().size(), 1);
		Participant tstPart = amendmentReq.getParticipants().iterator().next();
		Assert.assertNotNull(tstPart);
		Assert.assertEquals(tstPart.getPerson(), pers);
		
		// request needs a primary investigator
		Person pers2 = Person.findById(1004);
		Assert.assertNotNull(pers2);
		Assert.assertTrue(pers2.getId() > 0);
		
		Participant part2 = Participant.create(pers2, req, pers2.getLocation(), true, true, true);
		Assert.assertNotNull(part2);
		Assert.assertTrue(part2.getId() > 0);

		amendmentReq.getParticipants().clear();
		amendmentReq.getParticipants().add(part2);

		amendmentReq.approve(null, pers.getName());

		// create an amendment of the amendment
		DartRequest amendmentReq2 = amendmentReq.createAmendment("DNS");

		DartRequest req3 = DartRequest.findMostRecentAmendment(req.getId());
		Assert.assertNotNull(req3);

		Assert.assertNotEquals(req3, req);
		Assert.assertEquals(req3, amendmentReq2);
		Assert.assertTrue(req3.isAmendment());

		// principal investigator in the amendment of an amendment

		Assert.assertNotNull(req3.getParticipants());
		Assert.assertEquals(req3.getParticipants().size(), 1);
		Participant tstPart2 = req3.getParticipants().iterator().next();
		Assert.assertNotNull(tstPart2);
		Assert.assertNotEquals(tstPart2.getPerson(), pers);
		Assert.assertEquals(tstPart2.getPerson(), pers2);
	}

}
