/********************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ********************************************************************/
package gov.va.med.esr.common.model.person;

import java.util.Date;
import java.util.Iterator;
import java.util.Set;

import org.apache.commons.lang.Validate;
import org.apache.commons.lang.builder.ToStringBuilder;

import gov.va.med.fw.model.AbstractKeyedEntity;
import gov.va.med.fw.util.DateUtils;
import gov.va.med.fw.util.StringUtils;

import gov.va.med.esr.common.model.lookup.AssociationType;
import gov.va.med.esr.common.model.party.Address;

/**
 * Person Association BOM
 *
 * @author DNS   MANSOG
 * @version 1.0
 */
public class Association extends AbstractKeyedEntity implements Comparable
{
    /**
	 *
	 */
	private static final long serialVersionUID = 7361250873555917782L;
	private Person person = null;
    private AssociationType type = null;
    private String organizationName = null;
    private Name representativeName = null;
    private String relationship = null;
    private Address address = null;
    private String primaryPhone = null;
    private String alternatePhone = null;
    private Date primaryPhoneChangeDate = null;
    private Date deactivationDate;
    private Date alternatePhoneChangeDate = null;
    private Date lastUpdateDate = null;

    /**
     * Creates a new Association object.
     */
    public Association()
    {
        super();
    }

    public Person getPerson()
    {
        return person;
    }

    public void setPerson(Person person)
    {
        validateOwner(this.person, person);
        this.person = person;
    }

    public AssociationType getType()
    {
        return this.type;
    }

    public void setType(AssociationType type)
    {
        this.type = type;
    }

    public String getOrganizationName()
    {
        return this.organizationName;
    }

    public void setOrganizationName(String organizationName)
    {
        this.organizationName = organizationName;
    }

    public Name getRepresentativeName()
    {
        return this.representativeName;
    }

    public void setRepresentativeName(Name representativeName)
    {
        this.representativeName = representativeName;
    }

    public String getRelationship()
    {
        return this.relationship;
    }

    public void setRelationship(String relationship)
    {
        this.relationship = relationship;
    }

    public Address getAddress()
    {
        return address;
    }

    public void setAddress(Address address)
    {
        if (this.address != null)
        {
            this.address.setAssociation(null);
        }
        if (address != null)
        {
            address.setAssociation(this);
        }
        this.address = address;
    }

    public String getAlternatePhone()
    {
        return alternatePhone;
    }

    public void setAlternatePhone(String alternatePhone)
    {
        this.alternatePhone = alternatePhone;
    }

    public Date getAlternatePhoneChangeDate()
    {
        return alternatePhoneChangeDate;
    }

    public void setAlternatePhoneChangeDate(Date alternatePhoneChangeDate)
    {
        this.alternatePhoneChangeDate = alternatePhoneChangeDate;
    }

    public String getPrimaryPhone()
    {
        return primaryPhone;
    }

    public void setPrimaryPhone(String primaryPhone)
    {
        this.primaryPhone = primaryPhone;
    }

    public Date getPrimaryPhoneChangeDate()
    {
        return primaryPhoneChangeDate;
    }

    public void setPrimaryPhoneChangeDate(Date primaryPhoneChangeDate)
    {
        this.primaryPhoneChangeDate = primaryPhoneChangeDate;
    }

    private void isRepresentativeName() {
    	if (representativeName == null) {
    		representativeName = new Name();
    	}
    }
    public String getFirstName() {

		return  (representativeName == null) ? "" : representativeName.getGivenName();
	}

	public void setFirstName(String firstName) {
    	isRepresentativeName();
		representativeName.setGivenName(firstName);
	}

	public String getLastName() {
		return (representativeName == null) ? "" : representativeName.getFamilyName();
	}

	public void setLastName(String lastName) {
    	isRepresentativeName();
		representativeName.setFamilyName(lastName);
	}

	public String getMiddleName() {
		return (representativeName == null) ? "" : representativeName.getMiddleName();
	}

	public void setMiddleName(String middleName) {
    	isRepresentativeName();
		representativeName.setMiddleName(middleName);
	}

	public Date getLastUpdateDate()
    {
        return lastUpdateDate;
    }

    public void setLastUpdateDate(Date lastUpdateDate)
    {
        this.lastUpdateDate = lastUpdateDate;
    }

    public boolean isExpired() {
            Date today = DateUtils.getCurrentDate();
            Date deactiveDate = getDeactivationDate();

            // Check with the current date to see expired or not
            if (deactiveDate != null && deactiveDate.before(today)) {
                return true;
            }

            return false;
    }

    /**
     * Compares two associations.  The comparrison is done based on the associations name (last name first)
     * followed by the organization name.
     *
     * @param associationObject the other association to compare.
     * @return The comparrision value.
     */
    public int compareTo(Object associationObject)
    {
        Association otherAssociation = (Association)associationObject;

        // Start with the name
        String thisCompareValue = getRepresentativeName() != null ?
            getRepresentativeName().getFormattedName().trim() : "";
        String otherCompareValue = otherAssociation.getRepresentativeName() != null ?
            otherAssociation.getRepresentativeName().getFormattedName().trim() : "";

        // Add the organization name
        thisCompareValue += getOrganizationName() != null ? getOrganizationName().trim() : "";
        otherCompareValue += otherAssociation.getOrganizationName() != null ?
                otherAssociation.getOrganizationName().trim() : "";

        // Return the comparrion
        return StringUtils.compareTo(thisCompareValue, otherCompareValue);
    }

    /**
     * @see gov.va.med.fw.model.AbstractKeyedEntity#buildToString(org.apache.commons.lang.builder.ToStringBuilder)
     */
    protected void buildToString(ToStringBuilder builder)
    {
        super.buildToString(builder);
        builder.append("type", this.type);
        builder.append("organizationName", this.organizationName);
        builder.append("representativeName", this.representativeName);
        builder.append("address", this.address);
        builder.append("relationship", this.relationship);
        builder.append("deactivationDate", this.deactivationDate);
    }

    /**
     * Helper method to get the Association of a given type code. This method iterates the collection of associations
     * and return the Association of give type code or null if no association for a given type code exists.
     *
     * @param associations
     * @param typeCode
     *
     * @return the association of the specified type.
     */
    public static Association getAssociationOfType(Set associations, String typeCode)
    {
        Validate.notNull(associations, "The set of associations must not be null");
        Validate.notNull(typeCode, "Association type's code must not be null");
        for (Iterator iter = associations.iterator(); iter.hasNext();)
        {
            Association association = (Association)iter.next();

            // ESR3.1 CCR9972 -- this method should not be returning
            // deactivated entries
            if (association.getDeactivationDate() != null) {
              continue;
            }

            AssociationType associationType = association.getType();
            if (associationType != null && associationType.getCode().equals(typeCode))
            {
                return association;
            }
        }
        return null;
    }

    public Date getDeactivationDate() {
        return deactivationDate;
    }

    public void setDeactivationDate(Date deactivationDate) {
        this.deactivationDate = deactivationDate;
    }
}
