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


import gov.va.med.esr.common.infra.ImpreciseDate;
import gov.va.med.esr.common.model.ee.PrisonerOfWar;
import gov.va.med.esr.common.model.ee.POWEpisode;
import gov.va.med.esr.common.model.lookup.Indicator;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.util.RuleAbstractTestCase;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.esr.common.infra.ImpreciseDateUtils;


/**
 * @author VHAIVMNgVS
 * @author Yi He
 */

public class ProcessPOWTest extends RuleAbstractTestCase {
    
	/**
	 * An instance of onFile
	 */
	private Person onFile = null;
    
    public ProcessPOWTest(String testName) {
        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;
	}
	
    public void testHasPOW() throws Exception {
		// Persist the on-file person so we will have a pristine person in rule parameters
		// Prepare the on-file person with 1 POW
		this.getPersonService().save( onFile );

		// Clone the pristine to have a working version
		Person working = (Person)onFile.clone();
		Person incoming = (Person)onFile.clone();
        this.attachPrisonerOfWar(incoming, ImpreciseDateUtils.createImpreciseDate(1941,1,1), ImpreciseDateUtils.createImpreciseDate(1942,1,1));
        
		
		try {
			this.getPowRuleService().processPOW( incoming, working );
			
		}
		catch( ServiceException e ) {			
			this.fail( "Failed process POW exception ", e );
		}
    }
    public void testUpdatePOWFromUI()throws Exception {
                
        Person onFile = this.buildSimplePerson();
        this.attachPrisonerOfWar(onFile, ImpreciseDateUtils.createImpreciseDate(1917,1,1),
                ImpreciseDateUtils.createImpreciseDate(1918,1,1));        
        Person incoming = this.getPersonService().save( onFile );

        incoming.setPrisonerOfWar(null);
       
        ImpreciseDate capture = ImpreciseDateUtils.createImpreciseDate(1943,1,1);
        ImpreciseDate release = ImpreciseDateUtils.createImpreciseDate(1944,1,1);
        this.attachPrisonerOfWar(incoming, capture, release);              
        
        try {
            this.getPowRuleService().managePOW( incoming, onFile );
            PrisonerOfWar result = (PrisonerOfWar)onFile.getPrisonerOfWar();
            POWEpisode episode = (POWEpisode)result.getEpisodes().iterator().next();
            assertEquals(capture, episode.getCaptureDate());
            assertEquals(release, episode.getReleaseDate());

        }
        catch( ServiceException e ) {           
            this.fail( "Failed process POW exception ", e );
        }        
    }
    
    public void testUpdateNewPOWFromUI()throws Exception {
        
        Person onFile = this.buildSimplePerson();
        Person incoming = this.getPersonService().save( onFile );
        ImpreciseDate capture = ImpreciseDateUtils.createImpreciseDate(1943,1,1);
        ImpreciseDate release = ImpreciseDateUtils.createImpreciseDate(1944,1,1);
        this.attachPrisonerOfWar(incoming, capture, release);              
        
        try {
            this.getPowRuleService().managePOW( incoming, onFile );
            PrisonerOfWar result = (PrisonerOfWar)onFile.getPrisonerOfWar();
            POWEpisode episode = (POWEpisode)result.getEpisodes().iterator().next();            
            System.out.println("calcd diff="+episode.getNumberOfDaysInCaptivity());
            assertEquals(capture, episode.getCaptureDate());
            assertEquals(release, episode.getReleaseDate());

        }
        catch( ServiceException e ) {           
            this.fail( "Failed process POW exception ", e );
        }        
    }    
    
    public void testPOWInfoChangedFromUI() throws Exception {

        Person onFile = this.buildSimplePerson();
        this.attachPrisonerOfWar(onFile, ImpreciseDateUtils.createImpreciseDate(1943,1,1),
                ImpreciseDateUtils.createImpreciseDate(1944,1,1));        

        Person incoming = this.getPersonService().save(onFile);
        incoming.getPrisonerOfWar().setPowIndicator((Indicator)this.getLookupService().getByCode(Indicator.class, Indicator.NO.getCode()));
        this.getPowRuleService().managePOW(incoming, onFile);

        assertFalse(onFile.getPrisonerOfWar().getPowIndicator().getCode().equals(Indicator.NO.getCode()));
    }
    
    public void testPOWRemovedFromUI() throws Exception {

        Person onFile = this.buildSimplePerson();
        this.attachPrisonerOfWar(onFile, ImpreciseDateUtils.createImpreciseDate(1943,1,1),
                ImpreciseDateUtils.createImpreciseDate(1944,1,1));        
        Person incoming = this.getPersonService().save(onFile);
        incoming.setPrisonerOfWar(null);
        this.getPowRuleService().managePOW(incoming, onFile);

        assertNull(onFile.getPrisonerOfWar());
    }
    
    public void testPOWEpisodesRemovedFromUI() throws Exception {

        Person onFile = this.buildSimplePerson();
        this.attachPrisonerOfWar(onFile, ImpreciseDateUtils.createImpreciseDate(1943,1,1),
                ImpreciseDateUtils.createImpreciseDate(1944,1,1));
        POWEpisode e = new POWEpisode();
        e.setConfinementLocation(getRandomPrisonerOfWarLocation());        
        e.setCaptureDate(ImpreciseDateUtils.createImpreciseDate(1941,1,1));
        e.setReleaseDate(ImpreciseDateUtils.createImpreciseDate(1944,1,1));
        onFile.getPrisonerOfWar().addEpisode(e);
        
        Person updated = this.getPersonService().save(onFile);
        Person incoming = (Person)updated.clone();
        assertTrue(onFile.getPrisonerOfWar().getEpisodes().size() == 2);        
        assertTrue(incoming.getPrisonerOfWar().getEpisodes().size() == 2);
        
        incoming.getPrisonerOfWar().removeEpisode(e);
        incoming.getPrisonerOfWar().setPowIndicator((Indicator)this.getLookupService().getByCode(Indicator.class, Indicator.NO.getCode()));
        this.getPowRuleService().managePOW(incoming, onFile);

        assertTrue(onFile.getPrisonerOfWar().getEpisodes().size() == 1);
    }            


    public void testPOWValidation()throws Exception {
        
        this.getPersonService().save( onFile );
        // Clone the pristine to have a working version
        Person incoming = (Person)onFile.clone();
        this.attachPrisonerOfWar(incoming, ImpreciseDateUtils.createImpreciseDate(1943,1,1),
                ImpreciseDateUtils.createImpreciseDate(1944,1,1));        
        PrisonerOfWar prisonerOfWar = (PrisonerOfWar)incoming.getPrisonerOfWar();
        POWEpisode powe = (POWEpisode)prisonerOfWar.getEpisodes().iterator().next();
        
        try {
            this.getRuleValidationService().validatePOW( powe, incoming, true );
        }
        catch( ServiceException e ) {           
            this.fail( "Failed process POW exception ", e );
        }        
    }    
    
    public void testPowDiscrepantFromMessage()throws Exception {
        this.attachPrisonerOfWar(onFile, ImpreciseDateUtils.createImpreciseDate(1943,1,1),
                ImpreciseDateUtils.createImpreciseDate(1944,1,1));        
        this.getPersonService().save( onFile );

        // Clone the pristine to have a working version
        Person working = (Person)onFile.clone();
        Person incoming = (Person)onFile.clone();
        this.attachPrisonerOfWar(incoming, ImpreciseDateUtils.createImpreciseDate(1943,1,1),
                ImpreciseDateUtils.createImpreciseDate(1945,1,1));        
        
        try {
            this.getPowRuleService().processPOW( incoming, working );
            // Should trigger PowDiscrepant bulletin
        }
        catch( ServiceException e ) {           
            this.fail( "Failed process POW exception ", e );
        }        
    }    
}