package gov.va.med.esr.service.impl;

// Java Classes
import gov.va.med.esr.common.model.ee.HealthBenefitProfile;
import gov.va.med.esr.common.model.lookup.VAFacility;
import gov.va.med.esr.common.model.party.Address;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.person.id.PersonEntityKey;
import gov.va.med.esr.common.persistent.history.HistoryDAO;
import gov.va.med.esr.common.rule.service.EligibilityEnrollmentRuleService;
import gov.va.med.esr.service.HealthBenefitPlanService;
import gov.va.med.fw.model.AbstractEntity;
import gov.va.med.fw.model.EntityKey;
import gov.va.med.fw.persistent.DAOException;
import gov.va.med.fw.service.ServiceException;

import java.util.Set;

import org.apache.commons.lang.Validate;


public class HealthBenefitPlanServiceImpl extends AbstractRuleAwareServiceImpl implements HealthBenefitPlanService
{
	
	
    /**
     * An instance of serialVersionUID
     */
	private static final long serialVersionUID = 4204326579293875215L;

     /**
     * HistoryDAO that retrieves the address history data.
     */
    private HistoryDAO healthBenefitPlanHistoryDAO = null;
 

    /**
     * Default constructor.
     */
    public HealthBenefitPlanServiceImpl()
    {
        super();
    }

    /**
     * @see gov.va.med.esr.service.HealthBenefitPlanService#getHealthBenefitPlanHistoryChangeTimes(gov.va.med.fw.model.EntityKey)
     */
    public Set getHealthBenefitPlanHistoryChangeTimes(EntityKey personID) throws ServiceException
    {
        try
        {
            return healthBenefitPlanHistoryDAO.getHistoryChangeTimes(personID);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    /**
     * @see gov.va.med.esr.service.DemographicService#getHealthBenefitPlanHistoryByChangeTime(ChangeEvent)
     */
    public HistoricalInfo getHealthBenefitPlanHistoryByChangeTime(ChangeEvent event) throws ServiceException
    {
        try
        {
            return healthBenefitPlanHistoryDAO.getHistoryByChangeTime(event);
        }
        catch (DAOException e)
        {
            throw new ServiceException(e.getMessage(), e);
        }
    }

     /**
     * @see gov.va.med.esr.service.HealthBenefitPlanService#updateHealthBenefitPlan(gov.va.med.esr.common.model.person.Person)
     */
    public Person updateHealthBenefitPlan(Person incoming) throws ServiceException
    {
        Validate.notNull(incoming, "A veteran must not be null");

        Person result = this.getPersonService().getPerson(
            (PersonEntityKey)incoming.getEntityKey());
        Validate.notNull(result, "A veteran on file must not be null.");

        // Ensure that something changed on the incoming entity as compared to the onFile
        // entity
        ensureEntityChanged(incoming, result);

        // Validate that an enrollment record exists for the on-file Person
        // Question -- is this line necessary??
        validateEnrollmentDetermination(result);

        // Step 1: Update a veteran on file with health benfit plan information.
        this.getEnrollmentRuleService().manageHealthBenefitProfile(incoming, result);

        // Step 2: Send update Z11
        this.getEventRuleService().manageMessageEvents(result);

        // Step 3: Save the updated person
        result = this.getPersonService().save(result);

        return result;
    }

    /**
     * @see gov.va.med.esr.service.HealthBenefitPlanService#processHealthBenefitPlan(gov.va.med.esr.common.model.lookup.VAFacility,
     *gov.va.med.esr.common.model.person.Person)
     */
    public Person processHealthBenefitProfile(Person incoming) throws ServiceException
    {
        Validate.notNull(incoming, "A veteran must not be null");

        HealthBenefitProfile clonedHBP = (HealthBenefitProfile)incoming.getHealthBenefitProfile().clone();
        
        // This call should always return a person since a person must have
        // already been querried through a search to by the messaging.
        Person result = this.getPersonService().getPerson((PersonEntityKey)incoming.getEntityKey());

        // Step 1: Update a veteran on file and determine the HBP plans
        this.getEnrollmentRuleService().processHealthBenefitProfile(incoming, result);
        
        // Step 2: Send update Z11 IF HBP data changed
        if (!AbstractEntity.matchesDomainValues(clonedHBP, result.getHealthBenefitProfile())) {
        	this.getEventRuleService().manageMessageEvents(result);
        }
        
        // Step 3: Save the updated person
        result = this.getPersonService().save(result);

        return result;
    }
     
    public HistoryDAO getHealthBenefitPlanHistoryDAO()
    {
        return healthBenefitPlanHistoryDAO;
    }

    public void setHealthBenefitPlanHistoryDAO(HistoryDAO healthBenefitPlanHistoryDAO)
    {
        this.healthBenefitPlanHistoryDAO = healthBenefitPlanHistoryDAO;
    }

}
