/********************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ********************************************************************/
// Package
package gov.va.med.esr.service;

// Java classes
import java.sql.Date;
import java.util.Calendar;
import java.util.Iterator;

// Library classes
import org.apache.commons.lang.Validate;

// Framework classes
import gov.va.med.fw.util.DateUtils;
import gov.va.med.fw.service.ServiceException;

// ESR classes
import gov.va.med.esr.common.model.lookup.AddressType;
import gov.va.med.esr.common.model.lookup.AssociationType;
import gov.va.med.esr.common.model.person.Association;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.util.AbstractCommonTestCase;
import gov.va.med.esr.common.rule.service.MatchRuleService;

/** Test AssociationService's updateAssociation use case
 * 
 * Project: Common</br>
 * Created on: 7:00:09 PM </br>
 *
 * @author DNS   LEV
 */
public class AssociationServiceTest extends AbstractCommonTestCase {

	/**
	 * An instance of onFile
	 */
	private Person onFile = null;

	/**
	 * An instance of mergeRuleService
	 */
	private MatchRuleService matchRuleService = null;
	
	/**
	 * constructor
	 */
	public AssociationServiceTest(String testName) throws Exception {
		super(testName);
	}

	/**
	 * @see gov.va.med.fw.util.AbstractTestCase#customSetUp()
	 */
	protected void customSetUp() throws Exception {
		super.customSetUp();
		onFile = this.buildSimplePerson();
	}

	/**
	 * @see gov.va.med.fw.util.AbstractTestCase#customTearDown()
	 */
	protected void customTearDown() throws Exception {
		super.customTearDown();
		onFile = null;
	}


	// Tests use case to update an existing association
	public void testUpdateAssociation() throws Exception {

		// Persist the on-file person so we will have a pristine person in rule parameters
		// Prepare the on-file person with 1 association
		
		// Create a time to mimic last updated date on a pristine person
		Calendar cal = DateUtils.createCalendar( 2005, 6, 1 );
		
		Date lastUpdatedTime = new Date( cal.getTime().getTime() );
		
		// Adding some associations to a person
		for( int i=0; i<1; i++ ) {
			Association association = this.createPersonAssociation( "EDS", "Manager " + (i+1), AssociationType.CODE_GUARDIAN_VA.getName() );
			association.setAddress( this.createAddress( this.getAddressType( AddressType.CODE_PERMANENT_ADDRESS)));
			association.setLastUpdateDate( lastUpdatedTime );
			onFile.addAssociation( association );
		}
		Person saved = this.getPersonService().save( onFile );

		// Clone the pristine to have a working version
		Person incoming = (Person)saved.clone();

		// Modify data to accept changes
		Iterator incomingIterator = incoming.getAssociations().iterator();
		
		Date updatedTime = new Date( Calendar.getInstance().getTime().getTime() );


		Association modified = (Association)incomingIterator.next();
		modified.setRelationship( "Big Shot" );
		modified.setOrganizationName( "VHA" );
		modified.setLastUpdateDate( updatedTime );


		try {
			Person updated = this.getAssociationService().updateAssociation( incoming , modified);
			assertEquals( updated.getAssociations().size(), incoming.getAssociations().size() );
			
			incomingIterator = incoming.getAssociations().iterator();
			Iterator updatedIterator = updated.getAssociations().iterator();
			
			while( incomingIterator.hasNext() && updatedIterator.hasNext() ) {
				Association incoming_association = (Association)incomingIterator.next();
				Association updated_association = (Association)updatedIterator.next();
				assertEquals( incoming_association.getRelationship(), updated_association.getRelationship() );
				assertEquals( incoming_association.getOrganizationName(), updated_association.getOrganizationName() );
			}
		}
		catch( ServiceException e ) {
			// We don't expect any exception here
			this.fail( "Failed due to exception ", e );
		}
	}
	
	// Tests use case to update an existing association
	public void testDeleteAssociation() throws Exception {

		// Persist the on-file person so we will have a pristine person in rule parameters
		// Prepare the on-file person with 1 association
		
		// Create a time to mimic last updated date on a pristine person
		Calendar cal = DateUtils.createCalendar( 2005, 6, 1 );
		
		Date lastUpdatedTime = new Date( cal.getTime().getTime() );
		
		// Adding some associations to a person
		for( int i=0; i<1; i++ ) {
			Association association = this.createPersonAssociation( "EDS", "Manager " + (i+1), AssociationType.CODE_GUARDIAN_VA.getName() );
			association.setAddress( this.createAddress( this.getAddressType( AddressType.CODE_PERMANENT_ADDRESS)));
			association.setLastUpdateDate( lastUpdatedTime );
			onFile.addAssociation( association );
		}
		Person saved = this.getPersonService().save( onFile );

		// Clone the pristine to have a working version
		Person incoming = (Person)saved.clone();

		// Remove association from an incoming person
		incoming.removeAllAssociations();
		
		try {
			//Person updated = this.getAssociationService().updateAssociation( incoming );
		    Person updated = incoming;
			assertEquals( updated.getAssociations().size(), incoming.getAssociations().size() );

			if( this.logger.isDebugEnabled() ) {
				logger.debug( "Incoming association list " + incoming.getAssociations() );
				logger.debug( "Updated association list " + updated.getAssociations() );
			}
		}
		catch( Exception e ) {
			// We don't expect any exception here
			this.fail( "Failed due to exception ", e );
		}
	}
	
	/**
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
	 */
	public void afterPropertiesSet() throws Exception {
		Validate.notNull(this.getAssociationService(), "An association service is required");
	}

	/**
	 * @return Returns the matchRuleService.
	 */
	public MatchRuleService getMatchRuleService() {
		return matchRuleService;
	}

	/**
	 * @param matchRuleService The matchRuleService to set.
	 */
	public void setMatchRuleService(MatchRuleService matchRuleService) {
		this.matchRuleService = matchRuleService;
	}
}