package com.ejie.ab04b.util;

import com.ejie.ab04b.constantes.Constantes;

/**
 * ValidadorNifCifNie
 * 
 * @author ashleypayton
 */
public class ValidadorNifCifNie {

	/**
	 * Constructor de ValidadorNifCifNie
	 */
	private ValidadorNifCifNie() {
	}

	private static final int TAM_NIF = 9;
	private static final int TAM_CIF = 9;

	/**
	 * checkNif
	 * 
	 * @param paramString
	 *            String
	 * 
	 * @return boolean
	 */
	public static boolean checkNif(String paramString) {
		return paramString != null
				&& ValidadorNifCifNie.isNifValido(paramString);
	}

	/**
	 * checkCif
	 * 
	 * @param paramString
	 *            String
	 * 
	 * @return boolean
	 */
	public static boolean checkCif(String paramString) {
		return paramString != null
				&& paramString.length() == ValidadorNifCifNie.TAM_CIF
				&& ValidadorNifCifNie.isCifValido(paramString);
	}

	/****************************************************************************************/

	private static final String LETRAS_NIF = "TRWAGMYFPDXBNJZSQVHLCKE";
	private static final int NUM_LETRAS_NIF = 23;
	private static final String VALORES_CIF = "ABCDEFGHJKLMNPQRSUVW";
	private static final int DIEZ = 10;
	private static final int POSICION_LETRA_NIF = 8;

	/**
	 * Metodo que valida si es correcto el nif
	 * 
	 * @param nif
	 *            String
	 * @return boolean
	 */
	public static boolean isNifValido(String nif) {

		boolean resultado = false;

		try {
			String nif1 = nif.toUpperCase();
			if (nif1.startsWith("T")) {
				if (nif1.length() <= Integer
						.valueOf(Constantes.CAMPO_DNI_LENGTH_STR)) {
					resultado = true;
				} else {
					resultado = false;
				}
			} else {
				if (nif.length() == ValidadorNifCifNie.TAM_NIF) {
					if (nif1.startsWith("X")) {
						nif1 = Utilities.obtenerCadena("0", nif1.substring(1));
					} else if (nif1.startsWith("Y")) {
						nif1 = Utilities.obtenerCadena("1", nif1.substring(1));
					} else if (nif1.startsWith("Z")) {
						nif1 = Utilities.obtenerCadena("2", nif1.substring(1));
					}
					if (nif1.matches("[0-9]{8}[" + ValidadorNifCifNie.LETRAS_NIF
							+ "]")) {
						int dni = Integer.parseInt(nif1.substring(0,
								ValidadorNifCifNie.POSICION_LETRA_NIF));
						char letraCalculada = ValidadorNifCifNie.LETRAS_NIF
								.charAt(dni
										% ValidadorNifCifNie.NUM_LETRAS_NIF);
						if (letraCalculada == nif1.charAt(
								ValidadorNifCifNie.POSICION_LETRA_NIF)) {
							resultado = true;
						}
					}
				} else {
					resultado = false;
				}
			}
		} catch (Exception e) {
			// Si ha habido algun error es porque hay algun parseo que tira
			// bien.
			resultado = false;
		}

		return resultado;
	}

	/**
	 * Realiza la validacion si la cadena representa un CIF
	 * 
	 * @param cif
	 *            la cadena a comprobar
	 * @return true si la cadena representa un CIF del tipo indicado
	 */
	public static boolean isCifValido(String cif) {

		boolean resultado = false;

		try {
			String vCif = cif.trim();

			int suma = 0;
			int contador = 0;
			int temporal = 0;
			int codigoControl = 0;

			String cadenaTemporal = null;
			String primeraLetra = null;
			String ultimaLetra = null;

			// Comprueba la longitud correcta del CIF.
			if (!(vCif.length() == ValidadorNifCifNie.TAM_CIF)) {
				return false;
			}
			// Si encuentra algun caracter que no sea una letra o un numero, el
			// cif no es valido.
			if (vCif.matches("[^A-Za-z0-9]")) {
				return false;
			}
			// Convierte a may�sculas la cadena.
			vCif = vCif.toUpperCase();

			// Obtiene la primera letra (letra de la sociedad) y la ultima letra
			// del CIF (letra de control).
			primeraLetra = vCif.substring(0, 1);

			// Obtiene la ultima letra del CIF, para comprobar si es valida.
			ultimaLetra = vCif.substring(ValidadorNifCifNie.TAM_CIF - 1,
					ValidadorNifCifNie.TAM_CIF);

			// Comprueba si la primera letra es valida.
			if (ValidadorNifCifNie.VALORES_CIF.indexOf(primeraLetra) < 0) {
				return false;
			}
			// Obtiene el codigo de control.
			// Sumamos las cifras pares
			for (int pos = 2; pos + 1 < ValidadorNifCifNie.TAM_CIF; pos = pos
					+ 2) {
				suma += Integer.parseInt(vCif.substring(pos, pos + 1));
			}

			// Ahora cada cifra impar la multiplicamos por dos y sumamos las
			// cifras
			// del resultado.
			for (contador = 1; contador
					+ 1 < ValidadorNifCifNie.TAM_CIF; contador = contador + 2) {
				// Multiplica por 2
				temporal = (Integer
						.parseInt(vCif.substring(contador, contador + 1)) * 2);

				// Suma los digitos.
				// Diferencia si tiene una cifra, por ejemplo: 8 = 8
				// o si tiene varias, por ejemplo: 16 -> 6 + 1 = 7

				if (String.valueOf(temporal).length() < 2) {
					suma += temporal;
				} else {
					cadenaTemporal = String.valueOf(temporal);
					suma = suma
							+ (Integer.parseInt(cadenaTemporal.substring(0, 1)))
							+ (Integer
									.parseInt(cadenaTemporal.substring(1, 2)));
				}
			}

			// Obtiene las unidades de la suma y se las resta a 10, para obtener
			// el digito de control.
			codigoControl = ((ValidadorNifCifNie.DIEZ
					- (suma % ValidadorNifCifNie.DIEZ))
					% ValidadorNifCifNie.DIEZ);

			String control_letter = "JABCDEFGHI".substring(codigoControl,
					codigoControl + 1);

			// Control must be a digit
			if (primeraLetra.matches("/[ABEH]/ ")) {
				return ultimaLetra.equals(String.valueOf(codigoControl));

				// Control must be a letter
			} else if (primeraLetra.matches("/[KPQS]/")) {
				return ultimaLetra.equals(control_letter);

				// Can be either
			} else {
				return ultimaLetra.equals(String.valueOf(codigoControl))
						|| ultimaLetra.equals(control_letter);
			}

		} catch (Exception e) {
			resultado = false;
		}
		return resultado;
	}
}
