package gov.va.med.esr.common.model.ee;

import java.util.Collection;
import java.util.Set;
import java.util.HashSet;
import java.util.Collections;
import java.util.Iterator;
import org.apache.commons.lang.Validate;

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

import gov.va.med.esr.common.model.lookup.HealthBenefitPlanType;
import gov.va.med.esr.common.model.lookup.MonetaryBenefitType;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.security.EEServiceUserRequest;
import gov.va.med.esr.common.model.ee.HealthBenefitPlan;

public class HealthBenefitProfile extends AbstractKeyedEntity {

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

    private Person person;

    private Set internalHealthBenefitPlans = null;

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

	// ----------------------------------------------------------------------------
	// Public method(s)
	// ----------------------------------------------------------------------------

	public Person getPerson() {
		return this.person;
	}

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


	/**
	 * Unmodifiable
	 * 
	 * @return
	 */
	public Set getHealthBenefitPlans() {
		return Collections.unmodifiableSet(getInternalHealthBenefitPlans());
	}
	
	public boolean containsHealthBenefitPlans() {
		Set plans = getInternalHealthBenefitPlans();
		return plans != null && plans.size() > 0 ? true : false;
	}
    
	private Set getInternalHealthBenefitPlans() {
		if (internalHealthBenefitPlans == null) {
			this.internalHealthBenefitPlans = new HashSet();
		}
		return this.internalHealthBenefitPlans;
	}

	private void setInternalHealthBenefitPlans(Set internalHealthBenefitPlans) {
		this.internalHealthBenefitPlans = internalHealthBenefitPlans;
	}

	public void addHealthBenefitPlan(HealthBenefitPlan plan) {
		Validate.notNull(plan, "HealthBenefitPlan cannot be null");
        //If it already exists do not add
        if (getHealthBenefitPlanByType(plan.getPlanType()) == null) {
        	//setHealthBenfitProfile(this) before add to the set, 
        	//to avoid stack overflow error
        	plan.setHealthBenefitProfile(this);
        	getInternalHealthBenefitPlans().add(plan);          
        }
	}

	public void removeAllHealthBenefitPlans() {
		this.getInternalHealthBenefitPlans().clear();
	}

	public void removeHealthBenefitPlan(HealthBenefitPlan healthBenefitPlan) {
		Validate.notNull(healthBenefitPlan, "Health Benefit Plan cannot be null");
		removeHealthBenefitPlanByType(healthBenefitPlan.getPlanType());
	}
	
	public void removeHealthBenefitPlans(Collection removePlans) {
		if (removePlans != null && removePlans.size() <= 0  ){
			return;
		}
		Iterator itr = removePlans.iterator();
		while( itr.hasNext()) {
			HealthBenefitPlan plan = (HealthBenefitPlan)itr.next();
			removeHealthBenefitPlan(plan);
		}
	}

    
    public HealthBenefitPlan getHealthBenefitPlanByType(HealthBenefitPlanType planType) {
        Validate.notNull(planType,"HealthBenefitPlanType connot be null");
        return getHealthBenefitPlanByType(planType.getCode());
    }
    
    private HealthBenefitPlan getHealthBenefitPlanByType(HealthBenefitPlanType.Code planType) {
        Validate.notNull(planType,"HealthBenefitPlanType connot be null");
        return getHealthBenefitPlanByType(planType.getCode());
    }

    private HealthBenefitPlan getHealthBenefitPlanByType(String typeCode) {
        if(StringUtils.isNotEmpty(typeCode)) {
            for(Iterator iter= getInternalHealthBenefitPlans().iterator(); iter.hasNext();) {
            	HealthBenefitPlan plan = (HealthBenefitPlan)iter.next();
                String planType = (plan != null && plan.getPlanType() != null) ? plan.getPlanType().getCode() : null;
                if(StringUtils.equals(planType,typeCode)) {
                    return plan;
                }
            }
        }
        return null;
    } 
    
    public void removeHealthBenefitPlanByType(HealthBenefitPlanType planType) {
        Validate.notNull(planType,"HealthBenefitPlanType connot be null");
        HealthBenefitPlan plan = getHealthBenefitPlanByType(planType);
        if (plan != null) {
        	internalHealthBenefitPlans.remove(plan);
        }
    }
    
    private void removeHealthBenefitPlanByType(HealthBenefitPlanType.Code planType) {
        Validate.notNull(planType,"HealthBenefitPlanType connot be null");
        HealthBenefitPlan plan = getHealthBenefitPlanByType(planType.getCode());
        if (plan != null) {
        	internalHealthBenefitPlans.remove(plan);
      }
    }
}
