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

// Java classes

// Library classes
import java.sql.Timestamp;
import java.util.Date;
import java.util.Iterator;
import java.util.Set;

import org.apache.commons.lang.Validate;

// Framework classes

// ESR classes
import gov.va.med.esr.common.infra.ImpreciseDate;
import gov.va.med.esr.common.infra.ImpreciseDateUtils;
import gov.va.med.esr.common.model.ee.ConflictExperience;
import gov.va.med.esr.common.model.ee.MilitaryServiceEpisode;
import gov.va.med.esr.common.model.ee.MilitaryServiceSiteRecord;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.person.DeathRecord;
import gov.va.med.esr.common.model.lookup.ConflictLocation;
import gov.va.med.esr.common.model.lookup.DischargeType;
import gov.va.med.esr.common.model.lookup.FilipinoVeteranProof;
import gov.va.med.esr.common.model.lookup.MilitaryServiceComponent;
import gov.va.med.esr.common.model.lookup.ServiceBranch;
import gov.va.med.esr.common.model.lookup.ServicePeriod;
import gov.va.med.esr.common.model.lookup.VAFacility;
import gov.va.med.esr.common.rule.service.impl.RuleValidationMessage;
import gov.va.med.esr.common.util.RuleAbstractTestCase;
import gov.va.med.fw.security.UserCredentials;
import gov.va.med.fw.util.StringUtils;
import gov.va.med.fw.validation.ValidationFieldMessage;
import gov.va.med.fw.validation.ValidationMessages;
import gov.va.med.fw.validation.ValidationServiceException;
import gov.va.med.esr.common.model.ee.MilitaryService;
import gov.va.med.esr.common.model.lookup.EnrollmentStatus;
import gov.va.med.esr.common.rule.parameter.MilitaryServiceInputParameter;

/**
 * Provides methods to test BAL rules in ConflictExperienceValidation rule flow
 *
 * Project: Common</br>
 * Created on: 4:45:47 PM </br>
 *
 * @author DNS   LEV
 */
public class MilitaryServiceRuleServiceTest extends RuleAbstractTestCase {

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

	/**
	 * constructor
	 */
	public MilitaryServiceRuleServiceTest(String testName) throws Exception {
		super(testName);
	}
    
	public void testNDAARelatedDates() throws Exception {
		
		MilitaryServiceInputParameter input = new MilitaryServiceInputParameter();
		String ndaaDtStr = input.getNDAADate("01/28/2008").toString();
		String ndaaDtPlus3YrMinus1DayStr = input.getNDAADatePlus3YearsMinus1Day("01/28/2008").toString();
		return;
	}
    
    /** 
    3325[UC87.26] Combat Veteran Eligibility End Date 
    Combat Veteran Eligibility End Date is for display-only. 

    REPLACE REQUIREMENT 3326 WITH THE FOLLOWING
    3326[UC87.26.1]  
    The system determines if the veteran is Combat Veteran eligible and automatically sets the Combat Veteran Eligibility End Date using the following criteria:
    Veteran Indicator = Yes
    AND
    (If Service Separation Date (SSD) is precise
    AND greater than 11/11/98)
    AND The Combat To Date is greater than 11/11/98
    AND the Combat Location is either Yugoslavia, Somalia, Gulf War, Persian Gulf War or Other
    THEN
    The veteran is Combat Veteran Eligible.

    (If Service Separation Date (SSD) is precise
    AND greater than 11/11/98)
    AND the Combat Location is either OEF, OIF, Unknown OEF/OIF or Conflicted Unspecified
    THEN
    The veteran is Combat Veteran Eligible.

    If the Combat Location is either OEF, OIF, Unknown OEF/OIF, or Conflict Unspecified
    AND the Combat To Date is precise
    AND (the Combat To Date is later than the last SSD 
    OR there is no SSD)
    THEN
    The veteran is Combat Veteran Eligible.

    If the veteran is not determined to be Combat Veteran Eligible by any of the above conditions, the  system Automatically sets the CV Eligibility End Date to Null


    NEW REQUIREMENT
    The system automatically sets the Combat Veteran Eligibility End Date using the following criteria:
    The veteran is determined to be Combat Veteran Eligible (above)
    AND
    The veteran has no enrollment record prior to the NDAA Date of Enactment (1/28/2008)
    IF the most recent of [SSD (if one exists) or Combat To Date] is greater than five years prior to the NDAA Date of Enactment 
    THEN
    The system automatically sets the CV Eligibility End Date = NDAA Date of Enactment + 3 years – 1 day
    ELSE
    The system automatically sets the CV Eligibility End Date = the most recent of [SSD or Combat To Date] + 5 years minus 1 day .

    The veteran has one or more enrollment records prior to the NDAA Date of Enactment
    AND
    The enrollment status on the CURRENT enrollment record is Rejected; Below Enrollment Group Threshold or Rejected; Initial Application at VAMC
    IF the most recent of [SSD (if one exists) or Combat To Date] is greater than five years prior to the NDAA Date of Enactment
    THEN
    The system automatically sets the CV Eligibility End Date = NDAA Date of Enactment + 3 years – 1 day
    ELSE
    The system automatically sets the CV Eligibility End Date = the most recent of [SSD or Combat To Date] + 5 years minus 1 day.

    The enrollment status on the CURRENT enrollment record is any status other than “Rejected”
    The system automatically sets the CV Eligibility End Date = the most recent of [SSD or Combat To Date] + 5 years minus 1 day.


    Remove from 3326 and assign to a new requirement:
    For a recomputation of the CV End Date, the system will not assign a CV end date that is prior to the existing CV end date.  The veteran is always given the greater benefit.
    If there are multiple combat locations and Service Separation Dates (both HEC entered and site data) the system will use the SSD and/or the Combat To Date from the specific HEC entered data or a specific site data that gives the veteran the greater benefit.  The system does not mix SSD and Combat To dates between HEC and site data. 

             **/
	public void testComputeCVEligibilityEndDate() throws Exception {
		
        Person onFile = this.getPerson("104"); //vet, has enroll prior, not rejected, ssd/ctd within 5 years
                
        MilitaryService ms = onFile.getMilitaryService();
        
        java.util.Date cvEndDt1 = ms.getCombatVeteranEligibilityEndDate();
        
        Person updated = this.getMilitaryRuleService().manageMilitaryService(ms, onFile);
        
        MilitaryService currentMilitaryInfo = updated.getMilitaryService();
        if( currentMilitaryInfo == null ) {
            throw new Exception("Military Serveice can not be null!!");
        }
 
        java.util.Date cvEndDt2 = currentMilitaryInfo.getCombatVeteranEligibilityEndDate();
        this.assertEquals(cvEndDt1,cvEndDt2);

	}
	
    
    public void testNullMSEStartDate() throws Exception {
        
        Person onFile = this.getPerson("564");            
        MilitaryService ms = onFile.getMilitaryService();
        java.util.Date dt = ms.getServiceEntryDate(); //make sure no null pointer exception
        
        this.assertEquals(true, true);

    }
    
    public void tesIsCVEligibilityEndDateNotExpired() throws Exception {
        
        //CCR# 7124
        Person onFile = this.getPerson("564");            
        MilitaryService ms = onFile.getMilitaryService();
        java.util.Date cvEndDt = ms.getCombatVeteranEligibilityEndDate(); //make sure to change to today's date
        
        MilitaryServiceInputParameter param = new MilitaryServiceInputParameter();
        
        //simulate the rule
        //((?militaryServiceInput.isSameDay( ?militaryServiceInput.getCombatVeteranEligibilityEndDate(), ?militaryServiceInput.getCurrentDate() ) || ?militaryServiceInput.isAfter( ?militaryServiceInput.getCombatVeteranEligibilityEndDate(), ?militaryServiceInput.getCurrentDate() ))
        boolean notExpired = param.isSameDay( cvEndDt, new Timestamp(System.currentTimeMillis()) ) || param.isAfter( cvEndDt, new Timestamp(System.currentTimeMillis()) );
//        boolean notExpired = param.isAfter(new Timestamp(System.currentTimeMillis()), dt);
        
        this.assertEquals(true, notExpired);

    }
    
	public void testProcessMilitaryServiceNumbers() throws Exception {
		
        //Person onFile = this.getPerson("377490231");//0000001008693785V600883000000
        
		// Add HEC military service site record information
		MilitaryServiceSiteRecord siteRecord = new MilitaryServiceSiteRecord();
		siteRecord.setSite(getLookupService().getVaFacilityByCode(
				VAFacility.CODE_HEC.getName()));
		siteRecord.setServicePeriod(getLookupService().getServicePeriodByCode(
				ServicePeriod.CODE_AIR_FORCE.getName()));
		//siteRecord.setFilipinoVeteranProof(getLookupService()
		//		.getFilipinoVeteranProofByCode(
		//				FilipinoVeteranProof.CODE_US_BIRTH_CERTIFICATE
		//						.getName()));
		onFile.getMilitaryService().addMilitaryServiceSiteRecord(
				siteRecord);

		// Add military service episode information
		MilitaryServiceEpisode episode = new MilitaryServiceEpisode();
		//episode.setServiceNumber("Service Number 1");
		episode.setStartDate(ImpreciseDateUtils.createImpreciseDate(2008, 4, 1));
		episode.setEndDate(ImpreciseDateUtils.createImpreciseDate(2012, 3, 31));
		episode.setServiceBranch(getLookupService().getServiceBranchByCode(
				ServiceBranch.CODE_AIR_FORCE.getName()));
		episode.setDischargeType(getLookupService().getDischargeTypeByCode(
				DischargeType.CODE_HONORABLE.getName()));
		episode.setMilitaryServiceComponent(
				(MilitaryServiceComponent)this.getLookupService().getByCode(MilitaryServiceComponent.class, 
						MilitaryServiceComponent.CODE_REGULAR.getCode()));
		siteRecord.addMilitaryServiceEpisode(episode);
		
		// Add Site 608	MANCHESTER VAMC military service site record information
		MilitaryServiceSiteRecord siteRecord2 = new MilitaryServiceSiteRecord();
		siteRecord2.setSite(getLookupService().getVaFacilityByCode("608"));
		siteRecord2.setServicePeriod(getLookupService().getServicePeriodByCode(
				ServicePeriod.CODE_AIR_FORCE.getName()));
		//siteRecord.setFilipinoVeteranProof(getLookupService()
		//		.getFilipinoVeteranProofByCode(
		//				FilipinoVeteranProof.CODE_US_BIRTH_CERTIFICATE
		//						.getName()));
		onFile.getMilitaryService().addMilitaryServiceSiteRecord(
				siteRecord2);

		// Add military service episode information
		MilitaryServiceEpisode episode2 = new MilitaryServiceEpisode();
		episode.setServiceNumber("Service Number 1");
		episode2.setStartDate(ImpreciseDateUtils.createImpreciseDate(2008, 4, 1));
		episode2.setEndDate(ImpreciseDateUtils.createImpreciseDate(2012, 3, 31));
		episode2.setServiceBranch(getLookupService().getServiceBranchByCode(
				ServiceBranch.CODE_AIR_FORCE.getName()));
		episode2.setDischargeType(getLookupService().getDischargeTypeByCode(
				DischargeType.CODE_HONORABLE.getName()));
		episode2.setMilitaryServiceComponent(
				(MilitaryServiceComponent)this.getLookupService().getByCode(MilitaryServiceComponent.class, 
						MilitaryServiceComponent.CODE_REGULAR.getCode()));
		siteRecord2.addMilitaryServiceEpisode(episode2);
		
        Person updated = this.getMilitaryRuleService().processMilitaryServiceNumbers(onFile);
        
        MilitaryService currentMilitaryInfo = updated.getMilitaryService();
        if( currentMilitaryInfo == null ) {
            throw new Exception("Military Serveice can not be null!!");
        }
 
        MilitaryServiceSiteRecord hecRecord = currentMilitaryInfo.getHECMilitaryServiceSiteRecord();
        this.assertNotNull(hecRecord);

  		Set episodes = hecRecord.getMilitaryServiceEpisodes();
  		this.assertNotNull(episodes);
		
		for (Iterator i = episodes.iterator(); i.hasNext();) {
			MilitaryServiceEpisode hecMilitaryServiceEpisode = (MilitaryServiceEpisode) i.next();
			this.assertNotNull(hecMilitaryServiceEpisode.getServiceNumber());
			this.assertEquals(hecMilitaryServiceEpisode.getServiceNumber(), "Service Number 1");
		}

	}
	
	public void testisAgentOrangeLocationNull() throws Exception {
		/** 4084[UC34.3.10.1.8.5] 
		If the EDB Agent Orange Indicator is YES and the Agent Orange Location is NULL and the Z07 is received where Agent Orange is YES and Agent Orange location is not null THEN accept the Agent Orange Location even if current Eligibility Status on EDB is = Verified. This will allow the population of Agent Orange Location on records that had not had it populated before. Agent Orange location was collected at VistA sites prior to it being collected on the HEC legacy and EDB. 

		=================================
		IF
		The veteran's current agent orange indicator on file is equal to YES
		AND
		It is not true that
		The veteran's current agent orange location on file is provided
		AND
		the recieved agent orange indicator is equal to YES
		AND
		The received agent orange location is provided
		THEN
		Set a veteran’s agent orange location to the received agent orange location

		*/		
	}
	
	public void testisAgentOrangeUpdatedToNo() throws Exception {
		/** 
		1826[UC34.3.10.1.8.1] 
		If the Agent Orange Indicator changes from ‘Yes’ to ‘No’, the Agent Orange Location will become ‘NULL’. 

		IF
		The veteran’s current agent orange indicator is equal to YES
		AND
		The veteran’s result (updated) agent orange indicator is equal to NO
		THEN
		set a veteran’s agent orange location to NULL

		*/
	}
	
	public void testisEDBEligPendingAcceptDisability() throws Exception {
		/** 1816[UC34.3.10.1.3.2] 
		For an existing person: when the EDB Eligibility Status is Pending Verification or Pending Reverification and the Z07 Eligibility Status is = Verified, the system will accept the Z07 data for Military Disability Retirement and Discharge Due to Disability, regardless of the Z07 SC% and Total Check Amount. 


		IF
		(
		The current EDB eligibility status on file is Pending Verification
		OR
		The current EDB eligibility status on file is Pending Re-verification
		)
		AND
		The received eligibility status is equal to Verified
		THEN
		Set a veteran’s military disability retirement indicator to the received military disability retirement indicator
		Set a veteran’s discharge due to disability indicator to the received discharge due to disability indicator

		*/
	}
	
	public void testisEDBEligPendingAcceptSpecialFactors() throws Exception {
		/** 4083[UC34.3.10.1.8.4] 
		For an existing veteran if the EDB Eligibility Status is = Pending Verification or Pending Reverification THEN accept the Agent Orange Indicator and Agent Orange Location and/or the Radiation Exposure Indicator and Radiation Exposure Method and/or the Environmental Contaminant Indicator. 
		======================

		IF
		The current EDB eligibility status on file is Pending Verification
		OR
		The current EDB eligibility status on file is Pending Re-verification
		THEN
		Set a veteran’s agent orange indicator to the received agent orange indicator
		Set a veteran’s agent orange location to the received agent orange location
		Set a veteran’s radiation exposure indicator to the received radiation exposure indicator
		Set a veteran’s radiation exposure method to the received radiation exposure method
		Set a veteran’s environmental contaminants indicator to the received environmental contaminants indicator


		*/
	}
	
	public void testisRadiationExposureMethodNull() throws Exception {
		/** 4085[UC34.3.10.1.8.6] 
		If the EDB Radiation Exposure Indicator is YES and the Radiation Exposure Method is NULL and the Z07 is received where Radiation Exposure Method is YES and Radiation Exposure Method is not null THEN accept the Radiation Exposure Method even if current Eligibility Status on EDB is = Verified. This will allow the population of Radiation Exposure Method on records that had not had it populated before. Radiation Exposure Method was collected at VistA sites prior to it being collected on the HEC legacy and EDB. 

		IF
		The veteran's current radiation exposure indicator on file is equal to YES
		AND
		It is not true that
		The veteran's current radiation exposure method on file is provided
		AND
		the received rediation exposure indicator is equal to YES
		AND
		The received radiation exposure method is provided
		THEN
		set a veteran’s radiation exposure method to the received radiation exposure method

		*/
	}

	public void testisRadiationExposureUpdatedToNo() throws Exception {
		/** 1827[UC34.3.10.1.8.2] 
		If the Radiation Exposure Indicator changes from Yes to No then the Radiation Exposure Method will be set to Null. 

		IF
		The veteran’s current radiation exposure indicator on file is equal to YES
		AND
		The veteran’s resulting radiation exposure indicator is equal to NO
		THEN
		set a veteran’s radiation exposure method to NULL

		*/
	}
	
	public void testacceptMilitaryServiceDatafromHEC() throws Exception {
		/** 3171[UC23.4] Update Military Service Information
		The actor is allowed to update the following Military Service Information. Specific Requirements are found in the Special Requirements Section:
		Branch of Service
		Service Entry Date
		Service Separation Date
		Service Discharge Type
		Military Service Number
		Filipino Veteran Proof
		Conflict Location(s)
		Conflict From Date
		Conflict To Date
		Military Disability Retirement 
		Discharge Due to Disability 
		Radiation Exposure Indicator
		Radiation Exposure Method
		Agent Orange Indicator
		Agent Orange Exposure Location
		Environmental Contaminants Indicator
		HEC Period Of Service (POS)
		SHAD Indicator 

		4182[UC23.4.1] 
		When a HEC actor enters/edits the following Military Service Information the system updates it in place. HEC data becomes site 742 data. 
		Branch of Service
		Service Entry Date
		Service Separation Date
		Service Discharge Type
		Military Service Number
		Filipino Veteran Proof
		Conflict Location(s) (Includes the VistA Conflict locations)
		Conflict From Date (Includes the VistA Conflict From Date)
		Conflict To Date (Includes the VistA To Date)
		Period of Service 
		========================
		NOTE: When HEC entered data passes the data validation it is accepted.

		*/
	}
	
	public void testupdateAgentOrangeToNo() throws Exception {
		/** 4080[UC23.25.2]  GUI
		If the actor deletes the Agent Orange Location, the system sets the Agent Orange Indicator to = No
		The system displays a warning message to the actor:   “ Removing Agent Orange Location will change the Agent Orange Indicator to No.” 

		=============================
		IF
		The current agent orange location on file for the veteran is provided
		AND
		It is not true that
		The received agent orange location for the veteran is provided
		THEN
		set a veteran’s agent orange indicator to NO

		*/
	}
	
	public void testupdateAgentOrangeToYes() throws Exception {
		/** 3332[UC23.25] Agent Orange Exposure Location 
		If Agent Orange Location is entered, the system sets Agent Orange Indicator is = Yes. 

		IF
		The received agent orange location for the veteran is provided
		THEN
		Set a veteran's agent orange indicator to YES

		*/
	}
	
	public void testupdateRadiationExposureToNo() throws Exception {
		/** 3330[UC23.24.2]  
		If the actor deletes the Radiation Exposure Method, the system sets the Radiation Exposure Indicator to = No.

		The system displays a warning message to the actor:   " Removing Radiation Exposure Method  will change the Radiation Exposure Indicator to No." 

		======================================
		IF
		The current radiation exposure method on file for the veteran is provided
		AND
		It is not true that
		The received radiation exposure method is provided
		THEN
		set a veteran’s radiation exposure indicator to NO


		*/
	}
	
	public void testupdateRadiationExposureToYes() throws Exception {
		/** 3327[UC23.24] Radiation Exposure Method 
		If Radiation Exposure Method is entered , the system sets Radiation Exposure Indicator is = Yes. 

		==============================
		IF
		The received radiation exposure method is provided
		THEN
		set a veteran’s radiation exposure indicator to YES

		*/
	}
	
	public void testcalculateCVEligEndDate() throws Exception {
		/** 3325[UC23.23] Combat Veteran Eligibility End Date 
		Combat Veteran Eligibility End Date is for display-only. 

		3326[UC23.23.1]  
		The system determines if the veteran is Combat Veteran eligible and automatically sets the Combat Veteran Eligibility End Date using the following criteria:

		(IF Service Separation Date (SSD) is precise AND greater than 11/11/98, AND
		The Conf3325[UC23.23] Combat Veteran Eligibility End Date 
		Combat Veteran Eligibility End Date is for display-only. 

		3326[UC23.23.1]  
		The system determines if the veteran is Combat Veteran eligible and automatically sets the Combat Veteran Eligibility End Date using the following criteria:

		(IF Service Separation Date (SSD) is precise AND greater than 11/11/98, AND
		The Conflict To Date is greater than 11/11/98 and Conflict Location is Yugoslavia OR Somalia OR Gulf War
		THEN 
		The system Automatically sets the CV Eligibility End Date = SSD + 2 years)
		ELSE
		The system Automatically sets the CV Eligibility End Date to Null 

		=======================
		IF
		The most recent received service separation date for the veteran is greater than 11/11/98
		AND
		(
		The most recent received conflict to date for the veteran is greater than 11/11/98 with a conflict location of YUGOSLAVIA
		OR
		The most recent received conflict to date for the veteran is greater than 11/11/98 with a conflict location of  SOMALIA
		OR
		The most recent received conflict to date for the veteran is greater than 11/11/98 with a conflict location of GULF WAR
		)
		THEN
		Update a veteran's CV Eligibility End Date to most recent received SSD + 2 years
		ELSE
		Update a veteran's CV Eligibility End Date to NULL

		*/		
	}
	
	/**
	 * @see gov.va.med.fw.util.AbstractTestCase#customSetUp()
	 */
	protected void customSetUp() throws Exception {
		super.customSetUp();
		onFile = this.buildSimplePerson();
        UserCredentials credentials = new UserCredentials();
        credentials.setUserID("bea");
        credentials.setPassword("bea");
        loginManager.login(credentials);
	}

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

	/**
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
	 */
	public void afterPropertiesSet() throws Exception {
		super.afterPropertiesSet();
		Validate.notNull(this.getRuleValidationService(), "A rule validation service is required");
	}
}