package gov.va.med.esr.messaging.builder.message;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import gov.va.med.esr.common.model.financials.FinancialStatement;
import gov.va.med.esr.common.model.financials.SpouseFinancials;
import gov.va.med.esr.common.model.person.Employment;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.service.trigger.PersonTriggerEvent;
import gov.va.med.fw.hl7.builder.HL7MetaData;
import gov.va.med.fw.hl7.segment.ZEM;
import gov.va.med.fw.util.builder.BuilderException;

public class ZEMBuilder extends AbstractSegmentBuilder {


	private static final long serialVersionUID = 9172875772520689779L;

    protected AddressElementFormatter addressFormatter; 
    
	public AddressElementFormatter getAddressFormatter() {
		return addressFormatter;
	}
	
	public void setAddressFormatter(AddressElementFormatter addressFormatter) {
		this.addressFormatter = addressFormatter;
	}
	
	/**
     * Method to build the ZEM segments.
     * 
     * @param metaData
     *            The parameter object used to build the a ZEM segment.
     * @return The ZEM segments.
     */
    public Object build(HL7MetaData metaData, PersonTriggerEvent triggerEvent)
            throws BuilderException
    {
        if ((metaData == null) || (metaData.getEntity() == null)
                || !(metaData.getEntity() instanceof Person)
                || triggerEvent == null)
        {
            throw new BuilderException(
                    "Invalid input parameter to build a segment");
        }

        List segments = new ArrayList();

        Person person = (Person) metaData.getEntity();
        try
        {
          // 1. Person Employment
          // CCR 9988 -- Z05 requires at least 1 ZEM even if no employment data is present
        	Employment employment = person.getEmployment();
          ZEM segment = build(employment);
          //1. seq number       
          segment.setSetID("1");
      		//	Sequence 2  EMPLOYMENT PERSON   ID 1 if patient, 2 if spouse
      		segment.setEmploymentPerson("1");      		

          segments.add(segment);
          
          // 2. Spouse Employment
          // 3.1 CCR9857 -- Next add spouse employment if present
          Employment spouseEmployment = getSpouseEmployment(person); 
          if ( spouseEmployment != null )
          {
             segment = build(spouseEmployment);
             //1. seq number       
             segment.setSetID("2");
             //  Sequence 2  EMPLOYMENT PERSON   ID 1 if patient, 2 if spouse
             segment.setEmploymentPerson("2");         
          
             segments.add(segment);
          }
          
        } catch (Exception e)
        {
            throw new BuilderException(
                    "Failed to build ZEM Segment for Z05 due to an exception ", e);
        }

        return segments;
    }
    
    /**
     * Method to build the ZEM segment.
     * 
     * @param employment
     *            The data object used to build the a ZEM segment.
     * @return The single ZEM segment.
     */
    private ZEM build(Employment employment) throws BuilderException
    {
      //1. seq number
      ZEM segment = new ZEM();
      
      if (employment != null) {

        //  sequence 3. EMPLOYMENT STATUS   IS
        segment.setEmploymentStatus((employment.getEmploymentStatus() == null) ? null : employment.getEmploymentStatus().getCode());
          
        //  sequence 4. EMPLOYER NAME        ST
        segment.setEmployerName(employment.getEmployerName());
          
        //  sequence 5. OCCUPATION                 ST
        segment.setOccupation(employment.getOccupation());
          
        // sequence 6. EMPLOYER ADDRESS  AD
        if ( employment.getEmployerAddress() != null )
        {
          segment.setEmployerAddress(addressFormatter.formatSimpleAddress(employment.getEmployerAddress()));
        }
        
        //sequence 7.  EMPLOYER PHONE       TN
        segment.setEmployerPhoneNumber(employment.getEmployerPhone());
        
        //9. DATE OF RETIREMENT  DT
        segment.setRetirementDate(DateFormatter.formatDate(employment.getRetirementDate()));
      }
      return segment;
    }
    
    private Employment getSpouseEmployment(Person person) {
      Integer incomeYear = person.getLatestIncomeYear();
      
      FinancialStatement financialStatement = incomeYear == null ? null : 
          person.getFinancialStatement(incomeYear);
      
      SpouseFinancials spouseFinancials = financialStatement == null ? null
      : financialStatement.getActiveSpouseFinancials();

      Employment employment = spouseFinancials == null ? null :
         spouseFinancials.getReportedOn().getEmployment();
      
      return employment;
    }
}
