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

import gov.va.med.esr.common.model.lookup.Gender;
import gov.va.med.esr.service.UnknownLookupCodeException;
import gov.va.med.esr.service.UnknownLookupTypeException;
import gov.va.med.esr.voa.common.ErrorCode;
import gov.va.med.esr.voa.util.ServiceUtils;
//import gov.va.med.esr.voa.webservice.NameCollection;
//import gov.va.med.esr.voa.webservice.NameInfo;
import gov.va.med.esr.voa.webservice.PersonInfo;
import gov.va.med.fw.util.StringUtils;

//import java.util.List;



import org.springframework.validation.Errors;

/**
 * Validate person information
 */
public class PersonInfoValidator extends AbstractValidator {

	// limit chars to 20
	private static final int LIMIT_LESS_THAN_20_CHARS = 20;

	// limit chars to 30
	private static final int LIMIT_LESS_THAN_30_CHARS = 30;

	// limit chars to 35
	private static final int LIMIT_LESS_THAN_35_CHARS = 35;

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

	@Override
	public void validate(Object target, Errors errors) {
		if (logger.isDebugEnabled()){
			logger.debug("Person info validation...");
		}

		if (target != null) {
			PersonInfo personInfo = (PersonInfo) target;

			String lastName = personInfo.getLastName();
			if (StringUtils.isBlank(lastName)) {
				errors.reject(ErrorCode.VOA_0001,
						"Missing Required Field: Veteran Last Name.");
			}

			String firstName = personInfo.getFirstName();
			if (StringUtils.isBlank(firstName)) {
				errors.reject(ErrorCode.VOA_0002,
						"Missing Required Field: Veteran First Name.");
			}

			String middleName = personInfo.getMiddleName();
			if (StringUtils.isNotBlank(middleName)
					&& middleName.length() > LIMIT_LESS_THAN_30_CHARS) {
				errors.reject(ErrorCode.VOA_0003, "Invalid middle name.");
				
				if (logger.isDebugEnabled()){
					logger.debug("Invalid middle name.");
				}
			}

			//CCR13311 remove veteran other name for 2014 OMB approved form
/*			NameCollection nameCollection = personInfo.getNames();
			if (nameCollection != null) {
				List<NameInfo> nameList = nameCollection.getName();
				for (NameInfo nameInfo : nameList) {
					String otherName = nameInfo.getOtherName();
					if (StringUtils.isNotBlank(otherName)
							&& otherName.length() > LIMIT_LESS_THAN_30_CHARS) {
						errors.reject(ErrorCode.VOA_0005,
								"Invalid Veteran other names used.");
						logger.debug("Invalid Veteran other names used.");
						break;
					}
				}
			}*/

			String mothersMaidenName = personInfo.getMothersMaidenName();
			if (StringUtils.isNotBlank(mothersMaidenName)
					&& mothersMaidenName.length() > LIMIT_LESS_THAN_35_CHARS) {
				errors.reject(ErrorCode.VOA_0006,
						"Invalid Veteran's mother's maiden name.");
				if (logger.isDebugEnabled()){
					logger.debug("Invalid Veteran's mother's maiden name.");
				}
			}

			String ssnTxt = personInfo.getSsnText();
			if (StringUtils.isBlank(ssnTxt)) {
				errors.reject(ErrorCode.VOA_0007,
						"Missing Required Field:  Veteran SSN.");
			} else {
				boolean isValid = ServiceUtils.validateSsn(ssnTxt);
				if (!isValid) {
					errors.reject(ErrorCode.VOA_0008,
							"Invalid Veteran SSN value.");
					if (logger.isDebugEnabled()){
						logger.debug("Invalid Veteran SSN value.");
					}
				}
			}

			String dob = personInfo.getDob();
			if (StringUtils.isBlank(dob)) {
				errors.reject(ErrorCode.VOA_0009,
						"Missing Required Field:  Veteran Date of Birth.");
			} else {
				boolean isValid = ServiceUtils.validateDate(dob);
				if (isValid) {
					boolean isFuture = ServiceUtils.isFutureDate(dob);
					if (isFuture) {
						errors.reject(ErrorCode.VOA_0011,
								"Veteran Date of Birth cannot be a future date.");
					}
				} else {
					errors.reject(ErrorCode.VOA_0238,
							"Invalid Veteran date of birth.");
				}
			}
			
			//CCR 13884 - VOA forms (21526 or 1010EZ/R are not required to send a gender (optional) value to ES.  ES now defaults the gender to 'M' in the personserviceImpl.addPrefFacility() if it is missing or invalid
			//if null value is passed, U is set as default	
			String gender = personInfo.getGender();			
			if (StringUtils.isBlank(gender)) {
				try {
					getLookupService().getGenderByCode(Gender.UNKNOWN.getName());
				} catch (UnknownLookupTypeException e) {
					if (logger.isErrorEnabled())
						logger.error("Unknown gender lookup type" + e.getMessage());
				} catch (UnknownLookupCodeException e) {
					if (logger.isErrorEnabled())
						logger.error("Unknown gender lookup code" + e.getMessage());
				}
			} else {
				try {
					getLookupService().getGenderByCode(gender);
				} catch (Exception e) {
					errors.reject(ErrorCode.VOA_0013,
							"Invalid Gender value for Veteran.");
					if (logger.isDebugEnabled()){
						logger.debug("Invalid Gender value for Veteran. "
							+ e.getMessage());
					}
				}
			}
			
			
			String birthCity = personInfo.getPlaceOfBirthCity();
			if (StringUtils.isNotBlank(birthCity)
					&& birthCity.length() > LIMIT_LESS_THAN_20_CHARS) {
				errors.reject(ErrorCode.VOA_0014,
						"Invalid City of birth for Veteran.");
			}

			// Assume input is state code.
			try {
				String birthStateCode = personInfo.getPlaceOfBirthState();
				if (StringUtils.isNotBlank(birthStateCode)) {
					getLookupService().getStateByCode(birthStateCode);
				}
			} catch (Exception e) {
				errors.reject(ErrorCode.VOA_0015, "Invalid State value.");
				if (logger.isDebugEnabled()){
					logger.debug("Cannot getAllStates because of code exception. "
						+ e.getMessage());
				}
			}
		}
		if (logger.isDebugEnabled()){
			logger.debug("Person info validation - Done");
		}
	}

}
