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

import java.util.HashSet;
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.party.Address;
import gov.va.med.esr.common.model.party.Phone;
import gov.va.med.esr.common.model.lookup.EmploymentStatus;

/**
 * @author DNS   MANSOG
 * @version 1.0
 */
public class Spouse
    extends Relation {

    private static final long serialVersionUID = -4441058118001402944L;
    
    private String maidenName       = null;
   
    private Set internalEmployments = null;

    private Set internalAddresses = null;

    private Set internalPhones = null;
    
    private EmploymentStatus employmentStatus = null;

    /**
     * Creates a new Spouse object.
     */
    public Spouse() {
        super();
    }
    
    public EmploymentStatus getEmploymentStatus() {
        return employmentStatus;
    }

    public void setEmploymentStatus(EmploymentStatus employmentStatus) {
        this.employmentStatus = employmentStatus;
    }

    public String getMaidenName() {
        return maidenName;
    }

    public void setMaidenName(String maidenName) {
        this.maidenName = maidenName;
    }

    public ImpreciseDate getMarriageDate() {
        return getStartDate();
    }

    public void setMarriageDate(ImpreciseDate marriageDate) {
        setStartDate(marriageDate);
    }

    /**
     * Setter - for hibernate use only.
     *
     * @param addresses
     */
    private void setInternalAddresses(Set addresses)
    {
        this.internalAddresses = addresses;
    }

    /**
     * Getter - for hibernate use only.
     *
     * @return the internal addresses
     */
    private Set getInternalAddresses()
    {
        if (this.internalAddresses == null)
        {
            this.internalAddresses = new HashSet();
        }
        return this.internalAddresses;
    }

    /**
     * Add a Address for this InsurancePolicy. This method takes care of Bidirectional setting of Address's
     * InsurancePolicy.
     *
     * @param address
     */
    private void addAddress(Address address)
    {
        Validate.notNull(address, "Null address specified.");
        getInternalAddresses().add(address);
        address.setSpouse(this);
    }

    /**
     * Remove an Address from this Spouse's Address collection. This method takes care of Bidirectional setting
     * of Address's Spouse.
     *
     * @param address
     */
    private void removeAddress(Address address)
    {
        Validate.notNull(address, "Null address specified.");
        getInternalAddresses().remove(address);
    }

    /**
     * Get the Address associated with the Spouse
     *
     * @return Address or null if no address found.
     */
    public Address getAddress()
    {
        Set addresses = getInternalAddresses();
        if (addresses.size() > 0)
        {
            return (Address)addresses.iterator().next();
        }
        return null;
    }

    /**
     * Set the address to this Spouse.
     *
     * @param address
     */
    public void setAddress(Address address)
    {
        Set addresses = getInternalAddresses();
        addresses.clear();
        // setting null mean remove the existing but not add it.
        if (address != null)
        {
            addAddress(address);
        }
    }   
    
    /**
     * Getter - for hibernate use only.
     *
     * @return the internal phones
     */
    private Set getInternalPhones()
    {
        if (this.internalPhones == null)
        {
            this.internalPhones = new HashSet();
        }
        return this.internalPhones;
    }

    /**
     * Setter - for hibernate use only.
     *
     * @param phones
     */
    private void setInternalPhones(Set phones)
    {
        this.internalPhones = phones;
    }
     
    /**
     * Add a Phone for this Spouse. This method takes care of Bidirectional setting of Phone's
     * Spouse.
     *
     * @param phone
     */
    private void addPhone(Phone phone)
    {
        Validate.notNull(phone, "Null phone specified.");
        getInternalPhones().add(phone);
        phone.setSpouse(this);
    }

    /**
     * @param phones
     * @param phone
     * @param typeCode
     */
    public void setHomePhone(Phone phone)
    {
        Set phones = getInternalPhones();
        phones.clear();
        // setting null mean remove the existing but not add it.
        if (phone != null)
        {
            addPhone(phone);
        }
    }
    
    /**
     * Get the Phone associated with the Spouse
     *
     * @return Phone or null if no phone found.
     */
    public Phone getHomePhone()
    {
        Set phones = getInternalPhones();
        if (phones.size() > 0)
        {
            return (Phone)phones.iterator().next();
        }
        return null;
    }

    public Employment getEmployment() {
        Set employments = getInternalEmployments();
            return employments.size() > 0 ? (Employment)employments.iterator().next() : null;
      }

   public void setEmployment(Employment employment) {
        Set employments = getInternalEmployments();
        Iterator iter = employments.iterator();
        if (iter.hasNext()) {
            Employment e = (Employment) iter.next();
            employments.remove(e);
            e.setSpouse(null);
        }
 
        if (employment != null) {
            employments.add(employment);
            employment.setSpouse(this);
        }
    }

    private Set getInternalEmployments() {
        if (this.internalEmployments == null) {
            this.internalEmployments = new HashSet();
        }
        return this.internalEmployments;
    }

    private void setInternalEmployments(Set employments) {
        this.internalEmployments = employments;
    }

    public void removeEmployment(Employment employment) {
        Validate.notNull(employment, "Employment cannot be null");
        this.getInternalEmployments().remove(employment);
    }
    
     /*
         * (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("marriageDate", getMarriageDate());
        builder.append("maidenName", this.maidenName);
    }
    
}

