/********************************************************************
 * Copyright © 2004 EDS. All rights reserved
 ********************************************************************/
//Package
package gov.va.med.esr.messaging.builder.message;


import java.text.SimpleDateFormat;
import java.util.Iterator;
import java.util.Set;

import gov.va.med.fw.hl7.Segment;
import gov.va.med.fw.hl7.builder.HL7MetaData;
import gov.va.med.fw.hl7.constants.SegmentConstants;
import gov.va.med.fw.hl7.segment.ZPD;
import gov.va.med.fw.util.StringUtils;
import gov.va.med.fw.util.builder.Builder;
import gov.va.med.fw.util.builder.BuilderException;

import gov.va.med.esr.common.model.ee.Eligibility;
import gov.va.med.esr.common.model.ee.EnrollmentDetermination;
import gov.va.med.esr.common.model.ee.ReceivedEligibility;
import gov.va.med.esr.common.model.financials.IncomeTest;
import gov.va.med.esr.common.model.financials.IncomeTestStatus;
import gov.va.med.esr.common.model.lookup.EligibilityType;
import gov.va.med.esr.common.model.lookup.EmergencyResponse;
import gov.va.med.esr.common.model.lookup.IncomeTestType;
import gov.va.med.esr.common.model.lookup.PseudoSSNReason;
import gov.va.med.esr.common.model.person.EmergencyResponseIndicator;
import gov.va.med.esr.common.model.person.Person;

/**
 * Class to build the ZPD segment.
 * 
 * @author Alex Yoon
 * @version 1.0
 */
public class ZPDBuilder extends AbstractZPDBuilder
{

    /**
    * An instance of serialVersionUID 
    */
   private static final long serialVersionUID = -8482115495841076845L;
   private Builder alliedCountryBuilder;
    private Builder federalAgencyBuilder;
    
	/**
     * Default contructor.
     */
    public ZPDBuilder()
    {
        super();
    }
    
    

    /**
     * @return Returns the alliedCountryBuilder.
     */
    public Builder getAlliedCountryBuilder()
    {
        return alliedCountryBuilder;
    }
    /**
     * @param alliedCountryBuilder The alliedCountryBuilder to set.
     */
    public void setAlliedCountryBuilder(Builder alliedCountryBuilder)
    {
        this.alliedCountryBuilder = alliedCountryBuilder;
    }
    /**
     * @return Returns the federalAgencyBuilder.
     */
    public Builder getFederalAgencyBuilder()
    {
        return federalAgencyBuilder;
    }
    /**
     * @param federalAgencyBuilder The federalAgencyBuilder to set.
     */
    public void setFederalAgencyBuilder(Builder federalAgencyBuilder)
    {
        this.federalAgencyBuilder = federalAgencyBuilder;
    }
    /**
     * Method to build the ZPD segment.
     * 
     * @param metaData
     *            The parameter object used to build the a ZPD segment.
     * @return The ZPD segment.
     */
    public Object build(HL7MetaData metaData) throws BuilderException
    {
        if ((metaData == null) || (metaData.getEntity() == null)
                || !(metaData.getEntity() instanceof Person))
        {
            throw new BuilderException(
                    "Invalid input parameter to build a segment");
        }

        ZPD segment = new ZPD();        
        setDefaultValues(segment);
        
        Person person = (Person) metaData.getEntity();

        try
        {
        	segment.setSetID("1");
        	this.setMedicaid(person, segment);
        	
        	
        	//Sequence 30 Spinal Cord Injury
        	if ( person.getSpinalCordInjury() != null)
        	{
        		segment.setSpinalCordInjury(person.getSpinalCordInjury().getSpinalCordInjuryType().getCode());
        	}

        	
        	IncomeTest currentIncomeTest = getHelperService().getCurrentIncomeTest(person);
        	if (currentIncomeTest != null)
            {
                IncomeTestStatus status = currentIncomeTest
                        .getIncomeTestStatusOfType(IncomeTestType.CODE_CO_PAY_EXEMPTION_TEST);
                if (status != null)
                {
                    segment.setMedicationCopayExemptionStatus(super.build(status.getStatus()));
                }
            }
        	
        	PseudoSSNReason reason = person.getOfficialSsn() != null ? person.getOfficialSsn().getPseudoSSNReason() : null;
        	segment.setPseudoSSNReason(reason != null ? reason.getCode() : null);
        	
        	EmergencyResponseIndicator indicator = EmergencyResponseIndicator.getEmergencyResponseIndicatorOfType(person.getEmergencyResponseIndicators(), EmergencyResponse.CODE_KATRINA.getCode());
        	
        	//Send empty string if null
        	segment.setEmergencyResponseType(indicator == null ? StringUtils.EMPTY : indicator.getEmergencyResponse().getCode());
        	 
        	//Set Allied Country/Fed agency.
            //Work around to ensure Segment getSequenceValue method to return empty string to VistA
            //REEG_00004330 - Change is to remove this Other Federal Agency value from VistA by sending empty string        	
			 segment.setAlliedCountryOrFederalAgency(getValueToForceSegmentFieldToEmpty(getAlliedCountryOrFedAgencyCode(person)));
             
//             if(person.getPreferredLanguage() != null) {
//                 segment.setPreferredLanguageIndicator(person.getPreferredLanguage().getLanguage().getCode1());
//                 SimpleDateFormat sdf = new SimpleDateFormat("yyyymmdd");
//                 segment.setPreferredLanguageDateTime(sdf.format(person.getPreferredLanguage().getLanguageEntryDate()));
//             }
             
        } catch (Exception e)
        {
            throw new BuilderException(
                    "Failed to build ZPD Segment due to an exception ", e);
        }

        return segment;
    } 
    
    //Work around to ensure Segment getSequenceValue method to return empty string to VistA
    //REEG_00004330 - Change is to remove this Other Federal Agency value from VistA by sending empty string
    private String getValueToForceSegmentFieldToEmpty(String value) {
    	return (value == null ? Segment.NULL : value);
    }
    
    protected void setDefaultValues(Segment segment) 
    {
        ZPD zpd = (ZPD) segment;
        zpd.setEligibleForMedicaid(SegmentConstants.DEFAULT_VALUE);
        zpd.setPseudoSSNReason(SegmentConstants.DEFAULT_VALUE);
        //Do not send double quotes for seq 35 and 40
    }
    
	
	/**
	 * Defect REEG_00005494 
	 * 1. Get the Primary EC - if it is either Allied or Other, check the SITE_RECEIVED_ELIGIBILTY and match against the eligiblity type id 
	 * and send either Allied country or other federal agency in the ZPD 
	 * 
	 * 2. If there is a primary Veteran EC and an Allied secondary - get the allied country from site received eligibility.

	 * 3. If there a primary veteran EC and an other federal agency secondary - get the other federal agency from site received eligibility

	 * 4. If there is a primary and a secondary of Other federal agency AND Allied vet - get the ALLIED VET from site received eligiblity (using the logic of the order of preference of non vet codes assignment).

	 * 5. If there is a primary Vet EC and a secondary of allied AND other federal agency - get the ALLIED VET from site received eligiblity (using the logic of the order of preference of non vet code assignment). 
	 * @throws BuilderException 
	 */
	private String getAlliedCountryOrFedAgencyCode(Person person) throws BuilderException
	{
		String alliedCountryOrFedAgencyCode = null;
		
		EnrollmentDetermination enrollmentDetermination = person.getEnrollmentDetermination();
		
		if(enrollmentDetermination != null )
		{
			Eligibility primaryEligibility = enrollmentDetermination.getPrimaryEligibility();
			
			if(primaryEligibility != null)
			{
				//If Primary Eligibility is Allied or Federal Agency, get the code from received eligibilities
				if (primaryEligibility.getType().getCode().equals(EligibilityType.ALLIED_VETERAN.getCode()))
				{
					alliedCountryOrFedAgencyCode = getAlliedCountryFromReceivedEligibilities(person);

				}else if (primaryEligibility.getType().getCode().equals(EligibilityType.OTHER_FEDERAL_AGENCY.getCode()))
				{
					alliedCountryOrFedAgencyCode = getFederalAgencyFromReceivedEligibilities(person);
					
				}else {
					
					Set secondaryEligibilities = enrollmentDetermination.getSecondaryEligibilities();
					//If primary is not allied or federal and secondary contains allied, always get the allied 
					if(secondaryEligibilities != null)
					{
						if(hasTypeInSecondaryEligibilities(secondaryEligibilities, EligibilityType.ALLIED_VETERAN))
						{
							alliedCountryOrFedAgencyCode = getAlliedCountryFromReceivedEligibilities(person);
							
						}else if(hasTypeInSecondaryEligibilities(secondaryEligibilities, EligibilityType.OTHER_FEDERAL_AGENCY))
						{
							//Get the federal agency if it exists.
							alliedCountryOrFedAgencyCode = getFederalAgencyFromReceivedEligibilities(person);
						}
					}
				}
			}
				
		}
		
		return alliedCountryOrFedAgencyCode;
	}

	private String getAlliedCountryFromReceivedEligibilities(Person person) throws BuilderException
	{
		String alliedCountry = null;
		
		ReceivedEligibility receivedEligibility = person.getReceivedPrimaryEligibility();
		if(receivedEligibility != null && receivedEligibility.getAlliedCountry() != null)
		{
			alliedCountry = super.build(alliedCountryBuilder, receivedEligibility.getAlliedCountry()); 
		}
		if(alliedCountry == null)
		{
			Set receivedEligibilities = person.getReceivedSecondaryEligibilities();
			
			if(receivedEligibilities != null)
			{
				for (Iterator iter = receivedEligibilities.iterator(); iter
						.hasNext();) {
					ReceivedEligibility receivedSecEligibility = (ReceivedEligibility) iter.next();
					
					if(receivedSecEligibility.getAlliedCountry() != null)
					{
						alliedCountry = super.build(alliedCountryBuilder, 
								receivedSecEligibility.getAlliedCountry());
					}							
				}
			}
		}
		
		return alliedCountry;
	}
	
	private String getFederalAgencyFromReceivedEligibilities(Person person) throws BuilderException
	{
		String federalAgency = null;
		
		ReceivedEligibility receivedEligibility = person.getReceivedPrimaryEligibility();
		if(receivedEligibility != null && receivedEligibility.getOtherFederalAgency() != null)
		{
			federalAgency = super.build(federalAgencyBuilder, 
					receivedEligibility.getOtherFederalAgency());
		}
		if(federalAgency == null)
		{
			Set receivedEligibilities = person.getReceivedSecondaryEligibilities();
			
			if(receivedEligibilities != null)
			{
				for (Iterator iter = receivedEligibilities.iterator(); iter
						.hasNext();) {
					ReceivedEligibility receivedSecEligibility = (ReceivedEligibility) iter.next();
					
					if(receivedSecEligibility.getOtherFederalAgency() != null)
					{
						federalAgency = super.build(federalAgencyBuilder, 
								receivedSecEligibility.getOtherFederalAgency());
					}							
				}
			}
		}
		
		return federalAgency;
	}	
	
	private boolean hasTypeInSecondaryEligibilities(Set secondaryEligibilities, EligibilityType.Code type)
	{
		
		boolean hasAlliedCountryInSecondaryEligibilities = false;
		
		if(secondaryEligibilities != null)
		{
			for (Iterator iter = secondaryEligibilities.iterator(); iter
					.hasNext();) {
				Eligibility secEligibility = (Eligibility) iter.next();
				
				if(secEligibility.getType().getCode().equals(type.getCode()))
				{
					hasAlliedCountryInSecondaryEligibilities = true;
					break;
				}
			}
		}
		
		return hasAlliedCountryInSecondaryEligibilities;
	}	
}