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

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

import gov.va.med.fw.rule.RuleDataAware;
import gov.va.med.fw.util.StringUtils;
import gov.va.med.esr.common.infra.ImpreciseDateUtils;
import gov.va.med.esr.common.model.financials.FinancialStatement;
import gov.va.med.esr.common.model.financials.SpouseFinancials;
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.person.Spouse;
import gov.va.med.esr.common.rule.SpouseFinancialInput;
import gov.va.med.esr.common.rule.data.SpouseFinancialsInputData;

/**
 * @author Carlos Ruiz, Muddaiah Ranga
 * @version 1.0
 */
public class SpouseFinancialInputParameter extends AbstractFinancialInputParameter 
                                           implements SpouseFinancialInput {

    private static final long serialVersionUID = -5654960855600888352L;

    public SpouseFinancialInputParameter() 
    {
        super();
    }

    public boolean isDemographicUpdate()
    {
        return (getSpouseFinancialInputData() != null) ? getSpouseFinancialInputData().isDemographicUpdate() : false;
    }
    
    public BigDecimal getAssetAmount(AssetType.Code expenseType) {
        BigDecimal amount = getAssetAmount(getIncomingSpouseFinancials(),
                expenseType);
        return amount == null ? new BigDecimal(0d) : amount;
    }

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

    public BigDecimal getExpenseAmount(ExpenseType.Code expenseType) {
        BigDecimal amount = getExpenseAmount(getIncomingSpouseFinancials(),
                expenseType);
        return amount == null ? new BigDecimal(0d) : amount;
    }
    
    public BigDecimal getDebtAmount() {
        SpouseFinancials spouseFinancials = getIncomingSpouseFinancials();
        return (spouseFinancials != null && spouseFinancials.getDebt() != null) ? spouseFinancials.getDebt().getAmount() : new BigDecimal(0d);
    }
    
    public BigDecimal getSpousalContributionAmount()
    {
        FinancialStatement stmt = getIncomingFinancialStatement();
        return (stmt != null && stmt.getContributionToSpouse() != null) ? stmt.getContributionToSpouse() : new BigDecimal(0d);
    }
    
    @Override
    public Boolean getContributedToSpouseInd() {
        // ES 4.2_CodeCR13338_CR_Rule Layer Modifications for Decommissioning Spousal/Dependent Support 
        FinancialStatement stmt = getIncomingFinancialStatement();
        if (stmt != null) {
            return stmt.getContributedToSpouseInd();
        } 
        return null;
    }

    public boolean isContributionInRange(double lower, double upper)
    {
        FinancialStatement stmt = getIncomingFinancialStatement();
        if(stmt != null && stmt.getContributionToSpouse() != null)
        {
            return this.isInRange(stmt.getContributionToSpouse(),lower,upper);
        }
        return true;
    }
    
    public boolean isIncomeInRange(double lower, double upper)
    {
        SpouseFinancials spouseFinancials  = getIncomingSpouseFinancials();
        if(spouseFinancials != null && spouseFinancials.getIncome() != null)
        {
            return this.isIncomeInRange(spouseFinancials.getIncome().values(),lower,upper);
        }
        return true;
    }
    
    public boolean isExpenseInRange(double lower, double upper)
    {
        SpouseFinancials spouseFinancials  = getIncomingSpouseFinancials();
        if(spouseFinancials != null && spouseFinancials.getExpenses() != null)
        {
            return this.isExpenseInRange(spouseFinancials.getExpenses().values(),lower,upper);
        }
        return true;
    }
    
    public boolean isAssetInRange(double lower, double upper)
    {
        SpouseFinancials spouseFinancials  = getIncomingSpouseFinancials();
        if(spouseFinancials != null && spouseFinancials.getAssets() != null)
        {
            return this.isAssetInRange(spouseFinancials.getAssets().values(),lower,upper);
        }
        return true;
    }
    
    public boolean isDebtInRange(double lower, double upper) 
    {
        return this.isInRange(this.getDebtAmount(), lower, upper);
    }

    public String getSpouseGivenName()
    {
        String givenName = this.getRelationGivenName(getSpouse());
        return (StringUtils.isNotEmpty(givenName)) ? givenName : null;
    }
    
    public String getSpouseFamilyName()
    {
        String familyName = this.getRelationFamilyName(getSpouse());
        return (StringUtils.isNotEmpty(familyName)) ? familyName : null;
    }
    
    public Date getSpouseDateOfBirth() 
    {
        return getRelationBirthDate(getSpouse());
    }

    public String getSpouseSSN() {
        return getRelationSSN(getSpouse());
    }
    
    public boolean isSpouseSSNUsed() {
        return this.isRelationSSNUsed(getIncomingSpouseFinancials());
    }

    public boolean hasSpouseData() {
        return this.getSpouse() != null;
    }

    public boolean isFinancialInformationProvidedForSpouse() {
        return this.getIncomingSpouseFinancials() != null;
    }
    
    public Boolean getSpouseLivesWithVeteran()
    {
        SpouseFinancials fianacial = this.getIncomingSpouseFinancials();
        return fianacial.getLivedWithPatient();
    }
    
    public boolean isSpouseLivesWithVeteran()
    {
        SpouseFinancials spf = this.getIncomingSpouseFinancials();
        if (spf != null && spf.getLivedWithPatient() != null){
            return spf.getLivedWithPatient().booleanValue();
        }
        return false;
    }

    public Date getMarriageDate() 
    {
        return (getSpouse() != null) ? 
                ImpreciseDateUtils.getDateWithDefault(getSpouse().getMarriageDate()) : null;
    }

    public Date getSpouseInactiveDate() 
    {
        return getRelationInActiveDate(this.getSpouse());
    }

    private Spouse getSpouse() 
    {
        SpouseFinancials sf = this.getIncomingSpouseFinancials();
        return (sf != null) ? sf.getReportedOn() : null;
    }

    protected SpouseFinancials getIncomingSpouseFinancials() {
        return getSpouseFinancialInputData().getIncomingSpouseFinancials();
    }
    
    protected SpouseFinancialsInputData getSpouseFinancialInputData() 
    {
        RuleDataAware ruleDataAware = this.getRuleDataAware();
        return (ruleDataAware instanceof SpouseFinancialsInputData) ? (SpouseFinancialsInputData)ruleDataAware : null;
    }
}