

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.TemplateMetaData;

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/tfrCrdTemplatePersistenceContextTest.xml",
                "classpath:gov/va/med/tfs/config/nonWeblogicTfrDataSourceContext.xml" } )
public class CreateReadDeleteTemplateMappingTest
{
    private static ReadPersistenceManagerInterface readManager;
    private static CreateTemplatePersistenceManagerInterface 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_TEMPLATE";
    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 TEMPLATE_NAME = "TemplateName";
	private String OPERATION = "Read";
	private String STATUS = "ACTIVE";
	private boolean TEST_ONLY = true;
	private byte[] FILE_BYTES = new byte[(int)10];
	
	private String SUCCESSFUL_TEMPLATE_DELETE = "Sucessfully Deleted Template - Thank You";
	private String FAILED_TEMPLATE_DELETE = "Template Not Found -- Template Not Deleted";
	private String SUCCESSFUL_TEMPLATE_CREATE = "Sucessfully Persisted Template - Thank You";
	private String FAILED_TEMPLATE_CREATE = "Record already exists -- Template Not Persisted";
		

	@Test
    @Suite( groups = { "checkintest" } )
    public void testCreatePersistenceManagers( )
    {
		Assert.assertNotNull( readManager );
        Assert.assertNotNull( createManager );
        Assert.assertNotNull( deleteManager );
        System.out.println( "CreateReadDeleteTemplateMappingTest -- 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 templateCreateReadDeleteTest( )
        throws Exception    
    {
    	TemplateMetaData persistTemplateMetaData = new TemplateMetaData();
    	TemplateMetaData readTemplateMetaData = null;
    	String tfrReturn = null;
    	
    	//Populate Template
     	persistTemplateMetaData = populateTemplateMetaData();
    	
    	//Clean up database
     	System.out.println( "Clean up DB -- Regardless of status delete" );
     	deleteManager.deleteTemplateData( ID );
    	
    	//insert Active Template works
    	System.out.println( "Insert Active Template Works" );
    	tfrReturn = createManager.createTemplateData( persistTemplateMetaData );
    	Assert.assertEquals( tfrReturn, SUCCESSFUL_TEMPLATE_CREATE );
    	
    	//insert second Template fails
    	System.out.println( "Insert Second Template Fails" );
    	tfrReturn = createManager.createTemplateData( persistTemplateMetaData );
    	Assert.assertEquals( tfrReturn, FAILED_TEMPLATE_CREATE );
    	
    	//read Template works (status 'ACTIVE')
    	System.out.println( "Read Active Template Works" );
    	readTemplateMetaData = readManager.readTemplateData( ID );
    	Assert.assertNotNull( readTemplateMetaData );
    	
    	//validate Template DB contents
    	System.out.println( "Validate Persisted Data" );
    	validatePersistedData( readTemplateMetaData, persistTemplateMetaData );
    	
    	//delete Template works
    	System.out.println( "Delete Template Works" );
    	tfrReturn = deleteManager.deleteTemplateData( ID );
    	Assert.assertEquals( tfrReturn, SUCCESSFUL_TEMPLATE_DELETE );
    	
    	//second delete Template fails
    	System.out.println( "Second Delete Template Fails" );
    	tfrReturn = deleteManager.deleteTemplateData( ID );
    	Assert.assertEquals( tfrReturn, FAILED_TEMPLATE_DELETE );
    	
    	//read deleted Template fails
     	System.out.println( "Read Deleted Template Fails" );
    	readTemplateMetaData = readManager.readTemplateData( ID );
    	Assert.assertNull( readTemplateMetaData );
    	    	
    	System.out.println( "CreateReadDeleteTemplateMappingTest -- Test Completed" );
    }
    

    /*
     * This test will:
     *  	- Persist a new OLD filter
     *      - Read it and ensure ensure its ignored
     *      - Delete it                 
     */
    @Test
    @Suite( groups = { "checkintest" } )
    public void templateStatusTest( )
        throws Exception    
    {
    	TemplateMetaData persistTemplateMetaData = new TemplateMetaData();
    	TemplateMetaData readTemplateMetaData = null;
    	String tfrReturn = null;
    	
    	//Populate Template
     	persistTemplateMetaData = populateTemplateMetaData();
    	
    	//Clean up database
     	System.out.println( "Clean up DB -- Regardless of status delete" );
     	deleteManager.deleteTemplateData( ID );
     	
		//Testing Old status
		persistTemplateMetaData.setStatus("OLD");
     	
    	//insert Old Template works
    	System.out.println( "Insert Old Template Works" );
    	tfrReturn = createManager.createTemplateData( persistTemplateMetaData );
    	Assert.assertEquals( tfrReturn, SUCCESSFUL_TEMPLATE_CREATE );
    	
    	//read Template fails (ignore status 'OLD')
    	System.out.println( "Read OLD Template Fails" );
    	readTemplateMetaData = readManager.readTemplateData( ID );
    	Assert.assertNull( readTemplateMetaData );
    	
    	//Clean up database (ignore status 'OLD')
    	System.out.println( "Delete Template Works" );
		tfrReturn = deleteManager.deleteTemplateData( ID );
		Assert.assertEquals( tfrReturn, SUCCESSFUL_TEMPLATE_DELETE );
    	    	
    	System.out.println( "templateStatusTest -- Test Completed" );
    }
    

    private void validatePersistedData( TemplateMetaData aReadTemplateMetaData, TemplateMetaData aPersistTemplateMetaData )
	{
		Assert.assertEquals( aReadTemplateMetaData.getTemplateName(), aPersistTemplateMetaData.getTemplateName() );
		validateVhimVersions ( aReadTemplateMetaData.getVhimVersions(), aPersistTemplateMetaData.getVhimVersions() );
		Assert.assertEquals( aReadTemplateMetaData.getTemplateId(), aPersistTemplateMetaData.getTemplateId() );
		Assert.assertEquals( aReadTemplateMetaData.getOperation(), aPersistTemplateMetaData.getOperation() );
		Assert.assertEquals( aReadTemplateMetaData.getTestOnly(), aPersistTemplateMetaData.getTestOnly() );
		Assert.assertEquals( aReadTemplateMetaData.getTemplateDescription(), aPersistTemplateMetaData.getTemplateDescription() );
		validateDomainEntryPoints( aReadTemplateMetaData.getDomainEntryPoints(), aPersistTemplateMetaData.getDomainEntryPoints() );
		Assert.assertEquals( aReadTemplateMetaData.getStatus(), aPersistTemplateMetaData.getStatus() );
		Assert.assertArrayEquals( aReadTemplateMetaData.getTemplateJar(), aPersistTemplateMetaData.getTemplateJar() );
		validateDate( aReadTemplateMetaData.getDateDeprecated(),  aPersistTemplateMetaData.getDateDeprecated() );
		validateDate( aReadTemplateMetaData.getDateActivated(), aPersistTemplateMetaData.getDateActivated() );
		validateDate( aReadTemplateMetaData.getDateDeactivated(), aPersistTemplateMetaData.getDateDeactivated() );
		validateDate( aReadTemplateMetaData.getDateUpdated(), aPersistTemplateMetaData.getDateUpdated() );
	}
	

    private void validateDomainEntryPoints( Set<DomainEntryPoint> readEntryTemplates, Set<DomainEntryPoint> persistEntryTemplates )
	{
		String readName = null;
		String readDomain = null;
		Iterator<DomainEntryPoint> readEntryTemplatesIterator = readEntryTemplates.iterator();
		DomainEntryPoint readEntryTemplate = null;
		
		for ( DomainEntryPoint persistEntryTemplate : persistEntryTemplates )
		{
			readName = persistEntryTemplate.getName();
			readDomain = persistEntryTemplate.getDomain();

			readEntryTemplate = readEntryTemplatesIterator.next();
			Assert.assertEquals( readName, readEntryTemplate.getName() );
			Assert.assertEquals( readDomain, readEntryTemplate.getDomain() );
		}
	}


	//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() );

    }


/*	  
    TemplateMetaData():
    
    private String templateName;  DB
    private Set<String> vhimVersions;  DB
    private String templateId;  DB
    private String operation;  DB (as operation)
    private boolean testOnly;  DB
    private String templateDescription;  DB
    private Set<DomainEntryPoint> domainEntryPoints;  DB
    private String status;  DB
    private byte[] templateJar;  DB
    private Date dateAdded;  DB
    private Date dateDeprecated;  DB
    private Date dateActivated;  DB
    private Date dateDeactivated;  DB
    private Date dateUpdated;  DB
        
    No DB column:
    private String cdsVdm;
    private HashSet<String> readCdsVdms;
    
    */
    
    private TemplateMetaData populateTemplateMetaData() 
    {
    	TemplateMetaData templateMetaData = new TemplateMetaData();
    	
    	templateMetaData.setTemplateName( TEMPLATE_NAME);
    	templateMetaData.setVhimVersions( VHIM_VERSION );
    	templateMetaData.setTemplateId( ID );
    	templateMetaData.setOperation( OPERATION ); //RequestType
    	templateMetaData.setTestOnly( TEST_ONLY );
     	templateMetaData.setTemplateDescription( DESCRIPTION );
    	
     	Set<DomainEntryPoint> setDomainEntryPoints = new HashSet<DomainEntryPoint>();
    	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 );
    	setDomainEntryPoints.add( entryPointAllergy );
    	setDomainEntryPoints.add( entryPointTiu );
    	templateMetaData.setDomainEntryPoints( setDomainEntryPoints );
    	
    	templateMetaData.setStatus( STATUS );
    	templateMetaData.setTemplateJar( FILE_BYTES );
    	
    	java.util.Date date = new java.util.Date();   
    	Calendar cal = Calendar.getInstance();   
    	cal.setTime(date);   
    	
    	templateMetaData.setDateDeprecated( cal.getTime() );
		cal.add(Calendar.DATE,1); //force diff dates
		templateMetaData.setDateActivated( cal.getTime() );
    	cal.add(Calendar.DATE,1); //force diff dates
    	templateMetaData.setDateDeactivated( cal.getTime() );
    	cal.add(Calendar.DATE,1); //force diff dates
    	templateMetaData.setDateUpdated( cal.getTime() );
		
		return templateMetaData;
	}
    

    @Resource
    public void setCreateManager( CreateTemplatePersistenceManagerInterface aCreateManager )
	{
		createManager = aCreateManager;
	}
    

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

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

}
