package gov.va.vinci.dart;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.stub;
import gov.va.vinci.dart.biz.Request;
import gov.va.vinci.dart.common.SingletonShim;
import gov.va.vinci.dart.common.json.ErrorView;
import gov.va.vinci.dart.common.test.BusinessIntegrationTest;
import gov.va.vinci.dart.json.CreateActivityView;
import gov.va.vinci.dart.json.DataSourceIdView;
import gov.va.vinci.dart.json.DataSourceListView;
import gov.va.vinci.dart.json.DataSourceView;
import gov.va.vinci.dart.json.DocumentTemplateListView;
import gov.va.vinci.dart.json.DocumentTemplateView;
import gov.va.vinci.dart.json.NewActivityView;
import gov.va.vinci.dart.json.RequestDataSourcesView;
import gov.va.vinci.dart.json.RequestIdView;
import gov.va.vinci.dart.json.SaveRequestDataSourcesView;
import gov.va.vinci.dart.service.DartObjectFactory;
import gov.va.vinci.dart.usr.CustomAuthentication;

import javax.servlet.http.HttpServletRequest;

import org.springframework.security.core.context.SecurityContextHolder;
import org.testng.Assert;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

public class TestDataSourceController extends BusinessIntegrationTest {

	@BeforeTest
	public void setup() {
		SingletonShim.getBean(DartObjectFactory.class);
		
		CustomAuthentication token = new CustomAuthentication("DNS", null, "password", "details", "principal");

		try {
			DartObjectFactory.getInstance().getUserManager().login(token);
			SecurityContextHolder.getContext().setAuthentication(token);
		} 
		catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	@Test
	public void testOne() throws Exception {

		DataSourceController dsc = SingletonShim.getBean(DataSourceController.class);

		Object obj = dsc.getAllDataSources(null);  // you can actually pass a null to this handler method
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof DataSourceListView);
		DataSourceListView dslv = (DataSourceListView)obj;
		Assert.assertNotNull(dslv.getDataSources());
		Assert.assertTrue(dslv.getDataSources().size() > 0);
		
		HttpServletRequest request = mock(HttpServletRequest.class);
		Assert.assertNotNull(request);
		
		stub(request.getRequestURL()).toReturn(new StringBuffer("https://localhost:PORT/vinci_dart_client/dart/setup.json"));
		
		obj = dsc.getAllDataSources(request);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof DataSourceListView);
		dslv = (DataSourceListView)obj;
		Assert.assertNotNull(dslv.getDataSources());
		Assert.assertTrue(dslv.getDataSources().size() > 0);
		
		for (DataSourceView dsv : dslv.getDataSources()) {
			Assert.assertTrue(dsv.getId() > 0);
			Assert.assertNotNull(dsv.getName());
			Assert.assertNotNull(dsv.getDomainName());
			Assert.assertNotNull(dsv.getDescription());
		}
	}

	@Test
	public void testTwo() throws Exception {

		DataSourceController dsc = SingletonShim.getBean(DataSourceController.class);

		Object obj = dsc.getDataSourceInfo(null);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof ErrorView);
		 
		HttpServletRequest request = mock(HttpServletRequest.class);
		Assert.assertNotNull(request);
		
		stub(request.getRequestURL()).toReturn(new StringBuffer("https://localhost:PORT/vinci_dart_client/dart/setup.json"));
		
		obj = dsc.getAllDataSources(request);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof DataSourceListView);
		DataSourceListView dslv = (DataSourceListView)obj;
		Assert.assertNotNull(dslv.getDataSources());
		Assert.assertTrue(dslv.getDataSources().size() > 0);
		
		for (DataSourceView dsv : dslv.getDataSources()) {
			
			DataSourceIdView dsiv = new DataSourceIdView();
			dsiv.setId(dsv.getId());
			obj = dsc.getDataSourceInfo(dsiv);

			Assert.assertNotNull(obj);
			Assert.assertTrue(obj instanceof DataSourceView);
			DataSourceView dsv2 = (DataSourceView)obj;
			
			Assert.assertEquals(dsv.getId(), dsv2.getId());
			Assert.assertEquals(dsv.getName(), dsv2.getName());
			Assert.assertEquals(dsv.getDomainName(), dsv2.getDomainName());
			Assert.assertEquals(dsv.getDescription(), dsv2.getDescription());
		}
	}

	@Test
	public void testThree() throws Exception {

		DataSourceController dsc = SingletonShim.getBean(DataSourceController.class);

		Object obj = dsc.listDocumentTemplatesByDataSource(null);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof ErrorView);
		 
		HttpServletRequest request = mock(HttpServletRequest.class);
		Assert.assertNotNull(request);
		
		stub(request.getRequestURL()).toReturn(new StringBuffer("https://localhost:PORT/vinci_dart_client/dart/setup.json"));
		
		obj = dsc.getAllDataSources(request);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof DataSourceListView);
		DataSourceListView dslv = (DataSourceListView)obj;
		Assert.assertNotNull(dslv.getDataSources());
		Assert.assertTrue(dslv.getDataSources().size() > 0);
		
		for (DataSourceView dsv : dslv.getDataSources()) {
			
			DataSourceIdView dsiv = new DataSourceIdView();
			dsiv.setId(dsv.getId());
			obj = dsc.listDocumentTemplatesByDataSource(dsiv);

			Assert.assertNotNull(obj);
			Assert.assertTrue(obj instanceof DocumentTemplateListView);
			DocumentTemplateListView dtlv = (DocumentTemplateListView)obj;
			Assert.assertNotNull(dtlv.getTemplates());
//			Assert.assertTrue(dtlv.getTemplates().size() > 0);  // we may have a mock data source without templates
			
			if (dtlv.getTemplates().size() > 0) {
				for (DocumentTemplateView dtv : dtlv.getTemplates()) {
					Assert.assertNotNull(dtv);
					Assert.assertTrue(dtv.getId() > 0);
					Assert.assertNotNull(dtv.getName());
					Assert.assertNotNull(dtv.getDescription());
					Assert.assertNotNull(dtv.getActivityType());
					Assert.assertTrue(dtv.getSortOrder() > 0);
				}
			}
		}
	}

	@Test
	public void testFour() throws Exception {

		CreateActivityView req = new CreateActivityView ();
		
		ActivityController ac = SingletonShim.getBean(ActivityController.class);
		req.setType(Request.DATA_ACCESS);
		req.setOfficialName("official name");
		
		// now see if we can create it correctly
		Object obj = ac.createActivity(req);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof NewActivityView);
		
		NewActivityView nav = (NewActivityView)obj;
		Assert.assertTrue(nav.getActivityId() > 0);
		Assert.assertTrue(nav.getRequestId() > 0);
		
		// now we have a request to work with
		
		DataSourceController dsc = SingletonShim.getBean(DataSourceController.class);

		obj = dsc.getRequestDataSources(null);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof ErrorView);
		
		RequestIdView riv = new RequestIdView();
		riv.setRequestId(nav.getRequestId());
		riv.setUserId(1006);
		
		// does that request have any associated data sources?  (it should not)
		obj = dsc.getRequestDataSources(riv);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof RequestDataSourcesView);
		
		SaveRequestDataSourcesView rdsv = new SaveRequestDataSourcesView();
		rdsv.setUserId(((RequestDataSourcesView)obj).getUserId());
		rdsv.setRequestId(((RequestDataSourcesView)obj).getRequestId());
		rdsv.setLocationName(((RequestDataSourcesView)obj).getLocationName());		
		rdsv.setStartDate(((RequestDataSourcesView)obj).getStartDate());
		rdsv.setEndDate(((RequestDataSourcesView)obj).getEndDate());
		rdsv.setDataMart(((RequestDataSourcesView)obj).isDataMart());
		rdsv.setLocalServer(((RequestDataSourcesView)obj).isLocalServer());
		rdsv.setHipaaAuth(((RequestDataSourcesView)obj).isHipaaAuth());
		rdsv.setHipaaWaiver(((RequestDataSourcesView)obj).isHipaaWaiver());
		rdsv.setLocalServerLocation(((RequestDataSourcesView)obj).getLocalServerLocation());
		rdsv.setLocalServerAddress(((RequestDataSourcesView)obj).getLocalServerAddress());
		rdsv.setLocalServerBuilding(((RequestDataSourcesView)obj).getLocalServerBuilding());
		rdsv.setLocalServerRoomNumber(((RequestDataSourcesView)obj).getLocalServerRoomNumber());
		rdsv.setTransferredExternal(((RequestDataSourcesView)obj).isTransferredExternal());
		rdsv.setExternalDestination(((RequestDataSourcesView)obj).getExternalDestination());
		rdsv.setExternalStreet(((RequestDataSourcesView)obj).getExternalStreet());
		rdsv.setExternalCity(((RequestDataSourcesView)obj).getExternalCity());
		rdsv.setExternalState(((RequestDataSourcesView)obj).getExternalState());
		rdsv.setExternalZipCode(((RequestDataSourcesView)obj).getExternalZipCode());
		rdsv.getDataSources().addAll(((RequestDataSourcesView)obj).getDataSources());		
		rdsv.setRealSSNIdentifier(((RequestDataSourcesView)obj).isRealSSNIdentifier());
		rdsv.setScrambledSSNIdentifier(((RequestDataSourcesView)obj).isScrambledSSNIdentifier());
		rdsv.setPhiDataIdentifier(((RequestDataSourcesView)obj).isPhiDataIdentifier());
		
		Assert.assertEquals(rdsv.getRequestId(), nav.getRequestId());
		Assert.assertNotNull(rdsv.getDataSources());
		Assert.assertEquals(rdsv.getDataSources().size(), 0);
		
		// add data source
		rdsv.getDataSources().add(1);
		rdsv.getDataSources().add(2);
		rdsv.getDataSources().add(3);

		obj = dsc.saveRequestDataSources(rdsv);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof ErrorView);
		Assert.assertEquals(((ErrorView)obj).getMessage().get("text"), "OK");

		// were those data sources saved?
		obj = dsc.getRequestDataSources(riv);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof RequestDataSourcesView);

		RequestDataSourcesView rdsvObj = (RequestDataSourcesView)obj;
		Assert.assertEquals(rdsvObj.getRequestId(), nav.getRequestId());
		Assert.assertNotNull(rdsvObj.getDataSources());
		Assert.assertEquals(rdsvObj.getDataSources().size(), 3);

		// can I take a data source out again?
		rdsvObj.getDataSources().clear();
		rdsvObj.getDataSources().add(1);
		rdsvObj.getDataSources().add(3);

		rdsv = new SaveRequestDataSourcesView();
		rdsv.setUserId(((RequestDataSourcesView)rdsvObj).getUserId());
		rdsv.setRequestId(((RequestDataSourcesView)rdsvObj).getRequestId());
		rdsv.setLocationName(((RequestDataSourcesView)rdsvObj).getLocationName());		
		rdsv.setStartDate(((RequestDataSourcesView)rdsvObj).getStartDate());
		rdsv.setEndDate(((RequestDataSourcesView)rdsvObj).getEndDate());
		rdsv.setDataMart(((RequestDataSourcesView)rdsvObj).isDataMart());
		rdsv.setLocalServer(((RequestDataSourcesView)rdsvObj).isLocalServer());
		rdsv.setHipaaAuth(((RequestDataSourcesView)rdsvObj).isHipaaAuth());
		rdsv.setHipaaWaiver(((RequestDataSourcesView)rdsvObj).isHipaaWaiver());
		rdsv.setLocalServerLocation(((RequestDataSourcesView)rdsvObj).getLocalServerLocation());
		rdsv.setLocalServerAddress(((RequestDataSourcesView)rdsvObj).getLocalServerAddress());
		rdsv.setLocalServerBuilding(((RequestDataSourcesView)rdsvObj).getLocalServerBuilding());
		rdsv.setLocalServerRoomNumber(((RequestDataSourcesView)rdsvObj).getLocalServerRoomNumber());
		rdsv.setTransferredExternal(((RequestDataSourcesView)rdsvObj).isTransferredExternal());
		rdsv.setExternalDestination(((RequestDataSourcesView)rdsvObj).getExternalDestination());
		rdsv.setExternalStreet(((RequestDataSourcesView)rdsvObj).getExternalStreet());
		rdsv.setExternalCity(((RequestDataSourcesView)rdsvObj).getExternalCity());
		rdsv.setExternalState(((RequestDataSourcesView)rdsvObj).getExternalState());
		rdsv.setExternalZipCode(((RequestDataSourcesView)rdsvObj).getExternalZipCode());
		rdsv.getDataSources().addAll(((RequestDataSourcesView)rdsvObj).getDataSources());		
		rdsv.setRealSSNIdentifier(((RequestDataSourcesView)rdsvObj).isRealSSNIdentifier());
		rdsv.setScrambledSSNIdentifier(((RequestDataSourcesView)rdsvObj).isScrambledSSNIdentifier());
		rdsv.setPhiDataIdentifier(((RequestDataSourcesView)rdsvObj).isPhiDataIdentifier());
		
		obj = dsc.saveRequestDataSources(rdsv);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof ErrorView);
		Assert.assertEquals(((ErrorView)obj).getMessage().get("text"), "OK");

		// were those data sources saved?
		obj = dsc.getRequestDataSources(riv);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof RequestDataSourcesView);

		rdsvObj = (RequestDataSourcesView)obj;
		Assert.assertEquals(rdsvObj.getRequestId(), nav.getRequestId());
		Assert.assertNotNull(rdsvObj.getDataSources());
		Assert.assertEquals(rdsvObj.getDataSources().size(), 2);

	}
}
