package com.mx.dla.util;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.owasp.encoder.Encode;

public class Validaciones {

	private static final List<String> FORBIDDEN_WORDS = Collections
			.unmodifiableList(Arrays.asList("<script>", "<a>", "onclick"));

	/**
	 * 
	 * Este método devuelve la entrada ingresada como una cadena codificada mediante
	 * la librería OWASP Java Encoder.
	 * 
	 * @param dato cadena a encriptar
	 * @return String cadena encriptada
	 */
	public static String encodeString(String dato) {
		return Encode.forHtml(dato);
	}

	/**
	 * 
	 * Este método es el encargado de revisar si en el dato ingresado (String) se
	 * encuentra alguna de las palabras catalogadas como prohibidas en la constante
	 * FORBIDDEN_WORDS.
	 * 
	 * @param dato cadena validar
	 * @return respuesta de validacion arreglo de dos posiciones posicion [1] 0
	 *         false o 1 true posicion [2] mensaje de error o vacio si es valido.
	 */
	public static String[] validaListaNegra(String dato) {
		String[] respuesta = new String[2];
		respuesta[0] = "1";
		respuesta[1] = "";
		if (Objects.nonNull(dato)) {
			if (FORBIDDEN_WORDS.stream().anyMatch(word -> dato.contains(word.toLowerCase()))) {
				respuesta[0] = "0";
				respuesta[1] = "No es posible registrar el valor ingresado";
			}
		} else {
			respuesta[0] = "0";
			respuesta[1] = "El valor ingresado es null";
		}
		return respuesta;
	}

	/**
	 * 
	 * Valida datos de tipo Short, en caso de no cumplir las validaciones regresa un
	 * error.
	 * 
	 * @param dato
	 * @param hasLimits
	 * @param min
	 * @param max
	 * @param minLength
	 * @param maxLength
	 * @return respuesta de validacion arreglo de dos posiciones posicion [1] 0
	 *         false o 1 true posicion [2] mensaje de error o vacio si es valido.
	 */
	public static String[] validaShort(String dato, boolean hasLimits, short min, short max, int minLength,
			int maxLength) {
		String[] respuesta = new String[2];
		Pattern pat = Pattern.compile("^-?\\d+$");
		Short datoShort = null;
		if (Objects.nonNull(dato)) {
			Matcher mat = pat.matcher(dato);
			respuesta[1] = "";
			if (mat.matches()) {
				respuesta[0] = "1";
				try {
					datoShort = Short.parseShort(dato);
				} catch (NumberFormatException e) {
					respuesta[0] = "0";
					respuesta[1] = "El valor ingresado no puede ser convertido a short.";
				}
			} else {
				respuesta[0] = "0";
				respuesta[1] = "El valor ingresado no es de tipo short";
			}
		} else {
			respuesta[0] = "0";
			respuesta[1] = "El valor ingresado es null";
		}
		if (datoShort != null) {
			if (hasLimits && datoShort < min) {
				respuesta[0] = "0";
				respuesta[1] = "El valor ingresado es menor que el valor mínimo permitido";
			}
			if (hasLimits && datoShort > max) {
				respuesta[0] = "0";
				respuesta[1] = "El valor ingresado es mayor que el valor máximo permitido";
			}
			if (maxLength != -1 && dato.length() > maxLength) {
				respuesta[0] = "0";
				respuesta[1] = "La longitud del valor ingresado es mayor que la longitud máximo permitida";
			}
			if (minLength != -1 && dato.length() < minLength) {
				respuesta[0] = "0";
				respuesta[1] = "La longitud del valor ingresado es menor que la longitud mínimo permitida";
			}
		}
		return respuesta;
	}

	/**
	 * 
	 * Valida datos de tipo Integer, en caso de no cumplir las validaciones regresa
	 * un error.
	 * 
	 * @param dato
	 * @param hasLimits
	 * @param min
	 * @param max
	 * @param minLength
	 * @param maxLength
	 * @return respuesta de validacion arreglo de dos posiciones posicion [1] 0
	 *         false o 1 true posicion [2] mensaje de error o vacio si es valido.
	 */
	public static String[] validaInt(String dato, boolean hasLimits, int min, int max, int minLength, int maxLength) {
		String[] respuesta = new String[2];
		Pattern pat = Pattern.compile("^-?\\d+$");
		Matcher mat = pat.matcher(dato);
		Integer datoInt = null;
		if (Objects.nonNull(dato)) {
			respuesta[1] = "";
			if (mat.matches()) {
				respuesta[0] = "1";
				try {
					datoInt = Integer.parseInt(dato);
				} catch (NumberFormatException e) {
					respuesta[0] = "0";
					respuesta[1] = "El valor ingresado no puede ser convertido a int.";
				}
			} else {
				respuesta[0] = "0";
				respuesta[1] = "El valor ingresado no es de tipo int";
			}
		} else {
			respuesta[0] = "0";
			respuesta[1] = "El valor ingresado es null";
		}
		if (datoInt != null) {
			if (hasLimits && datoInt < min) {
				respuesta[0] = "0";
				respuesta[1] = "El valor ingresado es menor que el valor mínimo permitido";
			}
			if (hasLimits && datoInt > max) {
				respuesta[0] = "0";
				respuesta[1] = "El valor ingresado es mayor que el valor máximo permitido";
			}
			if (maxLength != -1 && dato.length() > maxLength) {
				respuesta[0] = "0";
				respuesta[1] = "La longitud del valor ingresado es mayor que la longitud máximo permitida";
			}
			if (minLength != -1 && dato.length() < minLength) {
				respuesta[0] = "0";
				respuesta[1] = "La longitud del valor ingresado es menor que la longitud mínimo permitida";
			}
		}
		return respuesta;
	}

	/**
	 * 
	 * Valida datos de tipo Long, en caso de no cumplir las validaciones regresa un
	 * error.
	 * 
	 * @param dato
	 * @param hasLimits
	 * @param min
	 * @param max
	 * @param minLength
	 * @param maxLength
	 * @return respuesta de validacion arreglo de dos posiciones posicion [1] 0
	 *         false o 1 true posicion [2] mensaje de error o vacio si es valido.
	 */
	public static String[] validaLong(String dato, boolean hasLimits, long min, long max, int minLength,
			int maxLength) {
		String[] respuesta = new String[2];
		Pattern pat = Pattern.compile("^-?\\d+$");
		Matcher mat = pat.matcher(dato);
		Long datoLong = null;
		if (Objects.nonNull(dato)) {
			respuesta[1] = "";
			if (mat.matches()) {
				respuesta[0] = "1";
				try {
					datoLong = Long.parseLong(dato);
				} catch (NumberFormatException e) {
					respuesta[0] = "0";
					respuesta[1] = "El valor ingresado no puede ser convertido a long.";
				}
			} else {
				respuesta[0] = "0";
				respuesta[1] = "El valor ingresado no es de tipo long";
			}
		} else {
			respuesta[0] = "0";
			respuesta[1] = "El valor ingresado es null";
		}
		if (datoLong != null) {
			if (hasLimits && datoLong < min) {
				respuesta[0] = "0";
				respuesta[1] = "El valor ingresado es menor que el valor mínimo permitido";
			}
			if (hasLimits && datoLong > max) {
				respuesta[0] = "0";
				respuesta[1] = "El valor ingresado es mayor que el valor máximo permitido";
			}
			if (maxLength != -1 && dato.length() > maxLength) {
				respuesta[0] = "0";
				respuesta[1] = "La longitud del valor ingresado es mayor que la longitud máximo permitida";
			}
			if (minLength != -1 && dato.length() < minLength) {
				respuesta[0] = "0";
				respuesta[1] = "La longitud del valor ingresado es menor que la longitud mínimo permitida";
			}
		}
		return respuesta;
	}

	/**
	 * 
	 * Valida datos de tipo Double, en caso de no cumplir las validaciones regresa
	 * un error.
	 * 
	 * @param dato
	 * @param hasLimits
	 * @param min
	 * @param max
	 * @param minLength
	 * @param maxLength
	 * @return respuesta de validacion arreglo de dos posiciones posicion [1] 0
	 *         false o 1 true posicion [2] mensaje de error o vacio si es valido.
	 */
	public static String[] validaDouble(String dato, boolean hasLimits, double min, double max, int minLength,
			int maxLength) {
		String[] respuesta = new String[2];
		Pattern pat = Pattern.compile("^-?\\d+(\\.\\d+)?$");
		Matcher mat = pat.matcher(dato);
		Double datoDouble = null;
		if (Objects.nonNull(dato)) {
			respuesta[1] = "";
			if (mat.matches()) {
				respuesta[0] = "1";
				datoDouble = Double.parseDouble(dato);
				try {
					datoDouble = Double.parseDouble(dato);
				} catch (NumberFormatException e) {
					respuesta[0] = "0";
					respuesta[1] = "El valor ingresado no puede ser convertido a double.";
				}
			} else {
				respuesta[0] = "0";
				respuesta[1] = "El valor ingresado no es de tipo double";
			}
		} else {
			respuesta[0] = "0";
			respuesta[1] = "El valor ingresado es null";
		}
		if (datoDouble != null) {
			if (hasLimits && datoDouble < min) {
				respuesta[0] = "0";
				respuesta[1] = "El valor ingresado es menor que el valor mínimo permitido";
			}
			if (hasLimits && datoDouble > max) {
				respuesta[0] = "0";
				respuesta[1] = "El valor ingresado es mayor que el valor máximo permitido";
			}
			if (maxLength != -1 && dato.length() > maxLength) {
				respuesta[0] = "0";
				respuesta[1] = "La longitud del valor ingresado es mayor que la longitud máximo permitida";
			}
			if (minLength != -1 && dato.length() < minLength) {
				respuesta[0] = "0";
				respuesta[1] = "La longitud del valor ingresado es menor que la longitud mínimo permitida";
			}
		}
		return respuesta;
	}

	/**
	 * 
	 * Valida datos de tipo Float, en caso de no cumplir las validaciones regresa un
	 * error.
	 * 
	 * @param dato
	 * @param hasLimits
	 * @param min
	 * @param max
	 * @param minLength
	 * @param maxLength
	 * @return respuesta de validacion arreglo de dos posiciones posicion [1] 0
	 *         false o 1 true posicion [2] mensaje de error o vacio si es valido.
	 */
	public static String[] validaFloat(String dato, boolean hasLimits, float min, float max, int minLength,
			int maxLength) {
		String[] respuesta = new String[2];
		Pattern pat = Pattern.compile("^-?\\d+(\\.\\d+)?$");
		Matcher mat = pat.matcher(dato);
		Float datoFloat = null;
		if (Objects.nonNull(dato)) {
			respuesta[1] = "";
			if (mat.matches()) {
				respuesta[0] = "1";
				try {
					datoFloat = Float.parseFloat(dato);
				} catch (NumberFormatException e) {
					respuesta[0] = "0";
					respuesta[1] = "El valor ingresado no puede ser convertido a float.";
				}
			} else {
				respuesta[0] = "0";
				respuesta[1] = "El valor ingresado no es de tipo float";
			}
		} else {
			respuesta[0] = "0";
			respuesta[1] = "El valor ingresado es null";
		}
		if (datoFloat != null) {
			if (hasLimits && datoFloat < min) {
				respuesta[0] = "0";
				respuesta[1] = "El valor ingresado es menor que el valor mínimo permitido";
			}
			if (hasLimits && datoFloat > max) {
				respuesta[0] = "0";
				respuesta[1] = "El valor ingresado es mayor que el valor máximo permitido";
			}
			if (maxLength != -1 && dato.length() > maxLength) {
				respuesta[0] = "0";
				respuesta[1] = "La longitud del valor ingresado es mayor que la longitud máximo permitida";
			}
			if (minLength != -1 && dato.length() < minLength) {
				respuesta[0] = "0";
				respuesta[1] = "La longitud del valor ingresado es menor que la longitud mínimo permitida";
			}
		}
		return respuesta;
	}

	/**
	 * 
	 * Valida datos de tipo String, en caso de no cumplir las validaciones regresa
	 * un error.
	 * 
	 * @param dato
	 * @param minLength
	 * @param maxLength
	 * @return respuesta de validacion arreglo de dos posiciones posicion [1] 0
	 *         false o 1 true posicion [2] mensaje de error o vacio si es valido.
	 */
	public static String[] validaString(String dato, int minLength, int maxLength) {
		String[] respuesta = new String[2];
		respuesta = validaListaNegra(dato);
		if (dato != null) {
			if (maxLength != -1 && dato.length() > maxLength) {
				respuesta[0] = "0";
				respuesta[1] = "La longitud del valor ingresado es mayor que la longitud máximo permitida";
			}
			if (minLength != -1 && dato.length() < minLength) {
				respuesta[0] = "0";
				respuesta[1] = "La longitud del valor ingresado es menor que la longitud mínimo permitida";
			}
		}
		return respuesta;
	}

}
