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

import gov.va.med.esr.common.model.financials.DependentFinancials;
import gov.va.med.esr.common.model.financials.FinancialStatement;
import gov.va.med.esr.common.model.financials.GMTThreshold;
import gov.va.med.esr.common.model.financials.IncomeTest;
import gov.va.med.esr.common.model.financials.IncomeThreshold;
import gov.va.med.esr.common.model.financials.SpouseFinancials;
import gov.va.med.esr.common.model.lookup.MeansTestStatus;
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.Relation;
import gov.va.med.fw.service.ServiceException;

/**
 * FinancialsHelperService to provide some helper methods related to the
 * financials.
 * 
 * @author Ranga Mudaiah
 * @author DNS   MANSOG
 * @version 1.0
 */
public interface FinancialsHelperService {

    /**
     * Process the 30 day pseudo ssn clock. Clock will be started if the condition matches
     * otherwise existing clock (if any) will be cancelled.
     * 
     * @param person
     * @param fStmt
     * @throws ServiceException
     */
    public void updatePseudoSsnClock(Person person, FinancialStatement fStmt) throws ServiceException;
    
    /**
     * Adjudicate the IncomeTest by setting the appropriate properties.
     * 
     * @param currentTest
     * @param status
     * @throws Exception
     */
    public void adjudicateIncomeTest(IncomeTest currentTest, MeansTestStatus status) throws ServiceException;

    /**
     * Calculate the Pseudo SSN for the spouse and all the dependents in a given
     * FinancialStatement.
     * @param stmt -
     *            a FinancialStatement
     * @throws ServiceException
     */
    public void processSsn(FinancialStatement stmt) throws ServiceException;

    /**
     * Calculate and set the Pseudo SSN for a given relation (spouse/dependent).
     * The method set the pseudo ssn only if there is no official ssn and pseudo
     * ssn reason is provided.
     * 
     * @param relation -
     *            spouse / dependent
     * @throws UnknownLookupCodeException
     * @throws UnknownLookupTypeException
     */
    public void processSsn(Relation relation) throws UnknownLookupTypeException, UnknownLookupCodeException;

    /**
     * Check if the given relation is active for the whole calendar year or not.
     * A relation is considered active if the relation, if the relation active
     * date is on or before january 01 and inactive date is after december 31 of
     * the same year.
     * 
     * @param relation
     * @return true if the relation is active, false otherwise.
     */
    public boolean isActiveRelation(Relation relation, Integer incomeYear);
    
	/**
	 * The rules for considering if a Spouse is active while transmitting a message to Vista.
	 * 
	 * If the inactive date of spouse is null OR inactive date of a spouse is within the IY and there is no other active spouse for that IY, 
	 * then consider the spouse as ACTIVE 
	 * If the inactive date of a spouse is within the IY and there IS another active spouse for that IY, then consider the
	 * spouse as INACTIVE. 
	 * If the inactive date of a spouse is after the IY and there no other active spouse for the IY, then consider the spouse as
	 * ACTIVE.  
	 * If the inactive date of a spouse is before the IY, then ALWAYS consider it as INACTIVE.
	 * 
	 * @param spouseFinancials
	 * @return boolean - spouse is active
	 */
    public boolean isActiveSpouseForVistaTransmission(SpouseFinancials spouseFinancials) ;
    
    /**
     * Get a active SpouseFinancials based for while transmitting a message to Vista.
     * 
     * @see isActiveSpouseForVistaTransmission
     * 
     * @param person
     * @param incomeYear
     * @return
     */
    public SpouseFinancials getActiveSpouseFinancialsForVistaTransmission(Person person, Integer incomeYear);

    /**
	 * The rules for considering if a Dependent is active while transmitting a message to Vista.
	 *  
	 * If the inactive date is null OR inactive date of a dependent is within the IY, then consider as ACTIVE 
	 * If inactive date is after IY, consider it ACTIVE
	 * 
	 * @param dependentFinancials
	 * @return boolean - dependent is active
	 */
    public boolean isActiveDependentForVistaTransmission(DependentFinancials dependentFinancials);
    
    
    public IncomeTest getCurrentIncomeTest(Person person);


    /**
     * Calculate the GMT Thresholds for a given income year, fips code and
     * number of extra dependents. If the extra dependents equals to zero, the
     * GMTThreshold object from the lookup service is returned. If there are
     * extra dependents, GMT threshold is calculated for each extra dependent
     * and returned.
     * 
     * @param incomeYear
     * @param fipsCode
     * @param extraDependents
     * @return GMTThreshold
     * @throws ServiceException
     */
    public GMTThreshold calculateGMTThresholds(Integer incomeYear, String fipsCode, int extraDependents)
            throws ServiceException;

    /**
     * Calculate the Income Thresholds for a given income year and number of
     * dependents. If the number of dependent is null, 7 is used as a default.
     * 
     * @param incomeYear
     * @param numberOfDependents
     * @return IncomeThreshold
     * @throws ServiceException
     */
    public IncomeThreshold calculateIncomeThresholds(Integer incomeYear, Integer numberOfDependents)
            throws ServiceException;

    /**
     * Calculate the Income Thresholds for a given income year and extra
     * dependents.
     * 
     * @param incomeYear
     * @param extraDependents
     * @return IncomeThreshold
     * @throws ServiceException
     */
    public IncomeThreshold calculateIncomeThresholds(Integer incomeYear, int extraDependents)
            throws ServiceException;

    /**
     * Returns true if the Person is subject to Means Test
     * @param person
     * @return true|false
     * @throws ServiceException
     */
    public boolean isSubjectToMeansTest(Person person) throws ServiceException;
    
    /**
     * Returns true if the Person is subject to Means Test
     * @param person
     * @return true|false
     * @throws ServiceException
     */
    public boolean isSubjectToMeansTestForBatchProcess(Person person) throws ServiceException;

    /**
     * Returns true if the Person is subject to Pharmacy Copay test.
     * @param person
     * @return true|false
     */
    public boolean isPhramacyCoPayApplicable(Person person);

    /**
     * Determines if the Means Test is permitted for this person or not.
     * 
     * @param person
     * @return true|false
     */
    public boolean isMeansTestPermitted(Person person);

    /**
     * Returns if the Hardship to this person has been granted or not.
     * @param person
     * @return
     */
    public boolean isHardShipGranted(Person person);

    /**
     * Returns if the Hardship to this person has been granted or not for a
     * given income year.
     * @param person
     * @param incomeYear
     * @return
     */
    public boolean isHardShipGranted(Person person, Integer incomeYear);

    /**
     * Returns true if the Person is allowed to edit the current income test.
     * 
     * @param person
     * @param incomeYear
     * @return
     * @throws ServiceException
     */
    public boolean isAllowedtoEditTest(Person person, Integer incomeYear) throws ServiceException;

    /**
     * Returns true if a Person is allowed to add a Means Test.
     * @param person
     * @param incomeYear
     *            TODO
     * @return
     * @throws ServiceException
     */
    public boolean isAllowedtoAddMeansTest(Person person, Integer incomeYear) throws ServiceException;

    /**
     * Returns true if the Person is allowed to add a Pharmacy Copay test
     * @param person
     * @param incomeYear
     *            TODO
     * @return
     * @throws ServiceException
     */
    public boolean isAllowedtoAddPharmacyCopayTest(Person person, Integer incomeYear) throws ServiceException;

    /**
     * Returns true if the Person is allowed to add any test.
     * @param person
     * @param incomeYear
     *            TODO
     * @return
     * @throws ServiceException
     */
    public boolean isAllowedtoAddTest(Person person, Integer incomeYear) throws ServiceException;
    
    /**
     * Returns false if the income year is 2009 or later. CR9619 VFA-SP1
     * @param person
     * @param incomeYear
     *            
     * @return
     * @throws ServiceException
     */
    public boolean isAllowedtoEditNetWorth(Person person, Integer incomeYear) throws ServiceException;
        
    /**
     * Process Spouse employment
     * 
     * @param incomingSpouseEmployment
     * @param onFileSpouseEmployment
     */
    public void updateSpouseEmployment(Employment incomingSpouseEmployment, Employment onFileSpouseEmployment);
        
    
}