package nl.quintor.commons.util;

import java.util.Calendar;


/**
 * Validation class with various algorithms including validation for email addresses and postal codes.
 * 
 * @author Benny Bottema
 */
public final class ValidatorUtils {

	/**
	 * Regular expression used to validate postal code.
	 * 
	 * @see #validatePostcode(String)
	 */
	private static final String REGEX_VALIDATION_POSTALCODE = "[1-9]{1}[0-9]{3}[a-zA-Z]{2}";

	/**
	 * Private constructor; This class is not meant to be instantiated. This is a utility class with static methods
	 * only.
	 */
	private ValidatorUtils() {
		//
	}

	/**
	 * Validates a dutch postal code using the following rules:
	 * <ul>
	 * <li>A postal code should begin with 4 numbers</li>
	 * <li>A postal code should start with a 1 or higher (postal codes can't be below 1000)</li>
	 * <li>A postal code should end with two alpha characters</li>
	 * <li>A postal code cannot contains spaces</li>
	 * </ul>
	 * For these rules the following regular expression is used: {@value #REGEX_VALIDATION_POSTALCODE}. <br /> <br />
	 * The following validation messages can be returned:
	 * <ul>
	 * <li>{@value ValidatorMessages#VALIDATIONERROR_POSTALCODE_UNAVAILABLE}</li>
	 * <li>{@value ValidatorMessages#VALIDATIONERROR_POSTALCODE_INVALID}</li>
	 * </ul>
	 * 
	 * @param postalcode The postal code to be validated.
	 * @return An error code if validation fails or <code>null</code> if validation succeeded.
	 * @see #REGEX_VALIDATION_POSTALCODE
	 * @see GenericUtils#regexPatternMatches(String, String)
	 */
	public static String validatePostcode(final String postalcode) {
		if (postalcode == null) {
			return ValidatorMessages.VALIDATIONERROR_POSTALCODE_UNAVAILABLE;
		} else if (!GenericUtils.regexPatternMatches(REGEX_VALIDATION_POSTALCODE, postalcode)) {
			return ValidatorMessages.VALIDATIONERROR_POSTALCODE_INVALID;
		} else {
			return null;
		}
	}

	/**
	 * Validates an age (birth date) based on a specified minimum and maximum age. <br /> <br /> The following
	 * validation message can be returned:
	 * <ul>
	 * <li>{@value ValidatorMessages#VALIDATIONERROR_BIRTHDATE_UNAVAILABLE}</li>
	 * <li>{@value ValidatorMessages#VALIDATIONERROR_BIRTHDATE_INFUTURE}</li>
	 * <li>{@value ValidatorMessages#VALIDATIONERROR_BIRTHDATE_TOOOLD}</li>
	 * <li>{@value ValidatorMessages#VALIDATIONERROR_BIRTHDATE_TOOYOUNG}</li>
	 * </ul>
	 * 
	 * @param birthdate The birth date from which the age can be derived.
	 * @param min Minimum age the birth date should comply too.
	 * @param max Maximum age the birth date should comply too.
	 * @return An error code if validation fails or <code>null</code> if validation succeeded.
	 * @see Calendar
	 */
	public static String validateAge(final Calendar birthdate, final Integer min, final Integer max) {
		if (birthdate == null) {
			return ValidatorMessages.VALIDATIONERROR_BIRTHDATE_UNAVAILABLE;
		} else if (birthdate.after(Calendar.getInstance())) {
			return ValidatorMessages.VALIDATIONERROR_BIRTHDATE_INFUTURE;
		} else {
			final Calendar calendarMaxYearsAgo = Calendar.getInstance();
			calendarMaxYearsAgo.roll(Calendar.YEAR, -max.intValue());
			if (birthdate.before(calendarMaxYearsAgo)) {
				return ValidatorMessages.VALIDATIONERROR_BIRTHDATE_TOOOLD;
			} else {
				final Calendar calendarMinYearsAgo = Calendar.getInstance();
				calendarMinYearsAgo.roll(Calendar.YEAR, -min.intValue());
				if (birthdate.after(calendarMinYearsAgo)) {
					return ValidatorMessages.VALIDATIONERROR_BIRTHDATE_TOOYOUNG;
				} else {
					return null;
				}
			}
		}
	}
}
