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

// Java classes
import java.util.Iterator;
import java.util.Set;

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

// Framework classes
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.validation.ValidationMessages;
import gov.va.med.fw.validation.ValidationServiceException;

// EDB classes
import gov.va.med.esr.common.clock.Clock;
import gov.va.med.esr.common.model.ee.PurpleHeart;
import gov.va.med.esr.common.model.ee.PurpleHeartDocument;
import gov.va.med.esr.common.model.ee.VerificationInfo;
import gov.va.med.esr.common.model.lookup.VAFacility;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.rule.data.PersonInputData;
import gov.va.med.esr.common.rule.service.PurpleHeartRuleService;

/**
 * Project: Common
 * 
 * @author DNS   LEV
 * @version 1.0
 */
public class PurpleHeartRuleServiceImpl extends AbstractRuleValidationServiceAwareImpl
      implements PurpleHeartRuleService {
   /**
    * An instance of serialVersionUID
    */
   private static final long serialVersionUID = -8424238104146792581L;

   private String purpleHeartRuleParameters = null;

   private String managePurpleHeartRuleParameters = null;

   public PurpleHeartRuleServiceImpl() {
      super();
   }

   /**
    * Process the Purple Heart data for the UI clent.
    * 
    * @param incoming
    *           the updated incoming person
    * @param onFile
    *           the onfile person
    * @throws ServiceException
    */
   public Person managePurpleHeart(Person incoming, Person onFile)
         throws ServiceException {
      return doProcessPurpleHeart(incoming, onFile, null, UI, null);
   }

   /**
    * @see gov.va.med.esr.common.rule.service.PurpleHeartRuleService#managePurpleHeart(gov.va.med.esr.common.model.person.Person,
    *      gov.va.med.esr.common.model.person.Person,
    *      gov.va.med.esr.common.clock.Clock.Type)
    */
   public Person managePurpleHeart(Person incoming, Person onFile, Clock.Type clockType)
         throws ServiceException {
      return doProcessPurpleHeart(incoming, onFile, null, UI, clockType);
   }

   /**
    * Process the Purple Heart data for message cleant.
    * 
    * @param incoming
    *           the updated incoming person
    * @param onFile
    *           the onfile person
    * @throws ServiceException
    */
   public Person processPurpleHeart(Person incoming, Person onFile,
         VerificationInfo verificationInfo) throws ServiceException {
      return doProcessPurpleHeart(incoming, onFile, verificationInfo, null, null,null);
   }
   public Person processPurpleHeart(Person incoming, Person onFile,
           VerificationInfo verificationInfo,VAFacility sendingFacility) throws ServiceException {
        return doProcessPurpleHeart(incoming, onFile, verificationInfo, null, null,sendingFacility);
     }
   
   public Person processPurpleHeart(Person incoming, Person onFile,
           VerificationInfo verificationInfo,VAFacility sendingFacility, String caller) throws ServiceException {
        return doProcessPurpleHeart(incoming, onFile, verificationInfo, caller, null,sendingFacility);
     }
   
   public void processWorkflowPurpleHeart(PurpleHeart incoming, Person onFile)
         throws ServiceException {
      // TODO Auto-generated method stub

   }

   private Person doProcessPurpleHeart(Person incoming, Person onFile,
         VerificationInfo verificationInfo, String caller, Clock.Type clockType)
         throws ServiceException {
      Validate.notNull(onFile, "A veteran on file must not be null");
      Validate.notNull(incoming, "An incoming person must not be null");

      Person pristine = this.getPristinePerson(onFile);

      // Invoke process association rule flow
      if( UI.equals(caller) ) {
         validatePurpleHeart(incoming, true); // only validate UI
         // Execute manage purple heart rules
         PersonInputData data = new PersonInputData(incoming, onFile, pristine, true);
         data.setFiredClockType(clockType);
         invokeRuleFlow( this.getRuleParameters(getManagePurpleHeartRuleParameters()), data);
      }
      else {
         // Execute process purple heart rules
         invokeRuleFlow(this.getRuleParameters( getPurpleHeartRuleParameters() ), new PersonInputData(
                      incoming, onFile, pristine, false, verificationInfo));
         }

      // Return the updated person
      return onFile;
   }
   private Person doProcessPurpleHeart(Person incoming, Person onFile,
           VerificationInfo verificationInfo, String caller, Clock.Type clockType,VAFacility sendingFacility)
           throws ServiceException {
        Validate.notNull(onFile, "A veteran on file must not be null");
        Validate.notNull(incoming, "An incoming person must not be null");

        Person pristine = this.getPristinePerson(onFile);

        // Invoke process association rule flow
        if( UI.equals(caller) ) {
           validatePurpleHeart(incoming, true); // only validate UI
           // Execute manage purple heart rules
           PersonInputData data = new PersonInputData(incoming, onFile, pristine, true);
           data.setFiredClockType(clockType);
           invokeRuleFlow( this.getRuleParameters(getManagePurpleHeartRuleParameters()), data);
        }
        else {
           // Execute process purple hear if(sendingFacility !=null){
           invokeRuleFlow(this.getRuleParameters( getPurpleHeartRuleParameters() ), new PersonInputData(
                 incoming, onFile, pristine,sendingFacility,  verificationInfo));
           }

        // Return the updated person
        return onFile;
     }
   public String getPurpleHeartRuleParameters() {
      return purpleHeartRuleParameters;
   }

   public void setPurpleHeartRuleParameters(String purpleHeartRuleParameters) {
      this.purpleHeartRuleParameters = purpleHeartRuleParameters;
   }

   /**
    * @return Returns the managePurpleHeartRuleParameters.
    */
   public String getManagePurpleHeartRuleParameters() {
      return managePurpleHeartRuleParameters;
   }

   /**
    * @param managePurpleHeartRuleParameters
    *           The managePurpleHeartRuleParameters to set.
    */
   public void setManagePurpleHeartRuleParameters(String managePurpleHeartRuleParameters) {
      this.managePurpleHeartRuleParameters = managePurpleHeartRuleParameters;
   }

   public void afterPropertiesSet() throws Exception {
      super.afterPropertiesSet();
      Validate.notNull(this.purpleHeartRuleParameters,
            "purpleHeartRuleParameters property is required");
      Validate.notNull(this.managePurpleHeartRuleParameters,
            "managePurpleHeartRuleParameters property is required");
   }

   private void validatePurpleHeart(Person incoming, boolean isDataFromGUI)
         throws ServiceException {
      PurpleHeart ph = incoming.getPurpleHeart();
      Set docs = ph != null ? ph.getDocuments() : null;

      if( docs != null && docs.size() > 0 ) {
         for( Iterator i = docs.iterator(); i.hasNext(); ) {
            PurpleHeartDocument purpleHeartDocument = (PurpleHeartDocument)i.next();
            ValidationMessages messages = this.getRuleValidationService()
                  .validatePurpleHeartDocument(purpleHeartDocument, incoming,
                        isDataFromGUI);
            if( messages != null && !messages.isEmpty() ) {
               throw new ValidationServiceException(messages);
            }
         }
      }
   }
}