package gov.va.med.esr.service.external;

import gov.va.med.esr.common.model.financials.Asset;
import gov.va.med.esr.common.model.financials.BeneficiaryTravel;
import gov.va.med.esr.common.model.financials.Debt;
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.Hardship;
import gov.va.med.esr.common.model.financials.Income;
import gov.va.med.esr.common.model.financials.IncomeTest;
import gov.va.med.esr.common.model.financials.IncomeTestStatus;
import gov.va.med.esr.common.model.financials.PatientVisitSummary;
import gov.va.med.esr.common.model.financials.SpouseFinancials;
import gov.va.med.esr.common.model.ivmdm.IVMMigration;
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.IncomeTestType;
import gov.va.med.esr.common.model.lookup.IncomeTestSource;
import gov.va.med.esr.common.model.lookup.IncomeType;
import gov.va.med.esr.common.model.lookup.VAFacility;
import gov.va.med.esr.common.model.party.Address;
import gov.va.med.esr.common.model.person.Dependent;
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.SignatureImage;
import gov.va.med.esr.common.model.person.Spouse;
import gov.va.med.esr.service.PSDelegateService;
import gov.va.med.esr.service.PersonHelperService;
import gov.va.med.esr.service.external.person.AddressInfo;
import gov.va.med.esr.service.external.person.AssetInfo;
import gov.va.med.esr.service.external.person.BeneficiaryTravelInfo;
import gov.va.med.esr.service.external.person.ConsentInfo;
import gov.va.med.esr.service.external.person.DebitInfo;
import gov.va.med.esr.service.external.person.DependentFinancialsInfo;
import gov.va.med.esr.service.external.person.DependentInfo;
import gov.va.med.esr.service.external.person.EESummary;
import gov.va.med.esr.service.external.person.EmploymentInfo;
import gov.va.med.esr.service.external.person.ExpenseInfo;
import gov.va.med.esr.service.external.person.FinancialStatementInfo;
import gov.va.med.esr.service.external.person.FinancialsInfo;
import gov.va.med.esr.service.external.person.HardshipInfo;
import gov.va.med.esr.service.external.person.IncomeInfo;
import gov.va.med.esr.service.external.person.IncomeTestInfo;
import gov.va.med.esr.service.external.person.IncomeTestStatusInfo;
import gov.va.med.esr.service.external.person.NonPrimaryFinancialStatementInfo;
import gov.va.med.esr.service.external.person.SignatureImageInfo;
import gov.va.med.esr.service.external.person.SpouseFinancialsInfo;
import gov.va.med.esr.service.external.person.SpouseInfo;
import gov.va.med.esr.service.external.person.collections.AssetCollection;
import gov.va.med.esr.service.external.person.collections.BeneficiaryTravelCollection;
import gov.va.med.esr.service.external.person.collections.DependentFinancialsCollection;
import gov.va.med.esr.service.external.person.collections.ExpenseCollection;
import gov.va.med.esr.service.external.person.collections.NonPrimaryFinancialStatementCollection;
import gov.va.med.esr.service.external.person.collections.IncomeCollection;
import gov.va.med.esr.service.external.person.collections.IncomeTestStatusCollection;
import gov.va.med.esr.service.external.person.collections.SpouseFinancialsCollection;
import gov.va.med.fw.model.lookup.Lookup;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.esr.service.IVMDMService;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class FinancialsSummaryFactoryImpl implements FinancialsSummaryFactory {
	public static final String IVMDATA = "IVMDATA";
	public static final String DELETE = "DELETE";	
	private String preciseDateTimeFormat = "yyyyMMddHHmmss";

	private PersonHelperService personHelperService = null;

	private IVMDMService ivmService = null;	

	private DemographicSummaryFactory demographicSummaryFactory = null;
	
	private PSDelegateService psDelegateService = null;
	
	protected Log logger = LogFactory.getLog(getClass());
	
	public DemographicSummaryFactory getDemographicSummaryFactory() {
		return demographicSummaryFactory;
	}


	public void setDemographicSummaryFactory(
			DemographicSummaryFactory demographicSummaryFactory) {
		this.demographicSummaryFactory = demographicSummaryFactory;
	}


	public PersonHelperService getPersonHelperService() {
		return personHelperService;
	}


	public void setPersonHelperService(PersonHelperService personHelperService) {
		this.personHelperService = personHelperService;
	}	
	
	public void applyFinancialsInfo(Person person, EESummary eeSummary, Integer incomeYear, String requestor) throws ServiceException {
		
		FinancialsInfo financialsInfo = new FinancialsInfo();
		
		//get the current incometest.
		IncomeTestInfo incomeTest =getIncomeTestInfo(person, incomeYear, requestor);
		if (incomeTest != null  ) {
			financialsInfo.setIncomeTest(incomeTest);
		}
		// CCR 12540 explicit delete for IVM means we can short-circuit applying financials info.
		if(requestor.equalsIgnoreCase(IVMDATA) && incomeTest != null && DELETE.equals(incomeTest.getComments())) {
			eeSummary.setFinancialsInfo(financialsInfo);
			return;
		}
		//Prepare the financialstatement for the current income year.
		if ( incomeTest != null && incomeTest.getIncomeYear() != null )
		{
			FinancialStatementInfo fStatement = getFinancialStatement(person, incomeTest.getIncomeYear());	
			financialsInfo.setFinancialStatement(fStatement);
			financialsInfo.setNonPrimaryFinancialsInfo(new NonPrimaryFinancialStatementCollection(addFinancialDataForNonPrimary(person,incomeTest.getIncomeYear())));			
		}

		BeneficiaryTravelInfo[] beneficiaryTravels = prepareBeneficiaryTravel(person);
		if ( beneficiaryTravels != null && beneficiaryTravels.length > 0 )
		{
			financialsInfo.setBeneficiaryTravels(new BeneficiaryTravelCollection(beneficiaryTravels));
		}
		eeSummary.setFinancialsInfo(financialsInfo);
	}
	
	
	private  BeneficiaryTravelInfo[] prepareBeneficiaryTravel(Person person) {
		Map travels = person.getBeneficiaryTravels();

		if (travels == null || travels.size() <= 0) {
			return null;
		}

		BeneficiaryTravelInfo[] beneficiaryTravels = new BeneficiaryTravelInfo[travels
				.size()];
		Iterator travelIter = travels.values().iterator();
		int i = 0;
		while (travelIter.hasNext()) {
			BeneficiaryTravel travel = (BeneficiaryTravel) travelIter.next();
			BeneficiaryTravelInfo travelInfo = new BeneficiaryTravelInfo();

			travelInfo.setDateCertified(travel.getDateCertified());
			travelInfo.setAmountCertified(travel.getAmountCertified());
			//travelInfo.setClaimDate(travel.getClaimDate());
			travelInfo.setEligible(travel.getEligible());
			//travelInfo.setYear(travel.getYear());

			beneficiaryTravels[i] = travelInfo;
			i++;
		}
		
		return beneficiaryTravels;
	}
	
	
	
	public  SignatureImageInfo[] buildSignatures(Person person) {
		
		Set signatures = person.getSignatureImages();
		if ( signatures == null ) return null;
		
		Iterator sigIter = signatures.iterator();
		
		SignatureImageInfo[] sigInfos = new SignatureImageInfo[signatures.size()];
		
		int i=0;
		while(sigIter.hasNext())
		{
			SignatureImage sig = (SignatureImage) sigIter.next();
			SignatureImageInfo sigInfo = new SignatureImageInfo();
			sigInfo.setDateIndex(sig.getDateIndex());
			sigInfo.setIncomeYear(sig.getIncomeYear());
			sigInfos[i] = sigInfo;
		}
		
		return sigInfos;
	}
	

	public  IncomeTestInfo getIncomeTestInfo(Person person, Integer incomeYear, String requestor) throws ServiceException {
		Map incomeTestsMap = person.getIncomeTests();
		IncomeTest currIncomeTest;
		if ( incomeTestsMap == null) return null;	
				
		if(requestor.equalsIgnoreCase(IVMDATA) && incomeYear != null && incomeYear.intValue() != 0){
			currIncomeTest = person.getIncomeTest(incomeYear);		
			if (currIncomeTest == null) {
				// apply special handling for CCR 12540
				IVMMigration migration = this.getIvmService().findIVMMigrationMarkedForDelete(person.getPersonEntityKey(),
						incomeYear);
				if (migration != null) {
					// IncomeTest was deleted so must notify IVM
					migration.setStampped(false); //reset to prevent endless delete signals 
					this.getIvmService().saveIVMMigration(migration);
					// CCR 12540 - create a stub for delete signal
					currIncomeTest = new IncomeTest();
					currIncomeTest.setIncomeYear(incomeYear);
					currIncomeTest.setComments(DELETE);
					// Don't associate to person
				}
			}
		}
		else{
			currIncomeTest = personHelperService.getCurrentIncomeTest(person);
			
		}						
		
		if ( currIncomeTest == null ) return null;
		
		//Iterator incomeYearItr = incomeTestsMap.keySet().iterator();
		
		//int i=0;
		//IncomeTestInfo[] incomeTestInfos = new IncomeTestInfo[incomeTestsMap.size()];
		//while( incomeYearItr.hasNext())
		//{
			
		//	Integer year = (Integer) incomeYearItr.next();
			
		//	IncomeTest test = person.getIncomeTest(year);
			
			IncomeTestInfo  incomeTestInfo = new IncomeTestInfo();
			
			if ( currIncomeTest.getHardship() != null)
			{
				Hardship hardShip = currIncomeTest.getHardship();
				HardshipInfo hardshipInfo = new HardshipInfo();
				
				hardshipInfo.setHardshipGranted(hardShip.getHardshipGranted());
				hardshipInfo.setReviewDate(hardShip.getReviewDate());
				hardshipInfo.setEffectiveDate(hardShip.getEffectiveDate());
				hardshipInfo.setSiteGrantingHardship(hardShip.getSiteGrantingHardship() != null? hardShip.getSiteGrantingHardship().getSiteNumberAndName():null);
				hardshipInfo.setReason(hardShip.getReason());				
				incomeTestInfo.setHardshipInfo(hardshipInfo);
			}
			
			incomeTestInfo.setIncomeYear(currIncomeTest.getIncomeYear());
			incomeTestInfo.setDiscloseFinancialInformation(currIncomeTest.getDiscloseFinancialInformation());
			incomeTestInfo.setAgreesToPayDeductible(currIncomeTest.getAgreesToPayDeductible());
			incomeTestInfo.setEffectiveDate(currIncomeTest.getEffectiveDate());
			incomeTestInfo.setTotalNumberOfDependents(currIncomeTest.getTotalNumberOfDependents());
			incomeTestInfo.setPreviousYearThresholdApplies(currIncomeTest.getPreviousYearThresholdApplies());
			incomeTestInfo.setPrimaryIncomeTest(currIncomeTest.getPrimaryIncomeTest());
			incomeTestInfo.setFutureTest(currIncomeTest.getFutureTest());
			incomeTestInfo.setIncomeTestsource(currIncomeTest.getSource() != null? currIncomeTest.getSource().getDescription():null);
			incomeTestInfo.setIncomeTestType(currIncomeTest.getType()!=null?currIncomeTest.getType().getDescription():null);
			incomeTestInfo.setThresholdA(currIncomeTest.getThresholdA());
			incomeTestInfo.setGmtThresholdAmount(currIncomeTest.getGmtThresholdAmount());
			incomeTestInfo.setSiteConductingTest(currIncomeTest.getSiteConductingTest()!=null?currIncomeTest.getSiteConductingTest().getSiteNumberAndName():null);
			incomeTestInfo.setAdjudicationDate(currIncomeTest.getAdjudicationDate());
			incomeTestInfo.setIvmTestCompletionDate(currIncomeTest.getIVMTestCompletionDate());
			incomeTestInfo.setIncomeVerificationStatus(currIncomeTest.getIncomeVerificationStatus()!=null?currIncomeTest.getIncomeVerificationStatus().getCode():null);
			incomeTestInfo.setIncomeVerificationStatusDate(currIncomeTest.getIncomeVerificationStatusDate());
			incomeTestInfo.setRefusedToSign(currIncomeTest.getRefusedToSign());
			incomeTestInfo.setReasonMTNoLongerRequired(currIncomeTest.getReasonMTNoLongerRequired());
			incomeTestInfo.setDateMTNoLongerRequired(currIncomeTest.getDateMTNoLongerRequired());
			incomeTestInfo.setTotalIncome(currIncomeTest.getTotalIncome());
			incomeTestInfo.setNetIncome(currIncomeTest.getNetIncome());
			incomeTestInfo.setDeductibleExpenses(currIncomeTest.getDeductibleExpenses());
			incomeTestInfo.setNetWorth(currIncomeTest.getNetWorth());			
			incomeTestInfo.setComments(currIncomeTest.getComments());
			incomeTestInfo.setIncomeTestReportDate(currIncomeTest.getModifiedOn());
			incomeTestInfo.setNetworthThreshold(currIncomeTest.getNetworthThreshold());
			incomeTestInfo.setPensionThreshold(currIncomeTest.getPensionThreshold());
			incomeTestInfo.setChildIncomeExclusionThreshold(currIncomeTest.getChildIncomeExclusionThreshold());
			incomeTestInfo.setCadAdjusted(currIncomeTest.getCadAdjusted());
			if ( currIncomeTest.getStatuses() != null)
			{
				IncomeTestStatus testStatus = currIncomeTest.getIncomeTestStatus(currIncomeTest.getType());
				if ( testStatus != null)
				{
					IncomeTestStatusInfo itsInfo = new IncomeTestStatusInfo();
					itsInfo.setCompletedDate(testStatus.getCompletedDate());
					itsInfo.setDeterminedStatus(testStatus.getDeterminedStatus()!=null?testStatus.getDeterminedStatus().getDescription():null);
					itsInfo.setLastEditedDate(testStatus.getLastEditedDate());
					itsInfo.setStatus(testStatus.getStatus()!=null? testStatus.getStatus().getDescription():null);
					itsInfo.setIncomeTestType(testStatus.getType()!=null?testStatus.getType().getDescription():null);
					//added for CCR 11871--
					IncomeTestStatusInfo mtInfo = null; 
					IncomeTestStatusInfo mtInfo1 = null;
					IncomeTestStatusInfo mtInfo2 = null;
					IncomeTestStatusInfo mtInfo3 = null;
					
					int i = 0;
		            
                    //mt and rx copy statuses
		            Set statuses1 = currIncomeTest.getStatuses();
		            if (statuses1 != null) {
		                for (Iterator iter=statuses1.iterator(); iter.hasNext(); ) {
		                    Object statusObj = iter.next ();
		                    if (statusObj != null && statusObj instanceof IncomeTestStatus) {
		                        IncomeTestStatus incomeTestStatus = (IncomeTestStatus) statusObj;
		                        
		                        String statusDesc = null;
		                        String statusType = null;
		                        if (incomeTestStatus.getStatus() != null ){
		                        	statusDesc = incomeTestStatus.getStatus().getDescription();
		                        }
		                        if(incomeTestStatus.getType() != null) {
		                        	statusType = incomeTestStatus.getType().getDescription();
		                            if (incomeTestStatus.getType().getCode().equals(
		                            		IncomeTestType.CODE_MEANS_TEST.getName())) {
		                            	if(!testStatus.getType().getCode().equals(IncomeTestType.CODE_MEANS_TEST.getName())){
		                            		mtInfo = new IncomeTestStatusInfo();
		                            	mtInfo.setStatus(statusDesc);
		                            	mtInfo.setIncomeTestType(statusType);
		                            	i++;
		                            	}
		                            }
		                            else if (incomeTestStatus.getType().getCode().equals(
		                            		IncomeTestType.CODE_CO_PAY_EXEMPTION_TEST.getName())) {
		                            	if(!testStatus.getType().getCode().equals(IncomeTestType.CODE_CO_PAY_EXEMPTION_TEST.getName())){
		                            		mtInfo1 = new IncomeTestStatusInfo();
		                            	mtInfo1.setStatus(statusDesc);
		                            	mtInfo1.setIncomeTestType(statusType);
		                            	i++;
		                            	}
		                            }
                                    else if (incomeTestStatus.getType().getCode().equals(
                                            IncomeTestType.CODE_LTC_CO_PAY_TEST.getName())) {
                                    	if(!testStatus.getType().getCode().equals(IncomeTestType.CODE_LTC_CO_PAY_TEST.getName())){
                                    		mtInfo2 = new IncomeTestStatusInfo(); 
                                    	mtInfo2.setStatus(statusDesc);
                                    	mtInfo2.setIncomeTestType(statusType);
                                    	i++;
                                    	}
                                    }
                                    else if (incomeTestStatus.getType().getCode().equals(
                                            IncomeTestType.CODE_LTC_CO_PAY_EXEMPTION_TEST.getName())) {
                                    	if(!testStatus.getType().getCode().equals(IncomeTestType.CODE_LTC_CO_PAY_EXEMPTION_TEST.getName())){
                                    	mtInfo3 = new IncomeTestStatusInfo();
                                    	mtInfo3.setStatus(statusDesc);
                                    	mtInfo3.setIncomeTestType(statusType);
                                    	i++;
                                    	}
                                    }
		                        }
		                    }                        
		                }
		            }
					//end CCR11871
					IncomeTestStatusInfo[] statuses = new IncomeTestStatusInfo[i+1];
					statuses[0] = itsInfo;
					int j = 1;
					if(mtInfo != null) {
						statuses[j] = mtInfo;
						j++;
					}
					if(mtInfo1 != null) {
						statuses[j] = mtInfo1;
						j++;
					}
					if(mtInfo2 != null) {
						statuses[j] = mtInfo2;
						j++;
					}
					if(mtInfo3 != null) {
						statuses[j] = mtInfo3;
						j++;
					}
					
					if ( statuses != null && statuses.length > 0 )
					{
						incomeTestInfo.setStatuses(new IncomeTestStatusCollection(statuses));
					}
				}
			}	
			
			incomeTestInfo.setNetWorth(currIncomeTest.getNetWorth());
			
			//incomeTestInfos[i] = incomeTestInfo;
			//i++;
		//}
			if(currIncomeTest.getGmtAddress() != null){
				AddressInfo gmtAddress = new AddressInfo();
				gmtAddress.setLine1(currIncomeTest.getGmtAddress().getInternalLine1());
				gmtAddress.setLine2(currIncomeTest.getGmtAddress().getInternalLine2());
				gmtAddress.setLine3(currIncomeTest.getGmtAddress().getInternalLine3());
				gmtAddress.setCity(currIncomeTest.getGmtAddress().getCity());
				gmtAddress.setState(currIncomeTest.getGmtAddress().getState());
				gmtAddress.setCounty(currIncomeTest.getGmtAddress().getCounty());
				gmtAddress.setCountry(currIncomeTest.getGmtAddress().getCountry());
				gmtAddress.setZipCode(currIncomeTest.getGmtAddress().getInternalZipCode());
				gmtAddress.setZipcode(currIncomeTest.getGmtAddress().getInternalZipCode());
				gmtAddress.setZipPlus4(currIncomeTest.getGmtAddress().getInternalZipPlus4());
				incomeTestInfo.setGmtAddressInfo(gmtAddress);
			}
		
		incomeTestInfo.setGmtThresholdAmount(currIncomeTest.getGmtThresholdAmount());
			
		return incomeTestInfo;
	}
	
	public  FinancialStatementInfo getFinancialStatement(Person person, Integer incomeYear) {

		//FinancialStatement statement = person.getFinancialStatement(incomeYear);

		//if (statement == null)
		//	return null;

		//Collection keys = fStatementMap.keySet();

		//Iterator keyIter = keys.iterator();
		
		//FinancialStatementInfo[] fStatementInfoArray = new FinancialStatementInfo[fStatementMap.size()];
		
		//int fStatementCount = 0;
		//while (keyIter.hasNext()) {
		//	Integer year = (Integer) keyIter.next();
		//	if (year != null) {
		IncomeTest incomeTest = person.getIncomeTest(incomeYear);
		PatientVisitSummary summary = person.getPatientVisitSummary(incomeYear, incomeTest.getSiteConductingTest());
		FinancialStatementInfo fStatementInfo = new FinancialStatementInfo();
				FinancialStatement statement = person
						.getFinancialStatement(incomeYear);				
				if (statement != null) {
					
					fStatementInfo.setMarriedLastCalendarYear(statement
							.getMarriedLastCalendarYear());
					fStatementInfo.setNumberOfDependentChildren(statement
							.getNumberOfDependentChildren());
					fStatementInfo.setContributionToSpouse(statement
							.getContributionToSpouse());	
					fStatementInfo.setOutpatientDays(summary == null ? null :summary.getOutpatientDays());
					fStatementInfo.setInpatientDays(summary == null ? null : summary.getInpatientDays());					
					fStatementInfo.setLastVisitDate(summary == null ? null : summary.getLastVisitDate());
					Date modifiedOn = summary == null ? incomeTest.getModifiedOn() : summary.getModifiedOn();
					fStatementInfo.setVamcReportDate(modifiedOn);
					
					fStatementInfo.setSpousalSupportInd(statement.getContributedToSpouseInd());
					
					DependentFinancialsInfo[] dFins = getDependentFinInfo(statement);
					
					if ( dFins != null)
					{
						fStatementInfo
							.setDependentFinancialsList(new DependentFinancialsCollection(dFins));
					}
					
					IncomeInfo[] incomes = getIncomeInfo(statement.getIncome());
					if ( incomes != null && incomes.length > 0 )
					{
						fStatementInfo.setIncomes(new IncomeCollection(incomes));
					}
					
					
					AssetInfo[] assests = getAssetInfo(statement.getAssets());
					if ( assests != null)
					{
						fStatementInfo
							.setAssets(new AssetCollection(assests));
					}
					
					ExpenseInfo[] expenses = getEexpensesInfo(statement.getExpenses());
					if ( expenses != null && expenses.length > 0 )
					{
						fStatementInfo.setExpenses(new ExpenseCollection(expenses));
					}
					
					Debt debt = statement.getDebt();
					
					if (debt != null)
					{
						DebitInfo debitInfo = new DebitInfo();
						debitInfo.setAmount(debt.getAmount());
						fStatementInfo.setDebits(debitInfo);
					}
					
					fStatementInfo.setIncomeYear(incomeYear);
					
					SpouseFinancialsInfo[] sFins = getSpouseFinInfo(statement);
					
					if ( sFins != null && sFins.length > 0 )
					{
						fStatementInfo
							.setSpouseFinancialsList(new SpouseFinancialsCollection(sFins));
					}					
					//fStatementInfoArray[fStatementCount] = fStatementInfo;
					//fStatementCount++;
				}
			//}
		//}

		return fStatementInfo;
	}

	private  DependentFinancialsInfo[] getDependentFinInfo(
			FinancialStatement statement) {
		if(statement==null ||statement.getDependentFinancials() ==null ||(statement.getDependentFinancials()).size()==0){
			return null;
		}
		Set dependentFinanSet = statement.getDependentFinancials();
		Iterator itr = dependentFinanSet != null ? dependentFinanSet.iterator()
				: null;
		int count = 0;
		DependentFinancialsInfo[] dependentFinInfoArray = new DependentFinancialsInfo[dependentFinanSet
				.size()];
		while (itr != null && itr.hasNext()) {
			DependentFinancials dependentFinancials = (DependentFinancials) itr
					.next();
			DependentFinancialsInfo dependentFinInfo = new DependentFinancialsInfo();

			if (dependentFinancials.getReportedOn() != null &&
					dependentFinancials.getReportedOn().getRelationship() != null)
			{
				//dependentFinInfo.s(dependentFinancials.getReportedOn().getRelationship().getDescription());
				dependentFinInfo.setDependentInfo(buildDependent(dependentFinancials.getReportedOn()));
			}
			
			dependentFinInfo.setAmountContributedToSupport(dependentFinancials
					.getAmountContributedToSupport());
			dependentFinInfo.setAttendedSchool(dependentFinancials
					.getAttendedSchool());
			dependentFinInfo.setHasIncome(dependentFinancials.getHasIncome());
			dependentFinInfo.setContributedToSupport(dependentFinancials
					.getContributedToSupport());
			dependentFinInfo.setIncapableOfSelfSupport(dependentFinancials
					.getIncapableOfSelfSupport());
			dependentFinInfo.setIncomeAvailableToPatient(dependentFinancials
					.getIncomeAvailableToPatient());				
			
			IncomeInfo[] incomes = getIncomeInfo(dependentFinancials.getIncome());
			if ( incomes != null && incomes.length > 0)
			dependentFinInfo.setIncomes(new IncomeCollection(incomes));
			
			AssetInfo[] assets = getAssetInfo(dependentFinancials.getAssets());
			if ( assets != null)
			{
				dependentFinInfo.setAssets(new AssetCollection(assets));
			}
			
			ExpenseInfo[] expenses = getEexpensesInfo(dependentFinancials.getExpenses());
			if ( expenses != null && expenses.length > 0 )
			{
				dependentFinInfo
					.setExpenses(new ExpenseCollection(expenses));
			}
			
			Debt debt = dependentFinancials.getDebt();
			if ( debt != null)
			{
				DebitInfo dependentDebitInfo = new DebitInfo();
				dependentDebitInfo.setAmount(debt.getAmount());
				dependentFinInfo.setDebits(dependentDebitInfo);
			}
			dependentFinInfo.setIncomeYear(dependentFinancials.getIncomeYear());
			dependentFinInfo.setLivedWithPatient(dependentFinancials.getLivedWithPatient());
			dependentFinInfoArray[count] = dependentFinInfo;
			count++;
		}
		return dependentFinInfoArray;
	}

	private  SpouseFinancialsInfo[] getSpouseFinInfo(FinancialStatement statement) {
		if(statement==null ||statement.getSpouseFinancials() ==null ||(statement.getSpouseFinancials()).size()==0){
			return null;
		}
		
		Set spousetFinanSet = statement.getSpouseFinancials();
		Iterator itr = spousetFinanSet != null ? spousetFinanSet.iterator()
				: null;
		int count = 0;
		SpouseFinancialsInfo[] spouseFinInfoArray = new SpouseFinancialsInfo[spousetFinanSet
				.size()];
		while (itr != null && itr.hasNext()) {
			SpouseFinancials spouseFinancials = (SpouseFinancials) itr.next();
		
			SpouseFinancialsInfo spouseFinInfo = new SpouseFinancialsInfo();	
			
			spouseFinInfo.setContributedToSpouseInd(statement.getContributedToSpouseInd());
			
			spouseFinInfo.setLivedWithPatient(spouseFinancials.getLivedWithPatient());
			spouseFinInfo.setValidDependent(spouseFinancials.getValidDependent());
			spouseFinInfo.setIncomeYear(spouseFinancials.getIncomeYear());				
			
			if (spouseFinancials.getReportedOn() != null )
			spouseFinInfo.setSpouse(buildSpouse(spouseFinancials.getReportedOn()));	
			
			
			IncomeInfo[] incomes = getIncomeInfo(spouseFinancials.getIncome());
			if ( incomes != null && incomes.length > 0)
			{
				spouseFinInfo.setIncomes(new IncomeCollection(incomes));
			}
			
			
			AssetInfo[] assests = getAssetInfo(spouseFinancials.getAssets());
			if ( assests != null)
			{
				spouseFinInfo
					.setAssets(new AssetCollection(assests));
			}
			
			ExpenseInfo[] expenses = getEexpensesInfo(spouseFinancials.getExpenses());
			if ( expenses != null && expenses.length > 0 )
			{
				spouseFinInfo.setExpenses(new ExpenseCollection(expenses));
			}
			
			Debt debt = spouseFinancials.getDebt();
			
			if (debt != null)
			{
				DebitInfo dependentDebitInfo = new DebitInfo();
				dependentDebitInfo.setAmount(debt.getAmount());
				spouseFinInfo.setDebits(dependentDebitInfo);
			}
			spouseFinInfoArray[count] = spouseFinInfo;
			count++;
		}

		return spouseFinInfoArray;

	}
	
	private NonPrimaryFinancialStatementInfo[] addFinancialDataForNonPrimary(Person person, Integer incomeYear ) {

		IncomeTest incomeTest = person.getIncomeTest(incomeYear);
		Set summaries = person.getPatientVisitSummaries(incomeTest.getIncomeYear());
		String testSiteCode = getSiteConductingTest(incomeTest);		
		List<NonPrimaryFinancialStatementInfo> fStatementInfoArrayList = new ArrayList<NonPrimaryFinancialStatementInfo>();		
		NonPrimaryFinancialStatementInfo[] fStatementInfoArray = null;		
		
		for (Iterator iter = summaries.iterator(); iter.hasNext();) {
			PatientVisitSummary summary = (PatientVisitSummary) iter.next();
			VAFacility facilityVisited = summary.getFacilityVisited();
			String facilityVisitedCode =  facilityVisited == null ? "" : facilityVisited.getCode();
			Date modifiedOn = summary == null ? incomeTest.getModifiedOn() : summary.getModifiedOn();
			
			if (!facilityVisitedCode.equals(testSiteCode)) {
				FinancialStatement statement = person
				.getFinancialStatement(incomeYear);				
				if (statement != null) {
					NonPrimaryFinancialStatementInfo fStatementInfo = new NonPrimaryFinancialStatementInfo();
						
					fStatementInfo.setOutpatientDays(summary.getOutpatientDays());
					fStatementInfo.setInpatientDays(summary.getInpatientDays());
					fStatementInfo.setLastVisitDate(summary.getLastVisitDate());
					fStatementInfo.setIncomeYear(incomeYear);
					fStatementInfo.setFacilityVisitedCode(summary.getFacilityVisited() == null? null : summary.getFacilityVisited().getSiteNumberAndName());
					fStatementInfo.setVamcReportDate(modifiedOn);
					fStatementInfoArrayList.add(fStatementInfo);	
				}
			}
		}
		if(fStatementInfoArrayList.size() >0){			
			fStatementInfoArray = new NonPrimaryFinancialStatementInfo[fStatementInfoArrayList.size()];
			int i = 0;
			for (Iterator iter = fStatementInfoArrayList.iterator(); iter.hasNext();){
				NonPrimaryFinancialStatementInfo fStatementInfo = (NonPrimaryFinancialStatementInfo) iter.next();				
				fStatementInfoArray[i] = fStatementInfo;
				i++;
			}			
		}		
		return fStatementInfoArray;	
	}
	
	public ConsentInfo applyConsentInfo(Person person, Integer incomeYear) {

		IncomeTest currIncomeTest;
		if(incomeYear == null || incomeYear.intValue() == 0){			
			currIncomeTest = personHelperService.getCurrentIncomeTest(person);			
		}
		else{			
			currIncomeTest = person.getIncomeTest(incomeYear);			
		}

		if ( currIncomeTest == null ) return null;

		ConsentInfo consentInfo = new ConsentInfo();
		addConsentData(person.getSignatureImage(currIncomeTest.getIncomeYear()), consentInfo);
		return consentInfo;

	}
	
	private void addConsentData(SignatureImage sigImage, ConsentInfo consentInfo) {
        if (sigImage == null) {
            return;
        }
        
        consentInfo.setConsentImagingSite(sigImage.getSiteSubmittingImage() != null ?sigImage.getSiteSubmittingImage().getSiteNumberAndName(): null);
        consentInfo.setConsentAuthCode(sigImage.getSignatureIndicator() != null ?sigImage.getSignatureIndicator().getCode(): null);
        consentInfo.setConsentImageIndexNumber(sigImage.getImageIdNumber());
        consentInfo.setConsentLastUpdateDate(sigImage.getModifiedOn());
        consentInfo.setConsentReportDate(sigImage.getDateIndex());               
    }
	
	private String getSiteConductingTest(IncomeTest test)  {
        String source = getCode(test.getSource());
        String siteCondTestCode = getCode(test.getSiteConductingTest());
        if (siteCondTestCode == null && IncomeTestSource.CODE_HEC.getCode().equals(source))
            return VAFacility.CODE_HEC.getCode();
        return siteCondTestCode;
    }
	
	private String getCode(Lookup lookup) {
        return lookup == null ? null : lookup.getCode();
    }

	private  IncomeInfo[] getIncomeInfo(Map incomeMap) {
		if(incomeMap ==null || incomeMap.isEmpty()){
			return null;
		}
		IncomeInfo[] incomeInfoArray = new IncomeInfo[incomeMap.size()];
		Collection incomeKeys = incomeMap != null ? incomeMap.keySet() : null;
		if (incomeKeys != null) {
			Iterator incomeIter = incomeKeys.iterator();
			int incomeCount = 0;
			while (incomeIter.hasNext()) {
				IncomeType incomeType = (IncomeType) incomeIter.next();
				if (incomeType != null) {
					Income income =(Income)incomeMap.get(incomeType);
					IncomeInfo incomeInfo = new IncomeInfo();
					incomeInfo.setAmount(income.getAmount());
					incomeInfo.setType(income.getType().getDescription());
					incomeInfo.setIncomeReportDate(income.getModifiedOn());
					incomeInfoArray[incomeCount] = incomeInfo;
					incomeCount++;
				}
			}
		}
		return incomeInfoArray;
	}

	private  AssetInfo[] getAssetInfo(Map assetsMap) {

		if(assetsMap ==null ||assetsMap.isEmpty()){
			return null;
		}
		AssetInfo[] assetInfoArray = new AssetInfo[assetsMap.size()];
		Collection assetKeys = assetsMap != null ? assetsMap.keySet() : null;
		if (assetKeys != null) {
			Iterator assetIter = assetKeys.iterator();
			int assetCount = 0;
			while (assetIter.hasNext()) {
				AssetType assetType = (AssetType) assetIter.next();
				if (assetType != null) {
					Asset asset = (Asset)assetsMap.get(assetType);
					AssetInfo assetInfo = new AssetInfo();
					assetInfo.setAmount(asset.getAmount());
					assetInfo.setAssetType(asset.getType().getDescription());
					assetInfo.setAssetReportDate(asset.getModifiedOn());
					assetInfoArray[assetCount] = assetInfo;
					assetCount++;
				}
			}
		}
		return assetInfoArray;

	}

	private  ExpenseInfo[] getEexpensesInfo(Map expensesMap) {

		if(expensesMap ==null ||expensesMap.isEmpty()){
			return null;
		}
		ExpenseInfo[] expenseInfoArray = new ExpenseInfo[expensesMap.size()];
		Collection expenseKeys = expensesMap != null ? expensesMap.keySet()
				: null;
		if (expenseKeys != null) {
			Iterator expenseIter = expenseKeys.iterator();
			int expenseCount = 0;
			while (expenseIter.hasNext()) {
				ExpenseType expenseType = (ExpenseType) expenseIter.next();
				if (expenseType != null) {
					Expense expense =(Expense)expensesMap.get(expenseType); 
					ExpenseInfo expenseInfo = new ExpenseInfo();
					expenseInfo.setAmount(expense.getAmount());
					expenseInfo.setExpenseType(expense.getType().getDescription());
					expenseInfo.setExpenseReportDate(expense.getModifiedOn());
					expenseInfoArray[expenseCount] = expenseInfo;
					expenseCount++;
				}
			}

		}
		return expenseInfoArray;
	}

	public  DependentInfo buildDependent(Dependent dependent)
	{
		if ( dependent == null) return null;
		
		DependentInfo dependentInfo = new DependentInfo();
		dependentInfo = (DependentInfo)demographicSummaryFactory.populateRelationInfo(dependent, dependentInfo);
		
		return dependentInfo;
	}
	
	
	public  SpouseInfo buildSpouse(Spouse spouse) {
		if ( spouse == null) return null;
		
		SpouseInfo spouseInfo = new SpouseInfo();
		spouseInfo = (SpouseInfo)demographicSummaryFactory.populateRelationInfo(spouse, spouseInfo);
		
		//set maiden name
		spouseInfo.setMaidenName(spouse.getMaidenName());
		//set addresses
		Address address = spouse.getAddress();
		AddressInfo addressinfo = demographicSummaryFactory.buildAddressInfo(address);
		spouseInfo.setAddress(addressinfo);
		
		//set employments.
		Employment employment = spouse.getEmployment();
		EmploymentInfo employmentInfo = demographicSummaryFactory.buildEmployment(employment);
		
		spouseInfo.setEmployments(employmentInfo);
		return spouseInfo;
	}
	
	public Set getVisitedSites(Person person)throws ServiceException{
		Set sites = null;
		
		sites = psDelegateService.getSites(person.getVPIDEntityKey());		
		return sites;
	}


	public PSDelegateService getPsDelegateService() {
		return psDelegateService;
	}


	public void setPsDelegateService(PSDelegateService psDelegateService) {
		this.psDelegateService = psDelegateService;
	}
	
	private String toPreciseDateTimeFormat(Date date) {
        if (date != null) {
            SimpleDateFormat format = new SimpleDateFormat(preciseDateTimeFormat);
            return format.format(date);        
        }
        return "";
    }


	public IVMDMService getIvmService() {
		return ivmService;
	}


	public void setIvmService(IVMDMService ivmService) {
		this.ivmService = ivmService;
	}
	
}
