/*
 * Created on Jan 5, 2005
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package gov.va.med.esr.common.rule.service;

//----------------------------------------------------------------------------
//Import java classes
//----------------------------------------------------------------------------
import java.text.SimpleDateFormat;
import java.util.Date;

//----------------------------------------------------------------------------
//Import third party library classes
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
//Import Framework classes
//----------------------------------------------------------------------------
import gov.va.med.fw.rule.RuleParameters;
import gov.va.med.fw.rule.RuleValidationException;
import gov.va.med.fw.rule.RuleException;
import gov.va.med.fw.service.ServiceException;

// ESR classes
import gov.va.med.esr.common.infra.ImpreciseDateUtils;
import gov.va.med.esr.common.model.lookup.Gender;
import gov.va.med.esr.common.model.person.DeathRecord;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.util.RuleAbstractTestCase;
import gov.va.med.esr.common.model.person.BirthRecord;
import gov.va.med.esr.common.rule.data.PersonInputData;
import gov.va.med.esr.common.infra.ImpreciseDate;

/**
 * @author vhaivmngvs
 * 
 * TODO To change the template for this generated type comment go to Window -
 * Preferences - Java - Code Style - Code Templates
 */
public class DemographicValidationTest extends RuleAbstractTestCase {

    public DemographicValidationTest(String testName) {
        super(testName);

        // Added the following lines to connect to a rule builder
        // for debugging. consider implementing a base rule test case
        // with options to allow you to connect to a rule engine.
        // Typically these options are passed into JVM through a -D option
        // System.setProperty( AbstractRule.DEBUG_MODE, "true" );
    }

    // ===========
    // IsPseudoSSN
    // ===========
    public void testIsPseudoSSN() throws Exception {
        Person person = this.buildPerson();
        // FIXME structure change
//        person.setSsn("P123456789");

        Gender gender = (Gender) this.getLookupService().getGenderByCode("F");
        person.setGender(gender);

        try {
            this.executeDemographicValidation(person);
        } catch (RuleValidationException rve) {
            assertEquals(rve.getMessageID(), "invalid SSN");
        }

    } // End of executeIsPseudoSSN

    // =========================
    // IsDateOfBirthLessThan1871
    // =========================
    public void testIsDateOfBirthLessThan1871() throws Exception {
        Person person = this.buildPerson();
        BirthRecord br = new BirthRecord();
        ImpreciseDate id = ImpreciseDateUtils.createImpreciseDate(1854, 5, 4);
        br.setBirthDate(id);
        person.setBirthRecord(br);
        try {
            this.executeDemographicValidation(person);
        } catch (Exception ex) {
            assertEquals(ex.getMessage(),
                    "the date of birth can not be greater than 1870");
        }
    } // End of executeIsDateOfBirthLessThan1871

    // =============================
    // IsDateOfBirthGreaterThanDeath
    // =============================
    public void testIsDateOfBirthGreaterThanDeath() throws Exception {
        Person person = this.buildPerson();
        // Set Date of Birth
        person.getBirthRecord().setBirthDate(ImpreciseDateUtils.createImpreciseDate(1954, 5, 6));
        DeathRecord dr = new DeathRecord();
        // Set Date of Death reported;
        dr.setDeathReportDate(getDate(2002, 7, 5));
        // Set Date of Death
        dr.setDeathDate(ImpreciseDateUtils.createImpreciseDate(1995, 5, 6));
        person.setDeathRecord(dr);
        try {
            this.executeDemographicValidation(person);
        } catch (RuleException rve) {
            assertEquals(rve.getMessage(),
                    "date of birth can not be greater than the date of death");
        }
    } // End of executeIsDateOfBirthLessThanDeath

    // ====================================
    // IsDateOfBirthGreaterThanMarriageDate
    // ====================================
    // PER EMAIL FROM YI HE ON JANUARY 10, 2005 ...
    // The Marriage Date is in the spouse role. To get to it, we would get
    // the veteran's beneficiary role, and then get the Spouse role related in
    // this relationship from the beneficiary role. The relationship between
    // the roles (ie. the way to link spouses and dependents to a veteran)
    // needs to be put into place, it's on the issue/to do list.
    // CAN'T BE COMPLETED AT THIS TIME
    //   TODO: NO CONNECTION FROM PERSON TO MARRIAGE INFO YET
    //		   ASSUME THAT MARRIAGE DATE IS NULL UNTIL ASSOCIATION WORKS
    public void testIsDateOfBirthGreaterThanMarriageDate() throws Exception {
        Person person = this.buildPerson();
        // Set Date of Birth
        BirthRecord br = new BirthRecord();
        ImpreciseDate dobid = ImpreciseDateUtils.createImpreciseDate(1954, 5, 6);
        br.setBirthDate(dobid);
        person.setBirthRecord(br);
        // Set Marriage Date
        //Spouse s = new Spouse();
        //Date sDt = null;
        //s.setMarriageDate(sDt);

        try {
            this.executeDemographicValidation(person);
        } catch (Exception ex) {
            assertEquals(ex.getMessage(),
                    "date of birth can not be greater than marriage date");
        }
    } // End of executeIsDateOfBirthLessThanMarriageDate

    // =====================
    // IsDateOfBirthInFuture
    // =====================
    public void testIsDateOfBirthInFuture() throws Exception {
        Person person = this.buildPerson();
        // Set Date of Birth
        BirthRecord br = new BirthRecord();
        ImpreciseDate DOBid = ImpreciseDateUtils.createImpreciseDate(2006, 5, 6);
        br.setBirthDate(DOBid);
        person.setBirthRecord(br);
        try {
            this.executeDemographicValidation(person);
        } catch (Exception ex) {
            assertEquals(ex.getMessage(),
                    "date of birth can not be in the future");
        }
    } // End of executeIsDateOfBirthInFuture

    // ====================================
    // IsDateOfDeathGreaterThanDateReported
    // ====================================
    public void testIsDateOfDeathGreaterThanDateReported() throws Exception {
        Person person = this.buildPerson();
        // Set Date of Death
        DeathRecord dr = new DeathRecord();
        ImpreciseDate DODid = ImpreciseDateUtils.createImpreciseDate(2003, 5, 7);
        dr.setDeathDate(DODid);
        // Set DOD Report Date
        Date DODrptid = new SimpleDateFormat("MM/dd/yyyy").parse("07/05/2002");
        dr.setDeathReportDate(DODrptid);
        person.setDeathRecord(dr);

        try {
            this.executeDemographicValidation(person);
        } catch (Exception ex) {
            assertEquals(ex.getMessage(),
                    "date of death can not be greater than date reported");
        }
    } // End of executeIsDateOfDeathGreaterThanDateReported

    // =====================
    // IsDateOfDeathInFuture
    // =====================
    public void testIsDateOfDeathInFuture() throws Exception {
        Person person = this.buildPerson();
        // Set Date of Death
        DeathRecord dr = new DeathRecord();
        ImpreciseDate DODid = ImpreciseDateUtils.createImpreciseDate(2006, 5, 7);
        dr.setDeathDate(DODid);
        person.setDeathRecord(dr);

        try {
            this.executeDemographicValidation(person);
        } catch (Exception ex) {
            assertEquals(ex.getMessage(),
                    "date of death can not be in the future");
        }
    } // End of executeIsDateOfDeathInFuture

    //	 ==============================================
    //	 IsDependentDateOfBirthGreaterThanEffectiveDate
    //	 ==============================================
    //   TODO: NO CONNECTION FROM PERSON TO DEPENDENT INFO YET
    //		   ASSUME THAT DEPENDENT DATE IS NULL UNTIL ASSOCIATION WORKS
    public void testIsDependentDateOfBirthGreaterThanEffectiveDate()
            throws Exception {
        Person person = this.buildPerson();
        // Set Dependent Date of Birth
        //BirthRecord br = new BirthRecord();
        //ImpreciseDate DOBid = new ImpreciseDate("20040507");
        //br.setBirthDate(DOBid);
        //person.setBirthRecord(br);
        // Set Effective Date

        try {
            this.executeDemographicValidation(person);
        } catch (Exception ex) {
            assertEquals(ex.getMessage(),
                    "date of birth must be less than child effective date");
        }
    } // End of executeIsDependentDateOfBirthGreaterThanEffectiveDate

    //	 ==============================
    //	 IsDependentDateOfBirthInFuture
    //	 ==============================
    //   TODO: NO CONNECTION FROM PERSON TO DEPENDENT INFO YET
    // 		   ASSUME THAT DEPENDENT DATE IS NULL UNTIL ASSOCIATION WORKS
    public void testIsDependentDateOfBirthInFuture() throws Exception {
        Person person = this.buildPerson();

        try {
            this.executeDemographicValidation(person);
        } catch (Exception ex) {
            assertEquals(ex.getMessage(),
                    "date of birth cannot be in the future");
        }
    } // End of executeIsDependentDateOfBirthInFuture

    //	 ==================================
    //	 IsMarriageDateGreaterThanDeathDate
    //	 ==================================
    //	 PER EMAIL FROM YI HE ON JANUARY 10, 2005 ...
    //	 The Marriage Date is in the spouse role. To get to it, we would get
    //	 the veteran's beneficiary role, and then get the Spouse role related in
    //	 this relationship from the beneficiary role. The relationship between
    //	 the roles (ie. the way to link spouses and dependents to a veteran)
    //	 needs to be put into place, it's on the issue/to do list.
    //	 CAN'T BE COMPLETED AT THIS TIME
    //	 TODO: NO CONNECTION BETWEEN PERSON AND MARRIAGE INFO YET
    //		   ASSUME THAT MARRIAGE DATE IS NULL UNTIL ASSOCIATION WORKS
    public void testIsMarriageDateGreaterThanDeathDate() throws Exception {
        Person person = this.buildPerson();
        // Set Date of Death
        DeathRecord dr = new DeathRecord();
        ImpreciseDate dodid = ImpreciseDateUtils.createImpreciseDate(2003, 5, 7);
        dr.setDeathDate(dodid);
        person.setDeathRecord(dr);

        try {
            this.executeDemographicValidation(person);
        } catch (Exception ex) {
            assertEquals(ex.getMessage(),
                    "date of marriage can not be greater than date of death");
        }
    } // End of executeIsMarriageDateGreaterThanDeathDate

    private void executeDemographicValidation(Person person) throws Exception {
        PersonInputData data = new PersonInputData(person, true);
        RuleParameters ruleParameters = this
                .getDemographicValidationRuleParameters();
        this.getRuleFlowService().execute(ruleParameters, data);
    }

    /**
     * @return Returns the demographicValidationRuleParameters.
     */
    private RuleParameters getDemographicValidationRuleParameters()
            throws ServiceException {
        return (RuleParameters) applicationContext.getBean("demographicValidationRuleParameters");
    }
}