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

// Java classes
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.esr.common.infra.ImpreciseDate;
import gov.va.med.esr.common.model.insurance.InsurancePolicy;
import gov.va.med.esr.common.model.lookup.AddressChangeSource;
import gov.va.med.esr.common.model.lookup.AddressType;
import gov.va.med.esr.common.model.lookup.BadAddressReason;
import gov.va.med.esr.common.model.lookup.NcoaDeliveryCode;
import gov.va.med.esr.common.model.lookup.NcoaStatus;
import gov.va.med.esr.common.model.lookup.NcoaZipMatch;
import gov.va.med.esr.common.model.lookup.VAFacility;
import gov.va.med.esr.common.model.lookup.ZipPlus4NoMatchReason;
import gov.va.med.esr.common.model.person.Association;
import gov.va.med.esr.common.model.person.Employment;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.person.Spouse;

/**
 * Address BOM
 * @author DNS   MANSOG
 * @version 1.0
 */
public class Address
    extends SimpleAddress {
	
    /**
	 * 
	 */
	private static final long serialVersionUID = -7981129128811594778L;
	private Person                person          = null;
    private Spouse                spouse          = null;
    private Employment            employment      = null;
    private Association           association     = null;
    private InsurancePolicy       insurancePolicy = null;

    private AddressChangeSource   changeSource;
    private VAFacility            changeSite;
    private Date                  changeDate;
    private ImpreciseDate         startDate;
    private ImpreciseDate         endDate;

    // 4114[UC14.25.7]  
    // Temporary Address information may include a Telephone Number.  This is display only. 
    private String                phoneNumber;
    private BadAddressReason      badAddressReason;
    private Date                  dateCheckedByNCOA;
    private Date                  ncoaInvalidUndeliverableDate;
    private NcoaStatus            ncoaStatus;
    private NcoaDeliveryCode      ncoaDeliveryCode;
    private NcoaZipMatch          ncoaZipPlus4MatchCode;
    private ZipPlus4NoMatchReason zipPlus4NoMatchReason;
    
    private boolean isActive = true;

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

    public Association getAssociation() {
        return association;
    }

    public void setAssociation(Association association) {
        this.association = association;
    }

    public Person getPerson() {
        return person;
    }

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

    public Spouse getSpouse() {
        return spouse;
    }

    public void setSpouse(Spouse spouse) {
        validateOwner(this.spouse, spouse);
        this.spouse = spouse;
    }
    
    public Employment getEmployment() {
       return employment;
    }

    public void setEmployment(Employment employment) {
       this.employment = employment;
    }

    public InsurancePolicy getInsurancePolicy() {
        return insurancePolicy;
    }

    public void setInsurancePolicy(InsurancePolicy insurancePolicy) {
        validateOwner(this.insurancePolicy, insurancePolicy);
       this.insurancePolicy = insurancePolicy;
    }

    public Date getChangeDate() {
        return this.changeDate;
    }

    public void setChangeDate(Date changeDate) {
        this.changeDate = changeDate;
    }

    public AddressChangeSource getChangeSource() {
        return this.changeSource;
    }

    public void setChangeSource(AddressChangeSource changeSource) {
        this.changeSource = changeSource;
    }

    public VAFacility getChangeSite() {
        return this.changeSite;
    }

    public void setChangeSite(VAFacility changeSite) {
        this.changeSite = changeSite;
    }

    public ImpreciseDate getEndDate() {
        return endDate;
    }

    public void setEndDate(ImpreciseDate endDate) {
        this.endDate = endDate;
    }

    public ImpreciseDate getStartDate() {
        return startDate;
    }

    public void setStartDate(ImpreciseDate startDate) {
        this.startDate = startDate;
    }

    /**
     * For Address of type Temporary only 
     * @return
     */
    public String getPhoneNumber() {
        return this.phoneNumber;
    }

    /**
     * For Address of type Temporary only 
     * @return
     */
    public void setPhoneNumber(String phone) {
        this.phoneNumber = phone;
    }

    public BadAddressReason getBadAddressReason() {
        return this.badAddressReason;
    }

    public void setBadAddressReason(BadAddressReason reason) {
        this.badAddressReason = reason;
    }

    public Date getDateCheckedByNCOA() {
        return this.dateCheckedByNCOA;
    }

    public void setDateCheckedByNCOA(Date date) {
        this.dateCheckedByNCOA = date;
    }

    public Date getNcoaInvalidUndeliverableDate() {
        return this.ncoaInvalidUndeliverableDate;
    }

    public void setNcoaInvalidUndeliverableDate(
            Date ncoaInvalidUndeliverableDate) {
        this.ncoaInvalidUndeliverableDate = ncoaInvalidUndeliverableDate;
    }

    public NcoaStatus getNcoaStatus() {
        return this.ncoaStatus;
    }

    public void setNcoaStatus(NcoaStatus status) {
        this.ncoaStatus = status;
    }

    public NcoaDeliveryCode getNcoaDeliveryCode() {
        return this.ncoaDeliveryCode;
    }

    public void setNcoaDeliveryCode(NcoaDeliveryCode code) {
        this.ncoaDeliveryCode = code;
    }

    public NcoaZipMatch getNcoaZipPlus4MatchCode() {
        return this.ncoaZipPlus4MatchCode;
    }

    public void setNcoaZipPlus4MatchCode(NcoaZipMatch code) {
        this.ncoaZipPlus4MatchCode = code;
    }

    public ZipPlus4NoMatchReason getZipPlus4NoMatchReason() {
        return this.zipPlus4NoMatchReason;
    }

    public void setZipPlus4NoMatchReason(ZipPlus4NoMatchReason reason) {
        this.zipPlus4NoMatchReason = reason;
    }

    /*
     * (non-Javadoc)
     * 
     * @see gov.va.med.fw.model.AbstractKeyedEntity#buildToString(org.apache.commons.lang.builder.ToStringBuilder)
     */
    protected void buildToString(ToStringBuilder builder) {
        super.buildToString(builder);
        builder.append("changeDate", this.changeDate);
        builder.append("changeSource", this.changeSource);
        builder.append("changeSite", this.changeSite);
        builder.append("changeDate", this.changeDate);
        builder.append("startDate", this.startDate);
        builder.append("endDate", this.phoneNumber);
        builder.append("phoneNumber", this.phoneNumber);
        builder.append("badAddressReason", this.badAddressReason);
        builder.append("dateCheckedByNCOA", this.dateCheckedByNCOA);
        builder.append("ncoaInvalidUndeliverableDate",
                this.ncoaInvalidUndeliverableDate);
        builder.append("ncoaStatus", this.ncoaStatus);
        builder.append("ncoaZipPlus4MatchCode", this.ncoaZipPlus4MatchCode);
        builder.append("zipPlus4NoMatchReason", this.zipPlus4NoMatchReason);
    }

    /**
     * Helper method to get the Address of a given type code.
     * This method iterates the collection of addresses and return 
     * the Address of give type code or null if no address for a given 
     * type code exists.
     * 
     * @param addresses
     * @param typeCode
     * @return Address if found or null if no phone with a given type found.
     */
    public static Address getAddressOfType(Set addresses, String typeCode) {
		Validate.notNull(addresses, "The set of addresses must not be null");
		Validate.notNull(typeCode, "Address type's code must not be null");
        for (Iterator iter = addresses.iterator(); iter.hasNext();) {
            Address addr = (Address) iter.next();
            AddressType addrType = addr.getType();
            if (addrType != null && addrType.getCode().equals(typeCode)) {
                return addr;
            }
        }
        return null;
    }

    public boolean isActive() {
        return isActive;
    }

    public void setActive(boolean isActive) {
        this.isActive = isActive;
    }

 }