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

// Java classes
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;

// Framework classes
import gov.va.med.fw.rule.RuleDataAware;
import gov.va.med.fw.util.StringUtils;

// ESR classes
import gov.va.med.esr.common.model.financials.Asset;
import gov.va.med.esr.common.model.financials.DependentFinancials;
import gov.va.med.esr.common.model.financials.Expense;
import gov.va.med.esr.common.model.financials.FinancialStatement;
import gov.va.med.esr.common.model.financials.Income;
import gov.va.med.esr.common.model.lookup.AssetType;
import gov.va.med.esr.common.model.lookup.ExpenseType;
import gov.va.med.esr.common.model.lookup.IncomeType;
import gov.va.med.esr.common.model.lookup.Relationship;
import gov.va.med.esr.common.model.person.Dependent;
import gov.va.med.esr.common.rule.DependentFinancialInput;
import gov.va.med.esr.common.rule.data.DependentFinancialsInputData;

/**
 * 
 * @author Carlos Ruiz
 * @author Ghazenfer Mansoor
 * @version 1.0
 */
public class DependentFinancialInputParameter extends AbstractFinancialInputParameter
        implements DependentFinancialInput {

    private static final long serialVersionUID = 4164075105209388639L;
    
    public DependentFinancialInputParameter() 
    {
        super();
    }
    
    public boolean isDemographicUpdate()
    {
        return (getDependentFinancialsInputData() != null) ? getDependentFinancialsInputData().isDemographicUpdate() : false;
    }

    public BigDecimal getAssetAmount(AssetType.Code expenseType) {
        BigDecimal amount = getAssetAmount(getDependentFinancials(),
                expenseType);
        return amount == null ? new BigDecimal(0d) : amount;
    }

    public BigDecimal getIncomeAmount(IncomeType.Code expenseType) {
        BigDecimal amount = getIncomeAmount(getDependentFinancials(),
                expenseType);
        return amount == null ? new BigDecimal(0d) : amount;
    }

    public BigDecimal getExpenseAmount(ExpenseType.Code expenseType) {
        BigDecimal amount = getExpenseAmount(getDependentFinancials(),
                expenseType);
        return amount == null ? new BigDecimal(0d) : amount;
    }

    public String getDependentGivenName()
    {
        String givenName = this.getRelationGivenName(getDependent());
        return (StringUtils.isNotEmpty(givenName)) ? givenName : null;
    }
    
    public String getDependentFamilyName()
    {
        String familyName = this.getRelationFamilyName(getDependent());
        return (StringUtils.isNotEmpty(familyName)) ? familyName : null;
    }
    
    public Date getChildDependentEffective() 
    {
        return getDependentEffectiveDate();
    }

    public String getDependentSSN() 
    {
        return getRelationSSN(getDependent());
    }

    public boolean isDependentSSNUsed() {
        return this.isRelationSSNUsed(getDependentFinancials());
    }
    
    public Date getDependentEffectiveDate() 
    {
        return getRelationEffectiveDate(getDependent());
    }
    
    public Date getDependentInactiveDate() 
    {
        return getRelationInActiveDate(this.getDependent());
    }
    
    public String getDependentRelationship() {
        Relationship relationship = (this.getDependent() != null) ? this.getDependent().getRelationship() : null;
        return (relationship != null) ? relationship.getCode() : null;
    }
    
    public BigDecimal getChildSupportContributionAmount()
    {
        DependentFinancials depFin  = getDependentFinancials();
        return (depFin != null && depFin.getAmountContributedToSupport() != null) ? depFin.getAmountContributedToSupport() : new BigDecimal(0d);
    }
    
    public Boolean getHasIncomeIndicator()
    {
        DependentFinancials depFin  = getDependentFinancials();
        return (depFin != null) ? depFin.getHasIncome() : null; 
    }
    
    public Boolean getIncomeAvailableToVeteranIndicator()
    {
        DependentFinancials depFin  = getDependentFinancials();
        return (depFin != null) ? depFin.getIncomeAvailableToPatient(): null;
    }
    
    public boolean isDependentHasAnyIncomeAmount() {
        DependentFinancials dependentFinancials  = getDependentFinancials();
        Collection incomes = (dependentFinancials != null && dependentFinancials.getIncome() != null) ? dependentFinancials.getIncome().values() : null;
        
        if (incomes != null && !incomes.isEmpty()) {
            for (Iterator iter = incomes.iterator(); iter.hasNext();) {
                Income income = (Income) iter.next();
                double amount = (income != null && income.getAmount() != null) ? income.getAmount().doubleValue() : 0.0d;
                if(amount > 0.0d) return true;
            }
        }
        return false;
    }
    
    public boolean isDependentHasAnyExpenseAmount() {
        DependentFinancials dependentFinancials  = getDependentFinancials();
        Collection expenses = (dependentFinancials != null && dependentFinancials.getExpenses() != null) ? dependentFinancials.getExpenses().values() : null;
        
        if (expenses != null && !expenses.isEmpty()) {
            for (Iterator iter = expenses.iterator(); iter.hasNext();) {
                Expense expense = (Expense) iter.next();
                double amount = (expense != null && expense.getAmount() != null) ? expense.getAmount().doubleValue() : 0.0d;
                if(amount > 0.0d) return true;
            }
        }
        return false;
    }
    
    public boolean isDependentHasAnyAssetAmount() {
        DependentFinancials dependentFinancials  = getDependentFinancials();
        Collection assets = (dependentFinancials != null && dependentFinancials.getAssets() != null) ? dependentFinancials.getAssets().values() : null;
        
        if (assets != null && !assets.isEmpty()) {
            for (Iterator iter = assets.iterator(); iter.hasNext();) {
                Asset asset = (Asset) iter.next();
                double amount = (asset != null && asset.getAmount() != null) ? asset.getAmount().doubleValue() : 0.0d;
                if(amount > 0.0d) return true;
            }
        }
        return false;
    }
    
    public boolean isContributionInRange(double lower, double upper)
    {
        DependentFinancials dependentFinancials  = getDependentFinancials();
        if(dependentFinancials != null && dependentFinancials.getAmountContributedToSupport() != null)
        {
            return this.isInRange(dependentFinancials.getAmountContributedToSupport(),lower,upper);
        }
        return true;
    }
    
    public boolean isIncomeInRange(double lower, double upper)
    {
        DependentFinancials dependentFinancials  = getDependentFinancials();
        if(dependentFinancials != null && dependentFinancials.getIncome() != null)
        {
            return this.isIncomeInRange(dependentFinancials.getIncome().values(),lower,upper);
        }
        return true;
    }
    
    public boolean isExpenseInRange(double lower, double upper)
    {
        DependentFinancials dependentFinancials  = getDependentFinancials();
        if(dependentFinancials != null && dependentFinancials.getExpenses() != null)
        {
            return this.isExpenseInRange(dependentFinancials.getExpenses().values(),lower,upper);
        }
        return true;
    }
    
    public boolean isAssetInRange(double lower, double upper)
    {
        DependentFinancials dependentFinancials  = getDependentFinancials();
        if(dependentFinancials != null && dependentFinancials.getAssets() != null)
        {
            return this.isAssetInRange(dependentFinancials.getAssets().values(),lower,upper);
        }
        return true;
    }
    
    public Date getDependentBirthDate() 
    {
        return getRelationBirthDate(getDependent());
    }

    public boolean isDependentLivesWithVeteran()
    {
        DependentFinancials dependentFinancials  = getDependentFinancials();
        return (dependentFinancials != null && dependentFinancials.getLivedWithPatient() != null) ? dependentFinancials.getLivedWithPatient().booleanValue() : false;
    }
    
    public boolean isChildSupportContributionIndicator()
    {
        DependentFinancials dependentFinancials  = getDependentFinancials();
        return (dependentFinancials != null && dependentFinancials.getContributedToSupport() != null) ? dependentFinancials.getContributedToSupport().booleanValue() : false;
    }
    
    public int getTotalNumberOfDependents()
    {
        FinancialStatement stmt = (getDependentFinancials() != null) ? this.getDependentFinancials().getFinancialStatement() : null;
        return (stmt != null) ? stmt.getDependentFinancials().size() : 0;
    }
    
    private Dependent getDependent() 
    {
        return (getDependentFinancials() != null) ? getDependentFinancials().getReportedOn() : null;
    }

    /**
     * This method is for use by validations. Will return the dependent
     * financials set by the caller.
     * 
     * @return Returns the dependentFinancials.
     */
    private DependentFinancials getDependentFinancials() 
    {
        DependentFinancialsInputData inputData = getDependentFinancialsInputData();
        return (inputData != null) ? inputData.getIncomingDependentFinancials() : null;
    }

    protected DependentFinancialsInputData getDependentFinancialsInputData() 
    {
        RuleDataAware ruleDataAware = this.getRuleDataAware();
        return (ruleDataAware instanceof DependentFinancialsInputData) ? (DependentFinancialsInputData)ruleDataAware : null;
    }
}