

package gov.va.med.tfs.persistence;


import gov.va.med.tfs.tfdm.DomainEntryPoint;
import gov.va.med.cds.junit.runners.Suite;
import gov.va.med.cds.junit.runners.SuiteAwareSpringRunner;
import gov.va.med.tfs.tfdm.EntryFilter;
import gov.va.med.tfs.tfdm.FilterMetaData;

import org.junit.Assert;
import org.junit.Test;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import javax.annotation.Resource;

import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;


@RunWith( SuiteAwareSpringRunner.class )
@ContextConfiguration( locations = { "classpath:gov/va/med/tfs/config/tfrPersistenceContext.xml",
				"classpath:gov/va/med/tfs/config/tfrCrdFilterPersistenceContextTest.xml",
                "classpath:gov/va/med/tfs/config/nonWeblogicTfrDataSourceContext.xml" } )
public class CreateReadDeleteFilterMappingTest
{
    private static ReadPersistenceManagerInterface readManager;
    private static CreateFilterPersistenceManagerInterface createManager;
    private static DeletePersistenceManagerInterface deleteManager;

    private Set<String> VHIM_VERSION = new HashSet<String>(Arrays.asList("Vhim_4_00", "Vhim_5_00"));
    private String ID = "TEST_BOGUS_FILTER";
    private String DESCRIPTION = "description";
	private String ENTRY_POINT_ALLERGY_NAME = "AllergyAssessment";
	private String ENTRY_POINT_ALLERGY_DOMAIN = "ALLERGY";
	private String ENTRY_POINT_TIU_NAME = "ClinicalDocumentEvent";
	private String ENTRY_POINT_TIU_DOMAIN = "TIU";
	private String STATUS = "ACTIVE";
	private String FILE_STRING = "Schema";
	private boolean CORRELATION = true;
	
	private String SUCCESSFUL_FILTER_DELETE = "Sucessfully Deleted Filter - Thank You";
	private String FAILED_FILTER_DELETE = "Filter Not Found -- Filter Not Deleted";
	private String SUCCESSFUL_FILTER_CREATE = "Sucessfully Persisted Filter - Thank You";
	private String FAILED_FILTER_CREATE = "Record already exists -- Filter Not Persisted";
	

	@Test
    @Suite( groups = { "checkintest" } )
    public void testCreatePersistenceManagers( )
    {
		Assert.assertNotNull( readManager );
        Assert.assertNotNull( createManager );
        Assert.assertNotNull( deleteManager );
        System.out.println( "CreateReadDeleteFilterMappingTest -- PersistenceManagers Injected" );
    }
       

	/*
	 * This test will:
	 *  	- Persist a new template
	 *      - Read it and ensure it was mapped correctly
	 *      - Delete it                 
	 */
    @Test
    @Suite( groups = { "checkintest" } )
    public void filterCreateReadDeleteTest( )
        throws Exception    
    {
    	FilterMetaData persistFilterMetaData = new FilterMetaData();
    	FilterMetaData readFilterMetaData = null;
    	String tfrReturn = null;
    	
    	//Populate Filter
     	persistFilterMetaData = populateFilterMetaData();
    	
    	//Clean up database
     	System.out.println( "Clean up DB -- Regardless of status delete" );
     	tfrReturn = deleteManager.deleteFilterData( ID );
    	
    	//insert Filter works
    	System.out.println( "Insert Active Filter Works" );
    	tfrReturn = createManager.createFilterData( persistFilterMetaData );
    	Assert.assertEquals( tfrReturn, SUCCESSFUL_FILTER_CREATE );
    	
    	//insert second Filter fails
    	System.out.println( "Insert Second Filter Fails" );
    	tfrReturn = createManager.createFilterData( persistFilterMetaData );
    	Assert.assertEquals( tfrReturn, FAILED_FILTER_CREATE );
    	
    	//read Filter works (status 'ACTIVE')
    	System.out.println( "Read Active Filter Works" );
    	readFilterMetaData = readManager.readFilterData( ID );
    	Assert.assertNotNull( readFilterMetaData );
    	
    	//validate Filter DB contents
    	System.out.println( "Validate Persisted Data" );
    	validatePersistedData( readFilterMetaData, persistFilterMetaData );
    	
    	//delete Filter works
    	System.out.println( "Delete Filter Works" );
    	tfrReturn = deleteManager.deleteFilterData( ID );
    	Assert.assertEquals( tfrReturn, SUCCESSFUL_FILTER_DELETE );
    	
    	//second delete filter fails
    	System.out.println( "Second Delete Filter Fails" );
    	tfrReturn = deleteManager.deleteFilterData( ID );
    	Assert.assertEquals( tfrReturn, FAILED_FILTER_DELETE );
    	    	
    	//read deleted filter fails
     	System.out.println( "Read Deleted Filter Fails" );
    	readFilterMetaData = readManager.readFilterData( ID );
    	Assert.assertNull( readFilterMetaData );
    	
    	System.out.println( "CreateReadDeleteFilterMappingTest -- Test Completed" );
    }
    

    /*
     * This test will:
     *  	- Persist a new OLD template
     *      - Read it and ensure ensure its ignored
     *      - Delete it                 
     */
    @Test
    @Suite( groups = { "checkintest" } )
    public void filterStatusTest( )
        throws Exception    
    {
    	FilterMetaData persistFilterMetaData = new FilterMetaData();
    	FilterMetaData readFilterMetaData = null;
    	String tfrReturn = null;
    	
    	//Populate Filter
     	persistFilterMetaData = populateFilterMetaData();
    	
    	//Clean up database
     	System.out.println( "Clean up DB -- Regardless of status delete" );
     	tfrReturn = deleteManager.deleteFilterData( ID );
  	
		//Testing OLD status
    	persistFilterMetaData.setStatus("OLD");
    	
    	//insert Filter works
    	System.out.println( "Insert Filter Works" );
    	tfrReturn = createManager.createFilterData( persistFilterMetaData );
    	Assert.assertEquals( tfrReturn, SUCCESSFUL_FILTER_CREATE );
    	
    	//read Filter fails (ignore status 'OLD')
    	System.out.println( "Read OLD Filter Fails" );
    	readFilterMetaData = readManager.readFilterData( ID );
    	Assert.assertNull( readFilterMetaData );
    	
    	//Clean up database (ignore status 'OLD')
    	System.out.println( "Delete Filter Works" );
    	tfrReturn = deleteManager.deleteFilterData( ID );
    	Assert.assertEquals( tfrReturn, SUCCESSFUL_FILTER_DELETE ); 	
    	
    	System.out.println( "filterStatusTest -- Test Completed" );
    }
    

    private void validatePersistedData( FilterMetaData aReadFilterMetaData, FilterMetaData aPersistFilterMetaData )
	{
		validateVhimVersions ( aReadFilterMetaData.getVhimVersions(), aPersistFilterMetaData.getVhimVersions() );
		Assert.assertEquals( aReadFilterMetaData.getFilterId(), aPersistFilterMetaData.getFilterId() );
		Assert.assertEquals( aReadFilterMetaData.getFilterDescription(), aPersistFilterMetaData.getFilterDescription() );
		validateEntryPoints( aReadFilterMetaData.getEntryFilters(), aPersistFilterMetaData.getEntryFilters() );
		Assert.assertEquals( aReadFilterMetaData.getStatus(), aPersistFilterMetaData.getStatus() );
		Assert.assertEquals( aReadFilterMetaData.getFilterSchemaXml(), aPersistFilterMetaData.getFilterSchemaXml() );
		Assert.assertEquals( aReadFilterMetaData.isContainsCorrelation(), aPersistFilterMetaData.isContainsCorrelation() );
		validateDate( aReadFilterMetaData.getDateDeprecated(),  aPersistFilterMetaData.getDateDeprecated() );
		validateDate( aReadFilterMetaData.getDateActivated(), aPersistFilterMetaData.getDateActivated() );
		validateDate( aReadFilterMetaData.getDateDeactivated(), aPersistFilterMetaData.getDateDeactivated() );
		validateDate( aReadFilterMetaData.getDateUpdated(), aPersistFilterMetaData.getDateUpdated() );
	}
	

	//TODO check for assert date compare
	private void validateDate(Date aReadDate, Date aPersistDate) 
	{
        SimpleDateFormat format = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss.SSS" );
		String readDate = null;
		
        try
        {
			readDate = format.parse( aReadDate.toString() ).toString();
			Assert.assertEquals( readDate.trim(), aPersistDate.toString().trim() );
		} 
		catch (ParseException e) 
		{
			e.printStackTrace();
			Assert.assertNotNull( null );
		}
		
	}


    private void validateVhimVersions( Set<String> aReadVhimVersions, Set<String> aPersistVhimVersions )
	{
        int matchCount = 0;
		
        for ( String vhimVersion : aReadVhimVersions )
		{
            for ( String persistedVersion : aPersistVhimVersions )
            {
                if ( vhimVersion.equals( persistedVersion ) )
                {
                    matchCount++ ;
                }
            }
		}
		
        Assert.assertEquals( matchCount, aReadVhimVersions.size() );
	}


    private void validateEntryPoints( Set<EntryFilter> readEntryFilters, Set<EntryFilter> persistEntryFilters )
	{
		DomainEntryPoint persistDomainEntryPoint = null;
		String readName = null;
		String readDomain = null;
		Iterator<EntryFilter> readEntryFiltersIterator = readEntryFilters.iterator();
		EntryFilter readEntryFilter = null;
		DomainEntryPoint readDomainEntryPoint = null;
		
		for ( EntryFilter persistEntryFilter : persistEntryFilters )
		{
			persistDomainEntryPoint = persistEntryFilter.getDomainEntryPoint();
			readName = persistDomainEntryPoint.getName();
			readDomain = persistDomainEntryPoint.getDomain();
			
			readEntryFilter = readEntryFiltersIterator.next();
			readDomainEntryPoint = readEntryFilter.getDomainEntryPoint();
			Assert.assertEquals( readName, readDomainEntryPoint.getName() );
			Assert.assertEquals( readDomain, readDomainEntryPoint.getDomain() );
		}
		
	}
    

/*	//private Set<String> vhimVersions; DBT
    //private String filterId; DB
	//private String filterDescription; DB
	//private Set<EntryFilter> entryFilters; DBT
	//private String status; DB
	//private String filterSchemaXml; DB
    //private boolean containsCorrelation; DB
	
    //private Date dateAdded; DB (not tested DB system date)
    //private Date dateDeprecated; DB
    //private Date dateActivated; DB
    //private Date dateDeactivated; DB
    //private Date dateUpdated; DB
	
    No DB column:
	private String filterString;
    private Schema filterSchema;*/
    
    private FilterMetaData populateFilterMetaData() 
    {
    	FilterMetaData filterMetaData = new FilterMetaData();
    	
    	filterMetaData.setVhimVersions( VHIM_VERSION );
    	filterMetaData.setFilterId( ID );
    	filterMetaData.setFilterDescription( DESCRIPTION );
    	
    	EntryFilter entryFilter = new EntryFilter();
     	DomainEntryPoint entryPointAllergy = new DomainEntryPoint();
    	entryPointAllergy.setName( ENTRY_POINT_ALLERGY_NAME );
    	entryPointAllergy.setDomain( ENTRY_POINT_ALLERGY_DOMAIN );
    	entryFilter.setDomainEntryPoint( entryPointAllergy );
     	DomainEntryPoint entryPointTiu = new DomainEntryPoint();
    	entryPointTiu.setName( ENTRY_POINT_TIU_NAME );
    	entryPointTiu.setDomain( ENTRY_POINT_TIU_DOMAIN );
    	entryFilter.setDomainEntryPoint( entryPointTiu );
    	Set<EntryFilter> setEntryFilters = new HashSet<EntryFilter>();
    	setEntryFilters.add( entryFilter );
    	filterMetaData.setEntryFilters( setEntryFilters );
    	
    	filterMetaData.setStatus( STATUS );
    	filterMetaData.setFilterSchemaXml( FILE_STRING );
    	filterMetaData.setContainsCorrelation( CORRELATION );
    	
    	java.util.Date date = new java.util.Date();   
    	Calendar cal = Calendar.getInstance();   
    	cal.setTime(date);   
    	
		filterMetaData.setDateDeprecated( cal.getTime() );
		cal.add(Calendar.DATE,1); //force diff dates
    	filterMetaData.setDateActivated( cal.getTime() );
    	cal.add(Calendar.DATE,1); //force diff dates
    	filterMetaData.setDateDeactivated( cal.getTime() );
    	cal.add(Calendar.DATE,1); //force diff dates
    	filterMetaData.setDateUpdated( cal.getTime() );
		
		return filterMetaData;
	}
    

    @Resource
    public void setCreateManager( CreateFilterPersistenceManagerInterface aCreateFilterManager )
	{
		createManager = aCreateFilterManager;
	}
    

    @Resource
    public void setDeleteManager( DeletePersistenceManagerInterface aDeleteManager )
	{
		deleteManager = aDeleteManager;
	}
	

    @Resource
    public void setReadManager( ReadPersistenceManagerInterface aReadManager )
    {
        readManager = aReadManager;
    }

}
