/********************************************************************
 * Copyright © 2004 EDS. All rights reserved
 ********************************************************************/
package gov.va.med.esr.common.builder.entity;

// Java Classes

// Library Classes

// Framework Classes
import java.util.Date;

import gov.va.med.fw.util.StringUtils;
import gov.va.med.fw.util.builder.Builder;
import gov.va.med.fw.util.builder.BuilderException;

// Common Classes
import gov.va.med.esr.common.builder.entity.metaData.AssociationMetaDataFromZCT;
import gov.va.med.esr.common.builder.entity.metaData.AssociationMetaDataFromZGD;
import gov.va.med.esr.common.model.lookup.AssociationType;
import gov.va.med.esr.common.model.party.Address;
import gov.va.med.esr.common.model.party.SimpleAddress;
import gov.va.med.esr.common.model.person.Association;
import gov.va.med.esr.common.model.person.Name;

// Messaging Classes

/**
 * Class that builds the application from a message.
 *
 * @author Carlos Ruiz
 * @version 1.0
 */
public class AssociationBuilder extends EntityBuilder
{
    /*
     * ZCT/ZGD Association Type constants
     * In the ZCT segment, the contact type could have values 1,2,3,4,5.
     * In the ZGD segment, the guardian type could have values 1,2
     * These will get parsed into the right AssociationType
     */
    public static final String VA_GUARDIAN = "1";

    public static final String VA_CIVIL = "2";

    public static final String PRIMARY_NEXT_OF_KIN = "1";

    public static final String OTHER_NEXT_OF_KIN = "2";

    public static final String EMERGENCY_CONTACT = "3";

    public static final String OTHER_EMERGENCY_CONTACT = "4";

    public static final String DESIGNEE = "5";

    /**
     * An instance of serialVersionUID
     */
    private static final long serialVersionUID = 2534437700958487077L;

    private Builder addressBuilder;

    private Builder nameBuilder;

    private Builder phoneBuilder;

    private Builder relationshipBuilder;

    private Builder typeBuilder;

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

    public Builder getAddressBuilder()
    {
        return this.addressBuilder;
    }

    public void setAddressBuilder(Builder addressBuilder)
    {
        this.addressBuilder = addressBuilder;
    }

    /**
     * @return Returns the nameBuilder.
     */
    public Builder getNameBuilder()
    {
        return nameBuilder;
    }

    /**
     * @param nameBuilder
     *            The nameBuilder to set.
     */
    public void setNameBuilder(Builder nameBuilder)
    {
        this.nameBuilder = nameBuilder;
    }

    public Builder getPhoneBuilder()
    {
        return this.phoneBuilder;
    }

    public void setPhoneBuilder(Builder phoneBuilder)
    {
        this.phoneBuilder = phoneBuilder;
    }

    public Builder getRelationshipBuilder()
    {
        return this.relationshipBuilder;
    }

    public void setRelationshipBuilder(Builder relationshipBuilder)
    {
        this.relationshipBuilder = relationshipBuilder;
    }

    public Builder getTypeBuilder()
    {
        return this.typeBuilder;
    }

    public void setTypeBuilder(Builder typeBuilder)
    {
        this.typeBuilder = typeBuilder;
    }

    public Association build(AssociationMetaData metaData)
            throws BuilderException
    {
    	Association input = metaData.getEntity();
        Association output = (input == null) ? new Association() : input;

        this.transfer(output, metaData);

        return this.shouldKeep(output) ? output : null;
    }

    private void transfer(Association input, AssociationMetaData metaData)
            throws BuilderException
    {

    	input.setAddress(this.buildAddress(input.getAddress(), metaData
                .getAddress()));

        input.setPrimaryPhone(super.build(input.getPrimaryPhone(), (metaData
                .getPrimaryPhone() == null) ? null : metaData.getPrimaryPhone()
                .getPhoneNumber()));

        input.setRelationship(super.build(input.getRelationship(), metaData
                .getRelationship()));

        input.setType(this.buildType(input.getType(), metaData));

        if(input.getType() != null &&
        		( AssociationType.CODE_GUARDIAN_VA.getCode().equals(input.getType().getCode())
        		|| AssociationType.CODE_GUARDIAN_CIVIL.getCode().equals(input.getType().getCode())) )
        {
            //Vista will always send the name(org name/LN,FN) in ZGD-3(Guardian name).
        	input.setOrganizationName(metaData.getGuardianName());
        } else {
        	//For contact
            Name name = metaData.getContactName() == null ?
            		null: (Name) nameBuilder.build(metaData.getContactName());
	        input.setRepresentativeName(name);
        }

        input.setAlternatePhone(super.build(input.getAlternatePhone(),
                (metaData.getAlternatePhone() == null) ? null : metaData
                		.getAlternatePhone().getPhoneNumber()));

        input.setLastUpdateDate(super.build(input.getLastUpdateDate(), metaData.getLastUpdateDate()));

    }

    private Address buildAddress(SimpleAddress input, AddressMetaData metaData)
            throws BuilderException
    {
        if (metaData == null)
        {
            return null;
        } else
        {
            metaData.setEntity((Address) input);
            return (Address) this.addressBuilder.build(metaData);
        }
    }

    /**
     * Parses the contact type and guardian type which came in the message
     * and converts them to the appropriate AssociationType
     *
     * @param input
     * @param metaData
     * @return
     * @throws BuilderException
     */
    private AssociationType buildType(AssociationType input,
            AssociationMetaData metaData) throws BuilderException
    {
        AssociationType type = null;
        if (metaData instanceof AssociationMetaDataFromZCT)
        {
            if (PRIMARY_NEXT_OF_KIN.equals(metaData.getType()))
            {
                type = (AssociationType) super.build(this.typeBuilder, input,
                        AssociationType.CODE_PRIMARY_NEXT_OF_KIN.getName());
            } else if (OTHER_NEXT_OF_KIN.equals(metaData.getType()))
            {
                type = (AssociationType) super.build(this.typeBuilder, input,
                        AssociationType.CODE_OTHER_NEXT_OF_KIN.getName());
            } else if (EMERGENCY_CONTACT.equals(metaData.getType()))
            {
                type = (AssociationType) super.build(this.typeBuilder, input,
                        AssociationType.CODE_EMERGENCY_CONTACT.getName());
            } else if (OTHER_EMERGENCY_CONTACT.equals(metaData.getType()))
            {
                type = (AssociationType) super.build(this.typeBuilder, input,
                        AssociationType.CODE_OTHER_EMERGENCY_CONTACT.getName());
            } else if (DESIGNEE.equals(metaData.getType()))
            {
                type = (AssociationType) super.build(this.typeBuilder, input,
                        AssociationType.CODE_DESIGNEE.getName());
            }
        } else if (metaData instanceof AssociationMetaDataFromZGD)
        {
            if (VA_GUARDIAN.equals(metaData.getType()))
            {
                type = (AssociationType) super.build(this.typeBuilder, input,
                        AssociationType.CODE_GUARDIAN_VA.getName());
            } else if (VA_CIVIL.equals(metaData.getType()))
            {
                type = (AssociationType) super.build(this.typeBuilder, input,
                        AssociationType.CODE_GUARDIAN_CIVIL.getName());
            }
        }
        return type;
    }

    private boolean shouldKeep(Association obj)
    {
        return ((obj.getType() != null)
        		&& ((obj.getRelationship() != null)
                || (obj.getRepresentativeName() != null) ||
                ( (obj.getOrganizationName() != null && !shouldDelete(obj.getOrganizationName())))));
    }

    /**
     * @param input
     * @param metaData
     * @return
     * @throws BuilderException
     */
    private Name buildContactName(Association input, AssociationMetaData metaData)
            throws BuilderException
    {
        return metaData.getContactName() == null ? null
                    : (Name) nameBuilder.build(metaData.getContactName());
    }
}