package gov.va.med.esr.voa.validator;

import gov.va.med.esr.common.model.lookup.AssetType;
import gov.va.med.esr.common.model.lookup.Country;
import gov.va.med.esr.common.model.lookup.ExpenseType;
import gov.va.med.esr.common.model.lookup.IncomeType;
import gov.va.med.esr.voa.common.ErrorCode;
import gov.va.med.esr.voa.util.ServiceUtils;
import gov.va.med.esr.voa.webservice.AddressInfo;
import gov.va.med.esr.voa.webservice.AssetCollection;
import gov.va.med.esr.voa.webservice.AssetInfo;
import gov.va.med.esr.voa.webservice.DependentFinancialsCollection;
import gov.va.med.esr.voa.webservice.DependentFinancialsInfo;
import gov.va.med.esr.voa.webservice.DependentInfo;
import gov.va.med.esr.voa.webservice.ExpenseCollection;
import gov.va.med.esr.voa.webservice.ExpenseInfo;
import gov.va.med.esr.voa.webservice.FinancialStatementInfo;
import gov.va.med.esr.voa.webservice.FinancialsInfo;
import gov.va.med.esr.voa.webservice.IncomeCollection;
import gov.va.med.esr.voa.webservice.IncomeInfo;
import gov.va.med.esr.voa.webservice.SpouseFinancialsCollection;
import gov.va.med.esr.voa.webservice.SpouseFinancialsInfo;
import gov.va.med.esr.voa.webservice.SpouseInfo;
import gov.va.med.esr.voa.webservice.SsnCollection;
import gov.va.med.esr.voa.webservice.SsnInfo;
import gov.va.med.fw.util.StringUtils;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;

/**
 * Validate Financial Information
 */
public class FinancialInfoValidator extends AbstractValidator {

	// Constant, limit of 30 characters.
	private static final int LIMIT_30_CHARS = 30;

	// Minimum decimal value accepted.
	private static final BigDecimal MINIMUM = new BigDecimal(0.0);

	// Maximum decimal value accepted.
	private static final BigDecimal MAXIMUM = new BigDecimal(9999999.99);

	@SuppressWarnings("rawtypes")
	@Override
	public boolean supports(Class clazz) {
		return FinancialsInfo.class.equals(clazz);
	}

	@Override
	public void validate(Object target, Errors errors) {
		logger.debug("FinancialsInfo validation...");

		if (target != null) {
			FinancialsInfo financialsInfo = (FinancialsInfo) target;

			FinancialStatementInfo financialStatementInfo = financialsInfo
					.getFinancialStatement();
			if (financialStatementInfo != null) {
				// validate spouse information.
				SpouseFinancialsCollection spouseFinancialsCollection = financialStatementInfo
						.getSpouseFinancialsList();
				if (spouseFinancialsCollection != null) {
					List<SpouseFinancialsInfo> spouseFinancialsInfoList = spouseFinancialsCollection
							.getSpouseFinancials();
					for (SpouseFinancialsInfo spouseFinancialsInfo : spouseFinancialsInfoList) {
						validateSpouseFinancialInfo(spouseFinancialsInfo,
								errors);
						break;
					}
				}

				// validate children information.
				DependentFinancialsCollection dependentFinancialsCollection = financialStatementInfo
						.getDependentFinancialsList();
				if (dependentFinancialsCollection != null) {
					List<DependentFinancialsInfo> dependentFinancialsList = dependentFinancialsCollection
							.getDependentFinancials();
					for (DependentFinancialsInfo dependentFinancialsInfo : dependentFinancialsList) {
						validateDependentFinancialInfo(dependentFinancialsInfo,
								errors);
						break;
					}
				}

				IncomeCollection incomeCollection = financialStatementInfo
						.getIncomes();
				if (incomeCollection != null) {
					List<IncomeInfo> incomeInfoList = incomeCollection
							.getIncome();
					for (IncomeInfo incomeInfo : incomeInfoList) {
						validateVeteranIncome(incomeInfo, errors);
					}
				}

				ExpenseCollection expenseCollection = financialStatementInfo
						.getExpenses();
				if (expenseCollection != null) {
					List<ExpenseInfo> expenseInfoList = expenseCollection
							.getExpense();
					for (ExpenseInfo expenseInfo : expenseInfoList) {
						String expenseType = expenseInfo.getExpenseType();
						BigDecimal amount = expenseInfo.getAmount();
						if (ExpenseType.EXPENSE_TYPE_NON_REIMBURSED_MEDICAL
								.getCode().equalsIgnoreCase(expenseType)) {
							if (amount == null) {
								errors.reject(
										ErrorCode.VOA_0187,
										"Missing Required Field: Total non-reimbursed medical expense paid by Veteran or spouse.");
							} else {
								if (amount.compareTo(MINIMUM) < 0
										|| amount.compareTo(MAXIMUM) > 0) {
									errors.reject(
											ErrorCode.VOA_0188,
											"Value outside range of  0 to 9999999.99 for  total non-reimbursed medical expense paid by Veteran or spouse.");
								}
							}
						} else if (ExpenseType.EXPENSE_TYPE_FUNERAL_AND_BURIAL
								.getCode().equalsIgnoreCase(expenseType)) {
							if (amount == null) {
								errors.reject(
										ErrorCode.VOA_0190,
										"Missing Required Field: Amount you paid last calendar year for burial expenses.");
							} else {
								if (amount.compareTo(MINIMUM) < 0
										|| amount.compareTo(MAXIMUM) > 0) {
									errors.reject(
											ErrorCode.VOA_0191,
											"Value outside range of  0 to 9999999.99 for amount you paid last calendar year for burial expenses.");
								}
							}
						} else if (ExpenseType.EXPENSE_TYPE_COLLEGE_AND_VOCATION
								.getCode().equalsIgnoreCase(expenseType)) {
							if (amount == null) {
								errors.reject(
										ErrorCode.VOA_0193,
										"Missing Required Field: Amount you paid last calendar year for educational expenses.");
							} else {
								if (amount.compareTo(MINIMUM) < 0
										|| amount.compareTo(MAXIMUM) > 0) {
									errors.reject(
											ErrorCode.VOA_0194,
											"Value outside range of  0 to 9999999.99 for amount you paid last calendar year for educational expenses.");
								}
							}
						}
					}
				}

				AssetCollection assetCollection = financialStatementInfo
						.getAssets();
				if (assetCollection != null) {
					validateVeteranAsset(assetCollection, errors);
				}
			}
		}

		logger.debug("FinancialsInfo validation - Done.");
	}

	/**
	 * Validate veteran's asset
	 *
	 * @param errors
	 * @param assetCollection
	 */
	private void validateVeteranAsset(AssetCollection assetCollection,
			Errors errors) {
		List<AssetInfo> assetInfoList = assetCollection.getAsset();
		for (AssetInfo assetInfo : assetInfoList) {
			BigDecimal amount = assetInfo.getAmount();
			String assetType = assetInfo.getAssetType();
			if (AssetType.CODE_CASH.getCode().equalsIgnoreCase(assetType)) {
				if (amount == null) {
					errors.reject(ErrorCode.VOA_0196,
							"Missing required field: Cash, amount in back accounts for Veteran.");
				} else {
					if (amount.compareTo(MINIMUM) < 0
							|| amount.compareTo(MAXIMUM) > 0) {
						errors.reject(
								ErrorCode.VOA_0197,
								"Value outside range of  0 to 9999999.99 for cash, amount in back accounts for Veteran.");
					}
				}
			} else if (AssetType.CODE_REAL_ESTATE.getCode().equalsIgnoreCase(
					assetType)) {
				if (amount == null) {
					errors.reject(ErrorCode.VOA_0205,
							"Missing required field: Market value of land/buildings/lien for Veteran.");
				} else {
					if (amount.compareTo(MINIMUM) < 0
							|| amount.compareTo(MAXIMUM) > 0) {
						errors.reject(
								ErrorCode.VOA_0206,
								"Value outside range of  0 to 9999999.99 for market value of land/buildings/lien for Veteran.");
					}
				}
			} else if (AssetType.CODE_OTHER.getCode().equalsIgnoreCase(
					assetType)) {
				if (amount == null) {
					errors.reject(ErrorCode.VOA_0214,
							"Missing required field: Value of other property or assets for Veteran.");
				} else {
					if (amount.compareTo(MINIMUM) < 0
							|| amount.compareTo(MAXIMUM) > 0) {
						errors.reject(
								ErrorCode.VOA_0215,
								"Value outside range of  0 to 9999999.99 for value of other property or assets for Veteran.");
					}
				}
			}
		}
	}

	/**
	 * Validate dependent financials info.
	 *
	 * @param dependentFinancialsInfo
	 * @param errors
	 */
	private void validateDependentFinancialInfo(
			DependentFinancialsInfo dependentFinancialsInfo, Errors errors) {
		if (dependentFinancialsInfo != null) {

			DependentInfo dependentInfo = dependentFinancialsInfo
					.getDependentInfo();
			if (dependentInfo != null) {
				String lastName = dependentInfo.getFamilyName();

				if (StringUtils.isBlank(lastName)) {
					errors.reject(ErrorCode.VOA_0135,
							"Missing required field:  child's last name.");
				} else {
					if (lastName.length() > LIMIT_30_CHARS) {
						errors.reject(ErrorCode.VOA_0136,
								"Invalid value for Child's last name.");
					}
				}

				String firstName = dependentInfo.getGivenName();
				if (StringUtils.isBlank(firstName)) {
					errors.reject(ErrorCode.VOA_0137,
							"Missing required field:  Child's first name.");
				} else {
					if (firstName.length() > LIMIT_30_CHARS) {
						errors.reject(ErrorCode.VOA_0138,
								"Invalid value for Child's first name.");
					}
				}

				String middleName = dependentInfo.getMiddleName();
				if (StringUtils.isNotBlank(middleName)
						&& middleName.length() > LIMIT_30_CHARS) {
					errors.reject(ErrorCode.VOA_0139,
							"Invalid value for Child's first name.");
				}

				String relationShip = dependentInfo.getRelationship();
				if (StringUtils.isBlank(relationShip)) {
					errors.reject(ErrorCode.VOA_0141,
							"Missing Required Field: Child's relationship to Veteran.");
				} else {
					boolean isValid = ServiceUtils.isAlphaNumeric(relationShip);
					if (!isValid) {
						errors.reject(ErrorCode.VOA_0142,
								"Invalid value for child's relationship to Veteran.");
						logger.debug("Invalid value for child's relationship to Veteran. "
								+ relationShip + "\n");
					}
				}

				SsnCollection ssnCollection = dependentInfo.getSsns();
				if (ssnCollection == null) {
					errors.reject(ErrorCode.VOA_0143,
							"Missing Required Field: Child's SSN.");
				} else {
					List<SsnInfo> ssnInfoList = ssnCollection.getSsn();
					if (ssnInfoList.isEmpty()) {
						errors.reject(ErrorCode.VOA_0143,
								"Missing Required Field: Child's SSN.");
					} else {
						for (SsnInfo ssnInfo : ssnInfoList) {
							String ssnTxt = ssnInfo.getSsnText();
							boolean isValid = ServiceUtils.validateSsn(ssnTxt);
							if (!isValid) {
								errors.reject(ErrorCode.VOA_0144,
										"Invalid Child's SSN value.");
								break;
							}
						}
					}
				}

				String startDate = dependentInfo.getStartDate();
				if (StringUtils.isBlank(startDate)) {
					errors.reject(ErrorCode.VOA_0145,
							"Missing Required Field: Date child became your dependent.");
				} else {
					boolean isValid = ServiceUtils.validateDate(startDate);
					if (isValid) {
						try {
							Date date = new SimpleDateFormat("MM/dd/yyyy",
									Locale.ENGLISH).parse(startDate);
							if (new Date().before(date)) {
								errors.reject(ErrorCode.VOA_0147,
										"Date child became dependent cannot be a future date.");
							}
						} catch (ParseException e) {
							logger.debug("cannot convert date " + startDate
									+ " to mm/dd/yyyy format.");
						}
					}

					boolean isValidOnlyYear = ServiceUtils
							.isValidYear(startDate);
					if (isValidOnlyYear) {
						try {
							Date date = new SimpleDateFormat("yyyy",
									Locale.ENGLISH).parse(startDate);
							if (new Date().before(date)) {
								errors.reject(ErrorCode.VOA_0147,
										"Date child became dependent cannot be a future date.");
							}
						} catch (ParseException e) {
							logger.debug("cannot convert date " + startDate
									+ " to yyyy format.");
						}
					}

					isValid = isValid || isValidOnlyYear;
					if (!isValid) {
						errors.reject(ErrorCode.VOA_0146,
								"Invalid date when child became dependent.");
					}
				}

				String dob = dependentInfo.getDob();
				if (StringUtils.isBlank(dob)) {
					errors.reject(ErrorCode.VOA_0148,
							"Missing Required Field: Child's date of birth.");
				} else {
					boolean isValid = ServiceUtils.validateDate(dob);
					if (isValid) {
						try {
							Date date = new SimpleDateFormat("MM/dd/yyyy",
									Locale.ENGLISH).parse(dob);
							if (new Date().before(date)) {
								errors.reject(ErrorCode.VOA_0150,
										"Child's date of birth cannot be a future date.");
							}
						} catch (ParseException e) {
							logger.error("cannot convert date " + dob
									+ " to mm/dd/yyyy format.");
						}
					}

					boolean isValidOnlyYear = ServiceUtils.isValidYear(dob);
					if (isValidOnlyYear) {
						try {
							Date date = new SimpleDateFormat("yyyy",
									Locale.ENGLISH).parse(dob);
							if (new Date().before(date)) {
								errors.reject(ErrorCode.VOA_0150,
										"Child's date of birth cannot be a future date.");
							}
						} catch (ParseException e) {
							logger.error("cannot convert date " + dob
									+ " to yyyy format.");
						}
					}

					isValid = isValid || isValidOnlyYear;
					if (!isValid) {
						errors.reject(ErrorCode.VOA_0149,
								"Invalid child's date of birth.");
					}
				}
			}

			Boolean isIncapableOfSelfSupport = dependentFinancialsInfo
					.isIncapableOfSelfSupport();
			if (isIncapableOfSelfSupport == null) {
				errors.reject(
						ErrorCode.VOA_0151,
						"Missing Required Field: Was child permanently and totally disabled before age of 18.");
			}

			ExpenseCollection expenseCollection = dependentFinancialsInfo
					.getExpenses();
			if (expenseCollection != null) {
				List<ExpenseInfo> expenseList = expenseCollection.getExpense();
				for (ExpenseInfo expenseInfo : expenseList) {
					String expenseType = expenseInfo.getExpenseType();
					if (ExpenseType.EXPENSE_TYPE_EDUCATIONAL_EXPENSES_BY_DEPENDENT
							.equals(expenseType)) {
						BigDecimal amount = expenseInfo.getAmount();
						if (amount != null) {
							if (amount.compareTo(MINIMUM) < 0
									|| amount.compareTo(MAXIMUM) > 0) {
								errors.reject(
										ErrorCode.VOA_0154,
										"Value outside range of  0 to 9999999.99 for expenses paid by child for college,"
												+ " vocational rehabilitation or training.");
							}
						}
					}
				}
			}

			Boolean isLivedWithPatient = dependentFinancialsInfo
					.isLivedWithPatient();
			if (isLivedWithPatient == null) {
				errors.reject(ErrorCode.VOA_0156,
						"Missing Required Field: Did your child live with you last year.");
			}

			// validate income info.
			IncomeCollection incomeCollection = dependentFinancialsInfo
					.getIncomes();
			if (incomeCollection != null) {
				List<IncomeInfo> incomeInfoList = incomeCollection.getIncome();
				for (IncomeInfo incomeInfo : incomeInfoList) {
					validateDependentIncome(incomeInfo, errors);
				}
			}

			AssetCollection dependentAssetCollection = dependentFinancialsInfo
					.getAssets();
			validateDependentAsset(dependentAssetCollection, errors);
		}
	}

	/**
	 * Validate deplendent asset
	 *
	 * @param errors
	 * @param dependentAssetCollection
	 */
	private void validateDependentAsset(
			AssetCollection dependentAssetCollection, Errors errors) {
		if (dependentAssetCollection != null) {
			List<AssetInfo> assetInfoList = dependentAssetCollection.getAsset();
			for (AssetInfo assetInfo : assetInfoList) {
				BigDecimal amount = assetInfo.getAmount();
				String assetType = assetInfo.getAssetType();
				if (AssetType.CODE_CASH.getCode().equalsIgnoreCase(assetType)) {
					if (amount == null) {
						errors.reject(ErrorCode.VOA_0202,
								"Missing required field: Cash, amount in back accounts for child.");
					} else {
						if (amount.compareTo(MINIMUM) < 0
								|| amount.compareTo(MAXIMUM) > 0) {
							errors.reject(
									ErrorCode.VOA_0203,
									"Value outside range of  0 to 9999999.99 for cash, amount in back accounts for child.");
						}
					}
				} else if (AssetType.CODE_REAL_ESTATE.getCode()
						.equalsIgnoreCase(assetType)) {
					if (amount == null) {
						errors.reject(ErrorCode.VOA_0211,
								"Missing required field: Market value of land/buildings/lien for child.");
					} else {
						if (amount.compareTo(MINIMUM) < 0
								|| amount.compareTo(MAXIMUM) > 0) {
							errors.reject(
									ErrorCode.VOA_0212,
									"Value outside range of  0 to 9999999.99 for market value of land/buildings/lien for child.");
						}
					}
				} else if (AssetType.CODE_OTHER.getCode().equalsIgnoreCase(
						assetType)) {
					if (amount == null) {
						errors.reject(ErrorCode.VOA_0220,
								"Missing required field: Value of other property or assets for child.");
					} else {
						if (amount.compareTo(MINIMUM) < 0
								|| amount.compareTo(MAXIMUM) > 0) {
							errors.reject(
									ErrorCode.VOA_0221,
									"Value outside range of  0 to 9999999.99 for value of other property or assets for child.");
						}
					}
				}
			}
		}
	}

	/**
	 * Validate spouse finalcials info
	 *
	 * @param spouseFinancialsInfo
	 * @param errors
	 */
	private void validateSpouseFinancialInfo(
			SpouseFinancialsInfo spouseFinancialsInfo, Errors errors) {
		if (spouseFinancialsInfo != null) {
			Boolean isLiveWithPatient = spouseFinancialsInfo
					.isLivedWithPatient();
			if (isLiveWithPatient == null) {
				errors.reject(ErrorCode.VOA_0125, "Missing Required Field: Did your child live with you last year.");
			}

			SpouseInfo spouseInfo = spouseFinancialsInfo.getSpouse();

			if (spouseInfo != null) {
				// Validate spouse information.
				ValidationUtils.invokeValidator(new SpouseInfoValidator(),
						spouseInfo, errors);

				AddressInfo addressInfo = spouseInfo.getAddress();

				if (addressInfo != null) {
					String line1 = addressInfo.getLine1();
					if (!ServiceUtils.hasLessThan30Chars(line1)) {
						errors.reject(ErrorCode.VOA_0128,
								"Missing Required Field: Spouse street address.");
					}

					String city = addressInfo.getCity();
					if (StringUtils.isBlank(city)) {
						errors.reject(ErrorCode.VOA_0129,
								"Missing Required Field: City for Spouse address.");
					} else {
						boolean isValid = ServiceUtils.hasLessThan30Chars(city);
						if (!isValid) {
							errors.reject(ErrorCode.VOA_0129,
									"Missing Required Field: City for Spouse address.");
						}
					}

					String country = addressInfo.getCountry();
					if (StringUtils.isBlank(country)) {
						errors.reject(ErrorCode.VOA_0246,
								"Missing required field: Country for Spouse address.");
						logger.debug("Missing required field: Country for Spouse address.");
					} else {
						try {
							getLookupService().getCountryByCode(country);
						} catch (Exception e) {
							errors.reject(ErrorCode.VOA_0229,
									"Invalid country for Spouse address.");
							logger.debug("Invalid country for Spouse address. "
									+ country + "\n" + e.getMessage());
						}

						String stateProvince = null;
						if (Country.CODE_USA.getCode()
								.equalsIgnoreCase(country)) {
							stateProvince = addressInfo.getState();

							String zipCode = addressInfo.getZipCode();
							if (StringUtils.isBlank(zipCode)) {
								errors.reject(ErrorCode.VOA_0132,
										"Missing required field: Zip code for Spouse address.");
							} else {
								boolean isValid = ServiceUtils
										.validateZip(zipCode);
								if (!isValid) {
									errors.reject(ErrorCode.VOA_0133,
											"Invalid Zip Code for spouse's address.");
								}
							}

							String zipPlus = addressInfo.getZipPlus4();
							if (StringUtils.isNotBlank(zipPlus)) {
								boolean isValid = ServiceUtils
										.validateZipPlus(zipPlus);
								if (!isValid) {
									errors.reject(ErrorCode.VOA_0236,
											"Invalid Zip Code plus 4 for spouse's address.");
								}
							}
						} else if (Country.CODE_CAN.getCode().equalsIgnoreCase(
								country)
								|| Country.CODE_MEX.getCode().equalsIgnoreCase(
										country)) {
							stateProvince = addressInfo.getProvinceCode();
						}

						// only check state of USA or province of CAN & MEX
						if (Country.CODE_USA.getCode()
								.equalsIgnoreCase(country)
								|| Country.CODE_CAN.getCode().equalsIgnoreCase(
										country)
								|| Country.CODE_MEX.getCode().equalsIgnoreCase(
										country)) {
							if (StringUtils.isBlank(stateProvince)) {
								errors.reject(ErrorCode.VOA_0130,
										"Missing required field: State or province for Spouse address.");
								logger.debug("Missing required field: State or province for Spouse address.");
							} else {
								try {
									getLookupService().getStateByCode(
											stateProvince);
								} catch (Exception e) {
									errors.reject(ErrorCode.VOA_0131,
											"Invalid state or province for Spouse address.");
									logger.debug("Invalid state or province for Spouse address. "
											+ e.getMessage());
								}
							}
						}
					}

					String phoneNumber = addressInfo.getPhoneNumber();
					if (StringUtils.isNotBlank(phoneNumber)) {
						boolean isValid = ServiceUtils
								.validatePhone(phoneNumber);
						if (!isValid) {
							errors.reject(ErrorCode.VOA_0134,
									"Invalid phone number for spouse.");
						}
					}
				}
			}

			// validate income info.
			IncomeCollection incomeCollection = spouseFinancialsInfo
					.getIncomes();
			if (incomeCollection != null) {
				List<IncomeInfo> incomeInfoList = incomeCollection.getIncome();
				for (IncomeInfo incomeInfo : incomeInfoList) {
					validateSpouseIncome(incomeInfo, errors);
				}
			}

			AssetCollection spouseAssetCollection = spouseFinancialsInfo
					.getAssets();
			validateSpouseAsset(spouseAssetCollection, errors);
		}
	}

	/**
	 * Validate spouse asset
	 *
	 * @param errors
	 * @param spouseAssetCollection
	 */
	private void validateSpouseAsset(AssetCollection spouseAssetCollection,
			Errors errors) {
		if (spouseAssetCollection != null) {
			List<AssetInfo> assetInfoList = spouseAssetCollection.getAsset();
			for (AssetInfo assetInfo : assetInfoList) {
				BigDecimal amount = assetInfo.getAmount();
				String assetType = assetInfo.getAssetType();
				if (AssetType.CODE_CASH.getCode().equalsIgnoreCase(assetType)) {
					if (amount == null) {
						errors.reject(ErrorCode.VOA_0199,
								"Missing required field: Cash, amount in back accounts for spouse.");
					} else {
						if (amount.compareTo(MINIMUM) < 0
								|| amount.compareTo(MAXIMUM) > 0) {
							errors.reject(
									ErrorCode.VOA_0200,
									"Value outside range of  0 to 9999999.99 for cash, amount in back accounts for spouse.");
						}
					}
				} else if (AssetType.CODE_REAL_ESTATE.getCode()
						.equalsIgnoreCase(assetType)) {
					if (amount == null) {
						errors.reject(ErrorCode.VOA_0208,
								"Missing required field: Market value of land/buildings/lien for spouse.");
					} else {
						if (amount.compareTo(MINIMUM) < 0
								|| amount.compareTo(MAXIMUM) > 0) {
							errors.reject(
									ErrorCode.VOA_0209,
									"Value outside range of  0 to 9999999.99 for market value of land/buildings/lien for spouse.");
						}
					}
				} else if (AssetType.CODE_OTHER.getCode().equalsIgnoreCase(
						assetType)) {
					if (amount == null) {
						errors.reject(ErrorCode.VOA_0217,
								"Missing required field:  Value of other property or assets for spouse.");
					} else {
						if (amount.compareTo(MINIMUM) < 0
								|| amount.compareTo(MAXIMUM) > 0) {
							errors.reject(
									ErrorCode.VOA_0218,
									"Value outside range of  0 to 9999999.99 for  value of other property or assets for spouse.");
						}
					}
				}
			}
		}
	}

	/**
	 * Validate IncomeInfo
	 *
	 * @param incomeInfo
	 * @param errors
	 */
	private void validateVeteranIncome(IncomeInfo incomeInfo, Errors errors) {
		if (incomeInfo != null) {
			String incomeType = incomeInfo.getType();
			BigDecimal amount = incomeInfo.getAmount();
			if (IncomeType.INCOME_TYPE_TOTAL_INCOME_FROM_EMPLOYMENT.getCode()
					.equalsIgnoreCase(incomeType)) {
				if (amount == null) {
					errors.reject(ErrorCode.VOA_0160,
							"Missing required Field: Gross annual income from employment for Veteran.");
				} else {
					if (amount.compareTo(MINIMUM) < 0
							|| amount.compareTo(MAXIMUM) > 0) {
						errors.reject(
								ErrorCode.VOA_0161,
								"Value outside range of  0 to 9999999.99 for net income from property or business for Veteran.");
					}
				}
			} else if (IncomeType.INCOME_TYPE_FARM_RANCH_PROPERTY_OR_BUSINESS_INCOME
					.getCode().equalsIgnoreCase(incomeType)) {
				if (amount == null) {
					errors.reject(ErrorCode.VOA_0169,
							"Missing Required Field: Gross annual income from employment for Veteran.");
				} else {
					if (amount.compareTo(MINIMUM) < 0
							|| amount.compareTo(MAXIMUM) > 0) {
						errors.reject(
								ErrorCode.VOA_0170,
								"Value outside range of  0 to 9999999.99 for "
										+ "gross annual income from employment for Veteran.");
					}
				}
			} else if (IncomeType.INCOME_TYPE_TOTAL_ALL_OTHER_INCOME.getCode()
					.equalsIgnoreCase(incomeType)) {
				if (amount == null) {
					errors.reject(ErrorCode.VOA_0178,
							"Missing Required Field: List other income amounts for Veteran.");
				} else {
					if (amount.compareTo(MINIMUM) < 0
							|| amount.compareTo(MAXIMUM) > 0) {
						errors.reject(
								ErrorCode.VOA_0179,
								"Value outside range of  0 to 9999999.99 for list other income amounts for Veteran.");
					}
				}
			}
		}
	}

	/**
	 * Validate IncomeInfo
	 *
	 * @param incomeInfo
	 * @param errors
	 */
	private void validateSpouseIncome(IncomeInfo incomeInfo, Errors errors) {
		if (incomeInfo != null) {
			String incomeType = incomeInfo.getType();
			BigDecimal amount = incomeInfo.getAmount();
			if (IncomeType.INCOME_TYPE_TOTAL_INCOME_FROM_EMPLOYMENT.getCode()
					.equalsIgnoreCase(incomeType)) {
				if (amount == null) {
					errors.reject(ErrorCode.VOA_0163,
							"Missing Required Field: Gross annual income from employment for spouse.");
				} else {
					if (amount.compareTo(MINIMUM) < 0
							|| amount.compareTo(MAXIMUM) > 0) {
						errors.reject(
								ErrorCode.VOA_0164,
								"Value outside range of  0 to 9999999.99 "
										+ "for gross annual income from employment for spouse.");
					}
				}
			} else if (IncomeType.INCOME_TYPE_FARM_RANCH_PROPERTY_OR_BUSINESS_INCOME
					.getCode().equalsIgnoreCase(incomeType)) {
				if (amount == null) {
					errors.reject(ErrorCode.VOA_0172,
							"Missing Required Field: Net income from property or business for spouse.");
				} else {
					if (amount.compareTo(MINIMUM) < 0
							|| amount.compareTo(MAXIMUM) > 0) {
						errors.reject(
								ErrorCode.VOA_0173,
								"Value outside range of  0 to 9999999.99 for net income from property or business for spouse.");
					}
				}
			} else if (IncomeType.INCOME_TYPE_TOTAL_ALL_OTHER_INCOME.getCode()
					.equalsIgnoreCase(incomeType)) {
				if (amount == null) {
					errors.reject(ErrorCode.VOA_0181,
							"Missing Required Field:  List other income amounts for spouse.");
				} else {
					if (amount.compareTo(MINIMUM) < 0
							|| amount.compareTo(MAXIMUM) > 0) {
						errors.reject(
								ErrorCode.VOA_0182,
								"Value outside range of  0 to 9999999.99 for list other income amounts for spouse.");
					}
				}
			}
		}
	}

	/**
	 * Validate IncomeInfo
	 *
	 * @param incomeInfo
	 * @param errors
	 */
	private void validateDependentIncome(IncomeInfo incomeInfo, Errors errors) {
		if (incomeInfo != null) {
			String incomeType = incomeInfo.getType();
			BigDecimal amount = incomeInfo.getAmount();
			if (IncomeType.INCOME_TYPE_TOTAL_INCOME_FROM_EMPLOYMENT.getCode()
					.equalsIgnoreCase(incomeType)) {
				if (amount == null) {
					errors.reject(ErrorCode.VOA_0166,
							"Missing Required Field: Gross annual income from employment for child.");
				} else {
					if (amount.compareTo(MINIMUM) < 0
							|| amount.compareTo(MAXIMUM) > 0) {
						errors.reject(
								ErrorCode.VOA_0167,
								"Value outside range of  0 to 9999999.99 "
										+ "for gross annual income from employment for child.");
					}
				}
			} else if (IncomeType.INCOME_TYPE_FARM_RANCH_PROPERTY_OR_BUSINESS_INCOME
					.getCode().equalsIgnoreCase(incomeType)) {
				if (amount == null) {
					errors.reject(ErrorCode.VOA_0175,
							"Missing Required Field: Net income from property or business for child.");
				} else {
					if (amount.compareTo(MINIMUM) < 0
							|| amount.compareTo(MAXIMUM) > 0) {
						errors.reject(
								ErrorCode.VOA_0176,
								"Value outside range of  0 to 9999999.99 for  net income from property or business for child.");
					}
				}
			} else if (IncomeType.INCOME_TYPE_TOTAL_ALL_OTHER_INCOME.getCode()
					.equalsIgnoreCase(incomeType)) {
				if (amount == null) {
					errors.reject(ErrorCode.VOA_0184,
							"Missing Required Field: List other income amounts for child.");
				} else {
					if (amount.compareTo(MINIMUM) < 0
							|| amount.compareTo(MAXIMUM) > 0) {
						errors.reject(
								ErrorCode.VOA_0185,
								"Value outside range of  0 to 9999999.99 for list other income amounts for child.");
					}
				}
			}
		}
	}
}
