package gov.va.vinci.dart.dms.db;

import gov.va.vinci.dart.biz.DartRequest;
import gov.va.vinci.dart.biz.DocumentTemplate;
import gov.va.vinci.dart.biz.Group;
import gov.va.vinci.dart.biz.Location;
import gov.va.vinci.dart.biz.Participant;
import gov.va.vinci.dart.biz.Person;
import gov.va.vinci.dart.biz.RequestAdminLocationDocument;
import gov.va.vinci.dart.biz.RequestAdminParticipantDocument;
import gov.va.vinci.dart.biz.RequestLocationDocument;
import gov.va.vinci.dart.biz.RequestParticipantDocument;
import gov.va.vinci.dart.common.SingletonShim;
import gov.va.vinci.dart.common.test.BusinessIntegrationTest;
import gov.va.vinci.dart.dms.biz.Content;
import gov.va.vinci.dart.dms.biz.Document;
import gov.va.vinci.dart.service.DartObjectFactory;

import java.util.List;

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

public class TestDocumentDAO extends BusinessIntegrationTest {

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

	@Test
	public void testOne() throws Exception {
		DartObjectFactory.getInstance().getResearchStudyDAO().listAll();

		List<DartRequest> reqList = DartObjectFactory.getInstance().getDartRequestDAO().listAll();
		Assert.assertNotNull(reqList);
		Assert.assertTrue(reqList.size() > 0);

		DartRequest req = reqList.get(0);
		Assert.assertNotNull(req);
		Assert.assertTrue(req.getId() > 0);
	
		List<DocumentTemplate> dtList = DartObjectFactory.getInstance().getDocumentTemplateDAO().listAll();
		Assert.assertNotNull(dtList);
		Assert.assertTrue(dtList.size() > 0);

		DocumentTemplate dt = dtList.get(0);
		Assert.assertNotNull(dt);

		Document doc = Document.create(req, dt, "DNS");
		Assert.assertNotNull(doc);
		Assert.assertTrue(doc.getId() > 0);

		Document doc2 = DartObjectFactory.getInstance().getDocumentDAO().findById(doc.getId());
		Assert.assertNotNull(doc2);
		Assert.assertTrue(doc2.getId() > 0);
		Assert.assertEquals(doc2, doc);

		DartObjectFactory.getInstance().getDocumentDAO().delete(doc);

		Document doc3 = DartObjectFactory.getInstance().getDocumentDAO().findById(doc.getId());
		Assert.assertNull(doc3);
	}

	@Test
	public void testTwo() throws Exception {
		DartObjectFactory.getInstance().getResearchStudyDAO().listAll();
		
		List<DartRequest> reqList = DartObjectFactory.getInstance().getDartRequestDAO().listAll();
		Assert.assertNotNull(reqList);
		Assert.assertTrue(reqList.size() > 0);

		DartRequest req = reqList.get(0);
		Assert.assertNotNull(req);
		Assert.assertTrue(req.getId() > 0);
	
		List<DocumentTemplate> dtList = DartObjectFactory.getInstance().getDocumentTemplateDAO().listAll();
		Assert.assertNotNull(dtList);
		Assert.assertTrue(dtList.size() > 0);

		DocumentTemplate dt = dtList.get(0);
		Assert.assertNotNull(dt);

		Document doc = Document.create(req, dt, "DNS");
		Assert.assertNotNull(doc);
		Assert.assertTrue(doc.getId() > 0);
		Assert.assertEquals(doc.getVersionNumber(), 1);

		Document dTest = DartObjectFactory.getInstance().getDocumentDAO().findCurrentVersion(doc.getId());
		Assert.assertNotNull(dTest);
		Assert.assertEquals(dTest, doc);

		dTest = DartObjectFactory.getInstance().getDocumentDAO().findMostRecentVersion(doc.getId());
		Assert.assertNotNull(dTest);
		Assert.assertEquals(dTest, doc);

		// sleep for 2 seconds so the timestamps on the documents will be distinct
		Thread.sleep(2000);
		
		Document doc2 = doc.createNewVersion("DNS");
		Assert.assertNotNull(doc2);
		Assert.assertTrue(doc2.getId() > 0);
		Assert.assertEquals(doc2.getHead(), doc.getId());
		Assert.assertEquals(doc2.getVersionNumber(), 2);

		dTest = DartObjectFactory.getInstance().getDocumentDAO().findCurrentVersion(doc.getId());
		Assert.assertNotNull(dTest);
		Assert.assertEquals(dTest, doc2);

		dTest = DartObjectFactory.getInstance().getDocumentDAO().findMostRecentVersion(doc.getId());
		Assert.assertNotNull(dTest);
		Assert.assertEquals(dTest, doc2);

		// sleep for 2 seconds so the timestamps on the documents will be distinct
		Thread.sleep(2000);

		Document doc3 = doc2.createNewVersion("DNS");
		Assert.assertNotNull(doc3);
		Assert.assertTrue(doc3.getId() > 0);
		Assert.assertEquals(doc3.getHead(), doc.getId());
		Assert.assertEquals(doc3.getVersionNumber(), 3);

		dTest = DartObjectFactory.getInstance().getDocumentDAO().findCurrentVersion(doc.getId());
		Assert.assertNotNull(dTest);
		Assert.assertEquals(dTest, doc3);

		dTest = DartObjectFactory.getInstance().getDocumentDAO().findMostRecentVersion(doc.getId());
		Assert.assertNotNull(dTest);
		Assert.assertEquals(dTest, doc3);

		List<Document> dList = DartObjectFactory.getInstance().getDocumentDAO().listVersionsById(doc.getId());
		Assert.assertNotNull(dList);
		Assert.assertTrue(dList.size() > 0);
		Assert.assertTrue(dList.contains(doc));
		Assert.assertTrue(dList.contains(doc2));
		Assert.assertTrue(dList.contains(doc3));
		
		// it doesn't matter which doc in the version chain you pass, this method will always return the current.
		dTest = DartObjectFactory.getInstance().getDocumentDAO().findCurrentVersion(doc.getId());
		Assert.assertNotNull(dTest);
		Assert.assertEquals(dTest, doc3);

		dTest = DartObjectFactory.getInstance().getDocumentDAO().findCurrentVersion(doc2.getId());
		Assert.assertNotNull(dTest);
		Assert.assertEquals(dTest, doc3);

		dTest = DartObjectFactory.getInstance().getDocumentDAO().findCurrentVersion(doc3.getId());
		Assert.assertNotNull(dTest);
		Assert.assertEquals(dTest, doc3);

	}

	@Test
	public void testThree() throws Exception {
		DartObjectFactory.getInstance().getResearchStudyDAO().listAll();

		List<DartRequest> reqList = DartObjectFactory.getInstance().getDartRequestDAO().listAll();
		Assert.assertNotNull(reqList);
		Assert.assertTrue(reqList.size() > 0);

		DartRequest req = reqList.get(0);
		Assert.assertNotNull(req);
		Assert.assertTrue(req.getId() > 0);
	
		List<DocumentTemplate> dtList = DartObjectFactory.getInstance().getDocumentTemplateDAO().listAll();
		Assert.assertNotNull(dtList);
		Assert.assertTrue(dtList.size() > 0);

		DocumentTemplate dt = dtList.get(0);
		Assert.assertNotNull(dt);

		Document doc = Document.create(req, dt, "DNS");
		Assert.assertNotNull(doc);
		Assert.assertTrue(doc.getId() > 0);
		Assert.assertEquals(doc.getVersionNumber(), 1);

		Content content = Content.create("pdf", 1);
		Assert.assertNotNull(content);
		Assert.assertTrue(content.getId() > 0);
		
		doc.setContent(content);
		
		List<Document> dList = DartObjectFactory.getInstance().getDocumentDAO().listByContentId(content.getId());
		Assert.assertNotNull(dList);
		Assert.assertTrue(dList.size() > 0);
		Assert.assertTrue(dList.contains(doc));
	}

	@Test
	public void testFour() throws Exception {
		DartObjectFactory.getInstance().getResearchStudyDAO().listAll();

		List<DartRequest> reqList = DartObjectFactory.getInstance().getDartRequestDAO().listAll();
		Assert.assertNotNull(reqList);
		Assert.assertTrue(reqList.size() > 0);

		DartRequest req = reqList.get(0);
		Assert.assertNotNull(req);
		Assert.assertTrue(req.getId() > 0);
	
		List<DocumentTemplate> dtList = DartObjectFactory.getInstance().getDocumentTemplateDAO().listAll();
		Assert.assertNotNull(dtList);
		Assert.assertTrue(dtList.size() > 0);

		DocumentTemplate dt = dtList.get(0);
		Assert.assertNotNull(dt);

		Person pers = DartObjectFactory.getInstance().getPersonDAO().findById(1006);
		Assert.assertNotNull(pers);
		Assert.assertTrue(pers.getId() > 0);
		Assert.assertNotNull(pers.getGroups());
		Assert.assertTrue(pers.getGroups().size() > 0);
		
		Group grp = pers.getGroups().iterator().next();
		Assert.assertNotNull(grp);
		Assert.assertTrue(grp.getId() > 0);
		
		Location loc = pers.getLocation();
		Assert.assertNotNull(loc);
		Assert.assertTrue(loc.getId() > 0);
		
		Document doc = Document.create(req, dt, "DNS");
		Assert.assertNotNull(doc);
		Assert.assertTrue(doc.getId() > 0);
		Assert.assertEquals(doc.getVersionNumber(), 1);

		// now the request needs an admin location document
		RequestAdminLocationDocument rald = RequestAdminLocationDocument.create(req, loc, doc, grp); 
		Assert.assertNotNull(rald);
		Assert.assertTrue(rald.getId() > 0);
		
		String locName = DartObjectFactory.getInstance().getDocumentDAO().findLocationByDocId(doc.getId());
		Assert.assertNotNull(locName);
		Assert.assertEquals(locName, loc.getName());
	}

	@Test
	public void testFive() throws Exception {
		DartObjectFactory.getInstance().getResearchStudyDAO().listAll();

		List<DartRequest> reqList = DartObjectFactory.getInstance().getDartRequestDAO().listAll();
		Assert.assertNotNull(reqList);
		Assert.assertTrue(reqList.size() > 0);

		DartRequest req = reqList.get(0);
		Assert.assertNotNull(req);
		Assert.assertTrue(req.getId() > 0);
	
		List<DocumentTemplate> dtList = DartObjectFactory.getInstance().getDocumentTemplateDAO().listAll();
		Assert.assertNotNull(dtList);
		Assert.assertTrue(dtList.size() > 0);

		DocumentTemplate dt = dtList.get(0);
		Assert.assertNotNull(dt);

		Person pers = DartObjectFactory.getInstance().getPersonDAO().findById(1006);
		Assert.assertNotNull(pers);
		Assert.assertTrue(pers.getId() > 0);
		Assert.assertNotNull(pers.getGroups());
		Assert.assertTrue(pers.getGroups().size() > 0);
		
		Group grp = pers.getGroups().iterator().next();
		Assert.assertNotNull(grp);
		Assert.assertTrue(grp.getId() > 0);
		
		Location loc = pers.getLocation();
		Assert.assertNotNull(loc);
		Assert.assertTrue(loc.getId() > 0);
		
		Document doc = Document.create(req, dt, "DNS");
		Assert.assertNotNull(doc);
		Assert.assertTrue(doc.getId() > 0);
		Assert.assertEquals(doc.getVersionNumber(), 1);

		Participant part = Participant.create(pers, req, loc, true, true, true);
		Assert.assertNotNull(part);
		Assert.assertTrue(part.getId() > 0);
		
		// now the request needs an admin participant document
		RequestAdminParticipantDocument rapd = RequestAdminParticipantDocument.create(req, part, doc, grp); 
		Assert.assertNotNull(rapd);
		Assert.assertTrue(rapd.getId() > 0);
		
		String locName = DartObjectFactory.getInstance().getDocumentDAO().findLocationByDocId(doc.getId());
		Assert.assertNotNull(locName);
		Assert.assertEquals(locName, loc.getName());
	}

	@Test
	public void testSix() throws Exception {
		DartObjectFactory.getInstance().getResearchStudyDAO().listAll();

		List<DartRequest> reqList = DartObjectFactory.getInstance().getDartRequestDAO().listAll();
		Assert.assertNotNull(reqList);
		Assert.assertTrue(reqList.size() > 0);

		DartRequest req = reqList.get(0);
		Assert.assertNotNull(req);
		Assert.assertTrue(req.getId() > 0);
	
		List<DocumentTemplate> dtList = DartObjectFactory.getInstance().getDocumentTemplateDAO().listAll();
		Assert.assertNotNull(dtList);
		Assert.assertTrue(dtList.size() > 0);

		DocumentTemplate dt = dtList.get(0);
		Assert.assertNotNull(dt);

		Person pers = DartObjectFactory.getInstance().getPersonDAO().findById(1006);
		Assert.assertNotNull(pers);
		Assert.assertTrue(pers.getId() > 0);
		Assert.assertNotNull(pers.getGroups());
		Assert.assertTrue(pers.getGroups().size() > 0);
		
		Group grp = pers.getGroups().iterator().next();
		Assert.assertNotNull(grp);
		Assert.assertTrue(grp.getId() > 0);
		
		Location loc = pers.getLocation();
		Assert.assertNotNull(loc);
		Assert.assertTrue(loc.getId() > 0);
		
		Document doc = Document.create(req, dt, "DNS");
		Assert.assertNotNull(doc);
		Assert.assertTrue(doc.getId() > 0);
		Assert.assertEquals(doc.getVersionNumber(), 1);

		// now the request needs an admin location document
		RequestLocationDocument rald = RequestLocationDocument.create(req, loc, doc); 
		Assert.assertNotNull(rald);
		Assert.assertTrue(rald.getId() > 0);
		
		String locName = DartObjectFactory.getInstance().getDocumentDAO().findLocationByDocId(doc.getId());
		Assert.assertNotNull(locName);
		Assert.assertEquals(locName, loc.getName());
	}

	@Test
	public void testSeven() throws Exception {
		DartObjectFactory.getInstance().getResearchStudyDAO().listAll();

		List<DartRequest> reqList = DartObjectFactory.getInstance().getDartRequestDAO().listAll();
		Assert.assertNotNull(reqList);
		Assert.assertTrue(reqList.size() > 0);

		DartRequest req = reqList.get(0);
		Assert.assertNotNull(req);
		Assert.assertTrue(req.getId() > 0);
	
		List<DocumentTemplate> dtList = DartObjectFactory.getInstance().getDocumentTemplateDAO().listAll();
		Assert.assertNotNull(dtList);
		Assert.assertTrue(dtList.size() > 0);

		DocumentTemplate dt = dtList.get(0);
		Assert.assertNotNull(dt);

		Person pers = DartObjectFactory.getInstance().getPersonDAO().findById(1006);
		Assert.assertNotNull(pers);
		Assert.assertTrue(pers.getId() > 0);
		Assert.assertNotNull(pers.getGroups());
		Assert.assertTrue(pers.getGroups().size() > 0);
		
		Group grp = pers.getGroups().iterator().next();
		Assert.assertNotNull(grp);
		Assert.assertTrue(grp.getId() > 0);
		
		Location loc = pers.getLocation();
		Assert.assertNotNull(loc);
		Assert.assertTrue(loc.getId() > 0);
		
		Document doc = Document.create(req, dt, "DNS");
		Assert.assertNotNull(doc);
		Assert.assertTrue(doc.getId() > 0);
		Assert.assertEquals(doc.getVersionNumber(), 1);

		Participant part = Participant.create(pers, req, loc, true, true, true);
		Assert.assertNotNull(part);
		Assert.assertTrue(part.getId() > 0);
		
		// now the request needs an admin participant document
		RequestParticipantDocument rapd = RequestParticipantDocument.create(req, part, doc); 
		Assert.assertNotNull(rapd);
		Assert.assertTrue(rapd.getId() > 0);
		
		String locName = DartObjectFactory.getInstance().getDocumentDAO().findLocationByDocId(doc.getId());
		Assert.assertNotNull(locName);
		Assert.assertEquals(locName, loc.getName());
	}

	@Test
	public void testEight() throws Exception {
		DartObjectFactory.getInstance().getResearchStudyDAO().listAll();

		List<DartRequest> reqList = DartObjectFactory.getInstance().getDartRequestDAO().listAll();
		Assert.assertNotNull(reqList);
		Assert.assertTrue(reqList.size() > 0);

		DartRequest req = reqList.get(0);
		Assert.assertNotNull(req);
		Assert.assertTrue(req.getId() > 0);
	
		List<DocumentTemplate> dtList = DartObjectFactory.getInstance().getDocumentTemplateDAO().listAll();
		Assert.assertNotNull(dtList);
		Assert.assertTrue(dtList.size() > 0);

		DocumentTemplate dt = dtList.get(0);
		Assert.assertNotNull(dt);

		Person pers = DartObjectFactory.getInstance().getPersonDAO().findById(1006);
		Assert.assertNotNull(pers);
		Assert.assertTrue(pers.getId() > 0);
		Assert.assertNotNull(pers.getGroups());
		Assert.assertTrue(pers.getGroups().size() > 0);
		
		Group grp = pers.getGroups().iterator().next();
		Assert.assertNotNull(grp);
		Assert.assertTrue(grp.getId() > 0);
		
		Location loc = pers.getLocation();
		Assert.assertNotNull(loc);
		Assert.assertTrue(loc.getId() > 0);
		
		Document doc = Document.create(req, dt, "DNS");
		Assert.assertNotNull(doc);
		Assert.assertTrue(doc.getId() > 0);
		Assert.assertEquals(doc.getVersionNumber(), 1);

		Participant part = Participant.create(pers, req, loc, true, true, true);
		Assert.assertNotNull(part);
		Assert.assertTrue(part.getId() > 0);
		
		// now the request needs an admin participant document
		RequestAdminParticipantDocument rapd = RequestAdminParticipantDocument.create(req, part, doc, grp); 
		Assert.assertNotNull(rapd);
		Assert.assertTrue(rapd.getId() > 0);
		
		String partName = DartObjectFactory.getInstance().getDocumentDAO().findParticipantNameByDocId(doc.getId());
		Assert.assertNotNull(partName);
		Assert.assertEquals(partName, pers.getFullName());
	}

	@Test
	public void testNine() throws Exception {
		DartObjectFactory.getInstance().getResearchStudyDAO().listAll();

		List<DartRequest> reqList = DartObjectFactory.getInstance().getDartRequestDAO().listAll();
		Assert.assertNotNull(reqList);
		Assert.assertTrue(reqList.size() > 0);

		DartRequest req = reqList.get(0);
		Assert.assertNotNull(req);
		Assert.assertTrue(req.getId() > 0);
	
		List<DocumentTemplate> dtList = DartObjectFactory.getInstance().getDocumentTemplateDAO().listAll();
		Assert.assertNotNull(dtList);
		Assert.assertTrue(dtList.size() > 0);

		DocumentTemplate dt = dtList.get(0);
		Assert.assertNotNull(dt);

		Person pers = DartObjectFactory.getInstance().getPersonDAO().findById(1006);
		Assert.assertNotNull(pers);
		Assert.assertTrue(pers.getId() > 0);
		Assert.assertNotNull(pers.getGroups());
		Assert.assertTrue(pers.getGroups().size() > 0);
		
		Group grp = pers.getGroups().iterator().next();
		Assert.assertNotNull(grp);
		Assert.assertTrue(grp.getId() > 0);
		
		Location loc = pers.getLocation();
		Assert.assertNotNull(loc);
		Assert.assertTrue(loc.getId() > 0);
		
		Document doc = Document.create(req, dt, "DNS");
		Assert.assertNotNull(doc);
		Assert.assertTrue(doc.getId() > 0);
		Assert.assertEquals(doc.getVersionNumber(), 1);

		Participant part = Participant.create(pers, req, loc, true, true, true);
		Assert.assertNotNull(part);
		Assert.assertTrue(part.getId() > 0);
		
		// now the request needs an admin participant document
		RequestParticipantDocument rapd = RequestParticipantDocument.create(req, part, doc); 
		Assert.assertNotNull(rapd);
		Assert.assertTrue(rapd.getId() > 0);
		
		String partName = DartObjectFactory.getInstance().getDocumentDAO().findParticipantNameByDocId(doc.getId());
		Assert.assertNotNull(partName);
		Assert.assertEquals(partName, pers.getFullName());
	}
}
