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

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

import gov.va.med.fw.hl7.builder.HL7MetaData;
import gov.va.med.fw.hl7.constants.SegmentConstants;
import gov.va.med.fw.hl7.segment.RF1;
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.lookup.AddressChangeSource;
import gov.va.med.esr.common.model.lookup.EmailSourceOfChange;
import gov.va.med.esr.common.model.lookup.PhoneSourceOfChange;
import gov.va.med.esr.common.model.lookup.PhoneType;
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.party.Email;
import gov.va.med.esr.common.model.party.Phone;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.service.trigger.PersonTrigger;
import gov.va.med.esr.service.trigger.PersonTriggerEvent;
import gov.va.med.esr.service.trigger.PersonTriggerIdentity;

/**
 * Builds RF1 segments for a outgoing ORUZ05 message
 * 
 * @author Rajiv Patnaik Created on Sep 8, 2005
 * @version 1.0
 * 
 * Copyright © 2005 VHA. All rights reserved
 */
public class RF1Z05Builder extends AbstractSegmentBuilder
{
    /**
    * An instance of serialVersionUID 
    */
   private static final long serialVersionUID = 9037363064775130073L;
   
   private Builder addressChangeSourceBuilder;

   private Builder emailChangeSourceBuilder;
   
   private Builder phoneChangeSourceBuilder;
   
   
	public Builder getAddressChangeSourceBuilder() {
		return addressChangeSourceBuilder;
	}
	
	public void setAddressChangeSourceBuilder(Builder addressChangeSourceBuilder) {
		this.addressChangeSourceBuilder = addressChangeSourceBuilder;
	}
	
	public Builder getEmailChangeSourceBuilder() {
		return emailChangeSourceBuilder;
	}
	
	public void setEmailChangeSourceBuilder(Builder emailChangeSourceBuilder) {
		this.emailChangeSourceBuilder = emailChangeSourceBuilder;
	}
	
	public Builder getPhoneChangeSourceBuilder() {
		return phoneChangeSourceBuilder;
	}
	
	public void setPhoneChangeSourceBuilder(Builder phoneChangeSourceBuilder) {
		this.phoneChangeSourceBuilder = phoneChangeSourceBuilder;
	}

/**
     * Method to build the ZPD segment.
     * 
     * @param metaData
     *            The parameter object used to build the a ZPD segment.
     * @return List of RF1 segments
     */
    public Object build(HL7MetaData metaData,
            PersonTriggerEvent personTriggerEvent) throws BuilderException
    {
         if ((metaData == null) || (metaData.getEntity() == null)
                || !(metaData.getEntity() instanceof Person)
                || personTriggerEvent == null || personTriggerEvent == null)
        {
            throw new BuilderException(
                    "Invalid input parameter to build a segment");
        }

        //The list of RF1 segments to return
        List rf1Segments = new ArrayList();

        Person person = (Person) metaData.getEntity();

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

        //If Date of Death info: SEQ 1 is not required, RF1 included but not
        // populated)
        //If Guardian info: SEQ 1 is not required, RF1 included but not
        // populated

        //If Address info: SEQ 3,6,7.
        //Upto 4 RF1 segments can be present for Street Address(SAD),
        // Cell(CPH), Pager(PNO) and Email (EAD).
        //RF1^^^SAD^^^500~USVAMC^20051208112215-0400^^^
        //RF1^^^PNO^^^500~VAMC^20050908^^^
        //RF1^^^CPH^^^500~VAMC^20051008^^^
        //RF1^^^EAD^^^500~VAMC^20050808^^^
        if (dataType == PersonTrigger.DataType.ADDRESS)
        {
            //Add SAD
            RF1 rf1SAD = buildRF1ForAddressChange(person.getPermanentAddress(), SegmentConstants.ADDRESS_TYPE_STREET);
            rf1Segments.add(rf1SAD);

            
            if ( person.getConfidentialAddress() != null && (person.getConfidentialAddressCategories() != null && !person.getConfidentialAddressCategories().isEmpty()))
            {
            	RF1 rf1CAD = buildRF1ForAddressChange(person.getConfidentialAddress(), SegmentConstants.ADDRESS_TYPE_CONFIDENTIAL);
            	rf1Segments.add(rf1CAD);
            }
            // CCR11569 Add PHH
           		RF1 rf1HomePhone = buildRF1ForPhone(Phone.getPhoneOfType(person
                    .getPhones(), PhoneType.CODE_HOME.getName()),
                    SegmentConstants.REFERRAL_TYPE_HOME_PHONE_CHANGE);
        		if (rf1HomePhone != null)
        			rf1Segments.add(rf1HomePhone);
        
            // Add CPH
            RF1 rf1CellPhone = buildRF1ForPhone(Phone.getPhoneOfType(person
                    .getPhones(), PhoneType.CODE_MOBILE.getName()),
                    SegmentConstants.REFERRAL_TYPE_CELL_PHONE_CHANGE);

            if (rf1CellPhone != null)
                rf1Segments.add(rf1CellPhone);

            //Add PNO
            RF1 rf1Pager = buildRF1ForPhone(Phone.getPhoneOfType(person
                    .getPhones(), PhoneType.CODE_PAGER.getName()),
                    SegmentConstants.REFERRAL_TYPE_PAGER_NUMBER_CHANGE);
            if (rf1Pager != null)
                rf1Segments.add(rf1Pager);

            //Add EAD
            if ((person.getEmails() != null && !person.getEmails().isEmpty()))
            {
                Email email = (Email) person.getEmails().iterator().next();
                RF1 rf1Email = buildRF1ForEmail(email);
                if (rf1Email != null)
                    rf1Segments.add(rf1Email);
            }

        } else
        {
            //If Date of Death info: SEQ 1 is not required, RF1 included but
            // not
            // populated)
            //If Guardian info: SEQ 1 is not required, RF1 included but not
            // populated

            RF1 rf1 = new RF1();
            //Set the ReferralStatus to create a new RF1 with a value RF1^. If
            // not, then for DOD, GuardianInfo,
            //an empty segment will be created without any delimiter. This will
            // create problems
            //during retransmission while trying to parse this segment without
            // a delimiter
            rf1.setReferralStatus(StringUtils.EMPTY); 

            rf1Segments.add(rf1);
        }

        return rf1Segments;
    }

    /**
     * @param emails
     * @return
     * @throws BuilderException 
     */
    private RF1 buildRF1ForEmail(Email email) throws BuilderException
    {
        //Should never happen
        if (email == null)
        {
            return null;
        }

        RF1 rf1 = new RF1();
        rf1.setReferralType(SegmentConstants.REFERRAL_TYPE_EMAIL_ADDRESS_CHANGE);

        VAFacility changeSite = email.getSiteOfChange();
        EmailSourceOfChange emailSourceOfChange = email.getSourceOfChange();
        //Translates the source to what Vista understands e.g 01 to USVAMC
        String translatedEmailChangeSource = (String)super.build(emailChangeSourceBuilder, email
                .getSourceOfChange());

        //Component 1 is only specified when the source of change is a
        // VAMC, and is the site number who sent the address update.
        // Component 2 is the address change source
        if (emailSourceOfChange != null)
        {
            if (EmailSourceOfChange.CODE_VAMC.getName().equals(
                    emailSourceOfChange.getCode()))
            {
                rf1.setOriginalReferralID((changeSite == null ? "" : changeSite.getCode()) + "~"
                        + translatedEmailChangeSource);
            } else
            {
                rf1.setOriginalReferralID("~" + translatedEmailChangeSource);
            }
        }

        //Seq 7 is Address Change date/time.
        rf1.setEffectiveDate(DateFormatter.formatDateTime(
                email.getChangeDate(), DateFormatter.DATETIME_ZONE_FORMAT));

        return rf1;

    }

    /**
     * @param phones
     * @return
     * @throws BuilderException 
     */
    private RF1 buildRF1ForPhone(Phone phone, String referralType) throws BuilderException
    {
        //Should never happen
        if (phone == null)
        {
            return null;
        }

        RF1 rf1 = new RF1();

        VAFacility changeSite = phone.getSiteOfChange();
        PhoneSourceOfChange phoneSourceOfChange = phone.getSourceOfChange();
        //Translates the source to what Vista understands e.g 01 to USVAMC
        String translatedPhoneChangeSource = (String)super.build(phoneChangeSourceBuilder, phone
                .getSourceOfChange());

        rf1.setReferralType(referralType);

        //Component 1 is only specified when the source of change is a
        // VAMC, and is the site number who sent the address update.
        // Component 2 is the address change source

        if (phoneSourceOfChange != null)
        {
            if (PhoneSourceOfChange.CODE_VAMC.getName().equals(
                    phoneSourceOfChange.getCode()))
            {
                rf1.setOriginalReferralID((changeSite == null ? "" : changeSite.getCode()) + "~"
                        + translatedPhoneChangeSource);
            } else
            {
                rf1.setOriginalReferralID("~" + translatedPhoneChangeSource); 
            }
        }

        //Seq 7 is Address Change date/time.
        rf1.setEffectiveDate(DateFormatter.formatDateTime(
                phone.getChangeDate(), DateFormatter.DATETIME_ZONE_FORMAT));

        return rf1;
    }

    /**
     * @param correspondenceAddress
     * @return
     * @throws BuilderException
     */
    private RF1 buildRF1ForAddressChange(Address address, String referralType )
            throws BuilderException
    {
        //Should never happen
        if (address == null)
        {
            throw new BuilderException(
                    "No Corresspondence Address on File to trigger Z05 message ");
        }

        RF1 rf1 = new RF1();
        setDefaultValues(rf1);
        
        rf1.setReferralType(referralType);

        VAFacility changeSite = address.getChangeSite();
        AddressChangeSource addressChangeSource = address.getChangeSource();
        //Translates the source to what Vista understands e.g VAMC to USVAMC
        String translatedAddressChangeSource = super.build(addressChangeSourceBuilder, address
                .getChangeSource());

        //Component 1 is only specified when the source of change is a
        // VAMC, and is the site number who sent the address update.
        // Component 2 is the address change source
        if (addressChangeSource != null)
        {
            if (AddressChangeSource.CODE_VAMC.getName().equals(
                    addressChangeSource.getCode()))
            {
                rf1.setOriginalReferralID((changeSite == null ? "" : changeSite.getCode()) + "~"
                        + translatedAddressChangeSource);
            } else 
            {
                rf1.setOriginalReferralID("~" + translatedAddressChangeSource);
            }
        }

        //Seq 7 is Address Change date/time.
        // When address update is from a site, the date/time on the RF1 of
        // the Z07.
        //(not the system date/time of the update)
        rf1.setEffectiveDate(DateFormatter.formatDateTime(address
                .getChangeDate(), DateFormatter.DATETIME_ZONE_FORMAT));

        return rf1;
    }
    
}