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

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

import gov.va.med.esr.common.model.lookup.AssociationType;
import gov.va.med.esr.common.model.person.Association;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.rule.service.impl.AssociationRuleServiceImpl;
import gov.va.med.esr.service.trigger.PersonTrigger;
import gov.va.med.esr.service.trigger.PersonTriggerEvent;
import gov.va.med.esr.service.trigger.PersonTriggerIdentity;
import gov.va.med.fw.hl7.builder.HL7MetaData;
import gov.va.med.fw.hl7.segment.ZCT;
import gov.va.med.fw.util.builder.BuilderException;

public class ZCTBuilder extends AbstractSegmentBuilder {
	

	private static final long serialVersionUID = 8982455003732347560L;

    protected AddressElementFormatter addressFormatter; 
    
	public AddressElementFormatter getAddressFormatter() {
		return addressFormatter;
	}
	
	public void setAddressFormatter(AddressElementFormatter addressFormatter) {
		this.addressFormatter = addressFormatter;
	}

	
	/**
     * Method to build the ZCT segment.
     * 
     * @param metaData
     *            The parameter object used to build the a ZPD segment.
     * @return The ZCT segment.
     */
    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");
        }

        PersonTriggerIdentity personTriggerIdentity = (PersonTriggerIdentity) triggerEvent
        .getTriggerIdentity();

        PersonTrigger.DataType dataType = (PersonTrigger.DataType) personTriggerIdentity
        .getApplicableDataTypes().iterator().next();

        Person person = (Person) metaData.getEntity();
        ArrayList zctSegments = new ArrayList();
        
        //CCR 10267: per email from Darlene
        //Terry also provided the information on one of these streams – 
        //VistA is expecting these segments in the ORU-Z05, 
        //but only the address type needs to have these segments populated.  
        //The Guardian and Death Z05s need the segments, just no information.  
        if (dataType != PersonTrigger.DataType.ADDRESS)
        {
    		//need at least one ZCT segment
    		ZCT segment = new ZCT(); 
     		segment.setSetID("1");
     		zctSegments.add(segment);
     		
          return zctSegments;
        }
        
        try
        {	
        	
        	Set associations = person.getAssociations();
        	int sequence = 1;
        	
        	//CONTACT TYPE  1=NOK, 2=2nd NOK, 3=e-contact, 4=2nd e-contact, 5=designee
        	Association  nok = Association.getAssociationOfType(associations, AssociationType.CODE_PRIMARY_NEXT_OF_KIN.getCode());
        	if (nok != null)
        	{
            	setContact(nok, sequence, zctSegments);
            	sequence++;
        	}
        	Association  nok2 = Association.getAssociationOfType(associations, AssociationType.CODE_OTHER_NEXT_OF_KIN.getCode());
        	if (nok2 != null)
        	{
            	setContact(nok2, sequence, zctSegments);  
            	sequence++;
        	}
        	Association  eContact = Association.getAssociationOfType(associations, AssociationType.CODE_EMERGENCY_CONTACT.getCode());
        	if (eContact != null)
        	{
            	setContact(eContact, sequence, zctSegments); 
            	sequence++;
        	}
        	Association  eContact2 = Association.getAssociationOfType(associations, AssociationType.CODE_OTHER_EMERGENCY_CONTACT.getCode());
        	if (eContact2 != null)
        	{
            	setContact(eContact2, sequence, zctSegments);
            	sequence++;
        	}
        	Association  designee = Association.getAssociationOfType(associations, AssociationType.CODE_DESIGNEE.getCode());
        	if (designee != null)
        	{
            	setContact(designee, sequence, zctSegments);
        	}
        	
        	if (zctSegments.size() == 0)
        	{
        		//need at least one ZCT segment
        		ZCT segment = new ZCT(); 
         		segment.setSetID("1");
         		
         		zctSegments.add(segment);
        	}
        } catch (Exception e)
        {
            throw new BuilderException(
                    "Failed to build ZCT Segment for Z05 due to an exception ", e);
        }

        return zctSegments;
    }
    
    //CCR 9932-Outbound Z05 does not include multiple ZCT segments for each contact
    private void setContact(Association contact, int sequence, ArrayList zctSegments) throws BuilderException
    {
        ZCT segment = new ZCT();
        
        if (contact.getRepresentativeName()!=null && contact.getRepresentativeName().getFamilyName()!=null && contact.getRepresentativeName().getFamilyName().equals(AssociationRuleServiceImpl.DELETE_FLAG)) {
            //1. seq number
           segment.setSetID(sequence+"");

           //            Sequence 2  CONTACT TYPE  1=NOK, 2=2nd NOK, 3=e-contact, 4=2nd e-contact, 5=designee
           segment.setContactType(contact.getType().getCode());

           //            sequence 3. CONTACT NAME      LAST~FIRST  MIDDLE~SUFFIX~~~~NAME TYPE
           segment.setContactName("");

           //            sequence 4. CONTACT RELATIONSHIP
           segment.setContactRelationship("");

           //            sequence 5. CONTACT ADDRESS
           segment.setContactAddress("");

           // sequence 6. CONTACT PHONE NUMBER
           segment.setContactPhoneNumber("");

           //sequence 7.  CONTACT WORK PHONE NUMBER
           segment.setContactWorkPhoneNumber("");
        } else {
    //1. seq number
           segment.setSetID(sequence+"");

           //            Sequence 2  CONTACT TYPE  1=NOK, 2=2nd NOK, 3=e-contact, 4=2nd e-contact, 5=designee
           segment.setContactType(contact.getType().getCode());

           //            sequence 3. CONTACT NAME      LAST~FIRST  MIDDLE~SUFFIX~~~~NAME TYPE
           segment.setContactName(ElementFormatter.formatName(contact.getRepresentativeName()));

           //            sequence 4. CONTACT RELATIONSHIP
           segment.setContactRelationship(contact.getRelationship());

           //            sequence 5. CONTACT ADDRESS
           //CCCR9931 ORU-Z05 not generating when patient's address is changed for patients with contact info and no contact address
           if (contact.getAddress() != null)
           {
                          segment.setContactAddress(addressFormatter.formatSimpleAddress(contact.getAddress()));
           }
           // sequence 6. CONTACT PHONE NUMBER
           segment.setContactPhoneNumber(contact.getPrimaryPhone());

           //sequence 7.  CONTACT WORK PHONE NUMBER
           segment.setContactWorkPhoneNumber(contact.getAlternatePhone());
    	}

		//10 Contact Date/Time last updated
		//ESR 3.5_CodeCR11155_st_ZCT not correctly capturing date/timestamp in ORU-Z05
		if(contact.getLastUpdateDate() !=null){
			segment.setLastUpdateDate(DateFormatter.formatDateTime(contact.getLastUpdateDate(),DateFormatter.DATETIME_ZONE_FORMAT));
		}
		zctSegments.add(segment);
    	
    }

}
