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

// Java classes
import java.util.Date;

// Third Party
import org.apache.commons.lang.Validate;

// Framework classes
import gov.va.med.fw.rule.RuleException;
import gov.va.med.fw.service.ServiceException;

// 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.EligibilityVerification;
import gov.va.med.esr.common.model.ee.VerificationInfo;
import gov.va.med.esr.common.model.lookup.EligibilityVerificationSource;
import gov.va.med.esr.common.model.lookup.EligibilityStatus;
import gov.va.med.esr.common.model.lookup.AACIndicator;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.rule.EligibilityVerificationInput;
import gov.va.med.esr.common.rule.data.EventInputData;
import gov.va.med.esr.common.rule.service.MergeRuleService;

/**
 * This class deals with any business related to verifying a veteran's eligibility. Please
 * note that the resultPerson should be used for updating.
 * 
 * @author Carlos Ruiz
 * @version 1.0
 */
public class EligibilityVerificationInputParameter extends BaseParameter implements
      EligibilityVerificationInput {

   private static final long serialVersionUID = -5394358886026071563L;

   private String messageType = null;

   private String aacEntitlementCode = null;
   
   private String unsolicitedType = null;

   private String queryStatus = null;

   private String siteNumber = null;
   
   /**
    *  
    */
   public EligibilityVerificationInputParameter() {
      super();
   }

   /**
    * @see gov.va.med.esr.common.rule.parameter.EligibilityVerificationInput#setAACIndicator(java.lang.String)
    */
   public void setQueryStatus(String indicator) throws RuleException {
      try {
         Person resultPerson = this.getResultPerson();
         this.getHelperService().setAACIndicator(indicator, resultPerson);
      }
      catch( ServiceException e ) {
         throw new RuleException("Failed to set AAC Indicator", e);
      }
   }

   /**
    * @see gov.va.med.esr.common.rule.parameter.EligibilityVerificationInput#getQueryStatus()
    */
   public String getQueryStatus() {
      if( this.queryStatus == null ) {
         if( this.getRuleDataAware() instanceof EventInputData ) {
            this.queryStatus = this.getQueryStatus( this.getIncomingPerson() );
         }
         else {
            this.queryStatus = ( this.getAacInfo() != null ) ? this.getAacInfo()
                  .getTextMessage() : null;
         }
      }
      return this.queryStatus;
   }
   
   /**
    * @see gov.va.med.esr.common.rule.EligibilityVerificationInput#getVeteranQueryStatus()
    */
   public String getQueryStatus( Person person ) {
      EligibilityVerification ev = person != null ? person.getEligibilityVerification() : null;
      AACIndicator indicator = ev != null ? ev.getAacIndicator() : null;
      return indicator != null ? indicator.getCode() : null;
   }

   /**
    * @see gov.va.med.esr.common.rule.parameter.EligibilityVerificationInput#getEligibilityStatus()
    */
   public String getEligibilityStatus() throws RuleException {
      return this.getEligibilityStatus( this.getIncomingPerson() );
   }
   
   public String getEligibilityStatus(Person person) throws RuleException {

      String code = null;
      try {
         EligibilityStatus status = this.getHelperService().getEligibilityStatus(person);
         code = status != null ? status.getCode() : null; 
      }
      catch( ServiceException e ) {
         throw new RuleException("Failed to get eligibility status code", e);
      }
      return code;
   }

   /**
    * @see gov.va.med.esr.common.rule.parameter.EligibilityVerificationInput#setEligibilityVerificationSource(java.lang.String)
    */
   public void setEligibilityVerificationSource(String code) throws RuleException {
      try {
         this.getHelperService().setVerificationSource(code, this.getResultPerson());
      }
      catch( ServiceException e ) {
         throw new RuleException("Failed to set verification source for code: " + code, e);
      }
   }

   /**
    * @see gov.va.med.esr.common.rule.parameter.EligibilityVerificationInput#setEligibilityStatus(java.lang.String)
    */
   public void setEligibilityStatus(String status) throws RuleException {
      try {
         this.getHelperService().setEligibilityStatus(status, this.getResultPerson());
      }
      catch( ServiceException e ) {
         throw new RuleException("Failed to set eligiblity status", e);
      }
   }

   /**
    * @see gov.va.med.esr.common.rule.parameter.EligibilityVerificationInput#setEligibilityStatusDate(java.util.Date)
    */
   public void setEligibilityStatusDate(ImpreciseDate date) {
      Person resultPerson = this.getResultPerson();
      EligibilityVerification eligibilityVerification = resultPerson
            .getEligibilityVerification();
      if( eligibilityVerification == null ) {
         eligibilityVerification = new EligibilityVerification();
         resultPerson.setEligibilityVerification(eligibilityVerification);
      }
      resultPerson.getEligibilityVerification().setEligibilityStatusDate(date);
   }

   /**
    * Convenience method for ILOG
    * 
    * @see gov.va.med.esr.common.rule.EligibilityVerificationInput#setEligibilityStatusDate(java.util.Date)
    */
   public void setEligibilityStatusDate(Date date) {
	   if( date != null ) {
		   // this date should not include time
		   ImpreciseDate idate = ImpreciseDateUtils.createImpreciseDateWithoutTime(date); 
		   this.setEligibilityStatusDate(idate);
	   }
      else {
         Person resultPerson = this.getResultPerson();
         EligibilityVerification eligibilityVerification = resultPerson
               .getEligibilityVerification();
         if( eligibilityVerification == null ) {
            eligibilityVerification = new EligibilityVerification();
            resultPerson.setEligibilityVerification(eligibilityVerification);
         }
         resultPerson.getEligibilityVerification().setEligibilityStatusDate(null);
      }
   }

   /**
    * @see gov.va.med.esr.common.rule.parameter.EligibilityVerificationInput#getMessageType()
    */
   public String getMessageType() {
      if( this.messageType == null ) {
         VerificationInfo info = this.getAacInfo();
         this.messageType = info != null ? info.getMessageType() : null;
      }
      return this.messageType;
   }

   /**
    * @see gov.va.med.esr.common.rule.parameter.EligibilityVerificationInput#getTriggerEnrollmentProcess()
    */
   public boolean getTriggerEnrollmentProcess() {
      VerificationInfo info = this.getAacInfo();
      return info != null ? info.isTriggerEnrollmentProcess() : false;
   }

   public boolean hasQualifyingMse() {
	   VerificationInfo info = this.getAacInfo();
	   return info != null ? info.hasQualifyingMse() : false;
   }

   public ImpreciseDate getMsdsMessageDate() {
	   VerificationInfo info = this.getAacInfo();
	   return (info != null && info.getMsdsMessageDate() != null) ? info.getMsdsMessageDate() : ImpreciseDateUtils.createImpreciseDateWithoutTime(this.getCurrentDate());
   }

   /**
    * @see gov.va.med.esr.common.rule.parameter.EligibilityVerificationInput#setTriggeredEnrollmentProcess(boolean)
    */
   public void setTriggeredEnrollmentProcess(boolean flag) {
	   VerificationInfo info = this.getAacInfo();
	   if( info != null ) {
		   info.setTriggerEnrollmentProcess(flag);
	   }
   }

   /**
    * @see gov.va.med.esr.common.rule.parameter.EligibilityVerificationInput#getAACEntitlementCode()
    */
   public String getAACEntitlementCode() {
      if( this.aacEntitlementCode == null ) {
         VerificationInfo info = this.getAacInfo();
         this.aacEntitlementCode = info != null ? info.getEntitlementCode() : null;
      }
      return this.aacEntitlementCode;
   }


   public String getUnsolicitedType() {
      if( this.unsolicitedType == null ) {
         VerificationInfo info = this.getAacInfo();
         this.unsolicitedType = info != null ? info.getUnsolicitedType() : null;
      }
      return this.unsolicitedType;
   }
   
   /**
    * @see gov.va.med.esr.common.rule.EligibilityVerificationInput#setEligibilityVerificationFacility(String)
    */
   public void setEligibilityVerificationFacility(String vaFacility)
         throws RuleException {
      try {
         this.getHelperService().setVerificationFacility(vaFacility,
               this.getResultPerson());
      }
      catch( ServiceException e ) {
         throw new RuleException("Failed to set a verification facility", e);
      }
   }

   /**
    * @see gov.va.med.esr.common.rule.EligibilityVerificationInput#setEligibilityVerificationMethod(java.lang.String)
    */
   public void setEligibilityVerificationMethod(String method) throws RuleException {
      try {
         this.getHelperService().setVerificationMethod(method, this.getResultPerson());
      }
      catch( ServiceException e ) {
         throw new RuleException("Failed to set eligbility source of verification", e);
      }
   }

   /**
    * @see gov.va.med.esr.common.rule.EligibilityVerificationInput#getEligibilityVerificationSource()
    */
   public String getEligibilityVerificationSource() throws RuleException {
      return getEligibilityVerificationSource( this.getIncomingPerson() );
   }
   
   /**
    * @see gov.va.med.esr.common.rule.EligibilityVerificationInput#getEligibilityVerificationSource(gov.va.med.esr.common.model.person.Person)
    */
   public String getEligibilityVerificationSource(Person person) throws RuleException {

      EligibilityVerification verification = person != null ? person.getEligibilityVerification() : null;
      String code = null;
      if( verification != null ) {
         EligibilityVerificationSource source = verification.getVerificationSource();
         code = ( source != null ) ? source.getCode() : null;
      }
      return code;
   }

   /**
    * @see gov.va.med.esr.common.rule.EligibilityVerificationInput#getEligibilityStatusDate()
    */
   public ImpreciseDate getEligibilityStatusDate() {
      return this.getEligibilityStatusDate( this.getIncomingPerson() );
   }

   /**
    * @see gov.va.med.esr.common.rule.EligibilityVerificationInput#getEligibilityStatusDate()
    */
   public ImpreciseDate getEligibilityStatusDate( Person person ) {
      EligibilityVerification verification = person != null ? person.getEligibilityVerification() : null;
      return verification != null ? verification.getEligibilityStatusDate() : null;
   }
   
   /**
    * @see gov.va.med.esr.common.rule.EligibilityVerificationInput#getEligibilityVerificationMethod()
    */
   public String getEligibilityVerificationMethod() {
      return this.getEligibilityVerificationMethod( this.getIncomingPerson() );
   }
   
   /**
    * @see gov.va.med.esr.common.rule.EligibilityVerificationInput#getEligibilityVerificationMethod(gov.va.med.esr.common.model.person.Person)
    */
   public String getEligibilityVerificationMethod(Person person) {
      EligibilityVerification verification = person != null ? person.getEligibilityVerification() : null;
      return ( verification != null ) ? verification.getVerificationMethod() : null;
   }

   public String getSiteNumber() throws RuleException {
      if( siteNumber == null ) {
         Person siteData = this.getMostRecentSiteData();
         siteNumber = siteData != null ? siteData.getSendingFacility() : null;
         
         // If site number is NULL, this means that this is the very first time
         // ESR receives a Z07 from a site so at this point a message log entry 
         // is not yet created in a HL7_TRANSACTION_LOG table for this Z07 record
         // In this case, use a site number that is passed into in VerificationInfo 
         if( siteNumber == null ) {
            VerificationInfo info = this.getAacInfo();
            this.siteNumber = info != null ? info.getSiteNumber() : null;
         }
      }
      return siteNumber;
   }

   /**
    * @see gov.va.med.esr.common.rule.EligibilityVerificationInput#acceptSiteEligibilityData(gov.va.med.esr.common.model.person.Person, gov.va.med.esr.common.model.person.Person)
    */
   public void acceptSiteEligibilityData(Person incoming, Person onFile) throws RuleException {
       Validate.notNull( incoming, "An incoming person must not be NULL");
       Validate.notNull( onFile, "An on file person must not be NULL");
       
       // Get a merge rule service
       MergeRuleService service = this.getMergeRuleService();
       
       try {
           onFile.setVeteran(incoming.getVeteran());
           
           // Merge service connection award & rated disabilities
           service.mergeServiceConnectionAward(incoming.getServiceConnectionAward(), onFile);
           
           // Merge monetary benefit - 
           service.mergeMonetaryBenefitAward(incoming.getMonetaryBenefitAward(), onFile);
           
           // Merge eligibility verification
           service.mergeEligibilityVerification(incoming.getEligibilityVerification(), onFile);
       }
       catch (ServiceException e) {
           throw new RuleException("Failed to accept data from VBA message", e);
       }
       
       
   }

   /**
    * @see gov.va.med.esr.common.rule.EligibilityVerificationInput#acceptEligibilityVerificationData(gov.va.med.esr.common.model.person.Person, gov.va.med.esr.common.model.person.Person)
    */
   public void acceptEligibilityVerificationData(Person incoming, Person onFile) throws RuleException {
       Validate.notNull( incoming, "An incoming person must not be NULL");
       Validate.notNull( onFile, "An on file person must not be NULL");
       
       // Get a merge rule service
       MergeRuleService service = this.getMergeRuleService();
       
       try {
           onFile.setVeteran(incoming.getVeteran());
           
           // Merge eligibility verification
           service.mergeEligibilityVerification(incoming.getEligibilityVerification(), onFile);
       }
       catch (ServiceException e) {
           throw new RuleException("Failed to accept data from VBA message", e);
       }
   }


}