/**
 * XXXX
 * Inserte aquí la descripción del tipo.
 * Fecha de creación: (14/05/07)
 */    
package com.ejie.p06b.util;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Date;

import com.ejie.p06b.datatype.logic.P06BError;
import com.ejie.p06b.general.P06BErrores;

/**
 * Esta clase valida los campos de los formularios (enteros, decimales, fechas...)
 * 
 * Cada método es específico para una validación devolviendo siempre un mensaje de error correspondiente.
 * 
 */
public class P06BFieldsValidations { 
	
	public static final String OBLIGATORIO = "oblig";
	public static final String ENTERO = "number";
	public static final String DECIMAL = "decimal";
	public static final String FECHA = "date";
	public static final String CMPFECHA = "cmpdate";
	public static final String HMIN = "horaM";
	public static final String TELEFONO = "telefono";
	public static final String MAIL = "mail";
	public static final String CMPLONGITUD = "cmplongitud";
	public static final String EJERCICIO = "ejercicio";
	
	public static ArrayList validation(ArrayList errors, String tipo, String nombreCampo, String valor, String idioma) {
		return validation(errors, tipo, nombreCampo, valor, idioma, 0);
   	}
	
	public static ArrayList validation(ArrayList errors, String tipo, String nombreCampo, Date fecha, String idioma) {
		if(tipo.equals(FECHA)){
			return isDate(errors,nombreCampo,fecha,idioma);
		}
		
		return errors;
   	}
	
	public static ArrayList validation(ArrayList errors, String tipo, String nombreCampo, String valor, String idioma, double valorMaximo) {
		if(tipo.equals(OBLIGATORIO)){
			return isOblig(errors,nombreCampo,valor);
		}
		if(tipo.equals(ENTERO)){
			return isEntero(errors,nombreCampo,valor);
		}
		if(tipo.equals(DECIMAL)){
			return isDecimal(errors,nombreCampo,valor,valorMaximo);
		}
		if(tipo.equals(FECHA)){
			return isDate(errors,nombreCampo,valor,idioma);
		}
		if(tipo.equals(HMIN)){
			return isHoraM(errors,nombreCampo,valor);
		}
		if(tipo.equals(TELEFONO)){
			return isTelefono(errors,nombreCampo,valor);
		}
		if(tipo.equals(EJERCICIO)){
			return isEjercicio(errors,nombreCampo,valor);
		}
		if(tipo.equals(MAIL)){
			return isMail(errors,nombreCampo,valor);
		}
		if(tipo.equals(CMPLONGITUD)){
			return compruebaLong(errors,nombreCampo,valor,valorMaximo);
		}
		
		return errors;
   	}
	
	public static ArrayList validation(ArrayList errors, String tipo, String nombreCampo1, String nombreCampo2, String valor1, String valor2, String idioma) throws Exception {
		if(tipo.equals(CMPFECHA)){
			return isDateBefore(errors,nombreCampo1,nombreCampo2,valor1,valor2,idioma);
		}
		return errors;
   	}
	
	/**
   	 *  Validacion de un valor como entero
     *  @param   nombreCampo   Nombre del campo que estamos validando
   	 *  @return  valor  valor a validar como entero
   	 */
	private static ArrayList isEntero(ArrayList errors, String nombreCampo,String valor) {
		if(valor!=null 
			&& !valor.equals("")){
			try{
				Integer.parseInt(valor.replaceAll("\\.",""));
			}catch(Exception e){
				P06BError error = new P06BError();
				error.setNombreCampo(nombreCampo);
				error.setCodigo(P06BErrores.P06B_ERROR_0004);
				errors.add(error);
				return errors;
			}
		}
		return errors;
   	}
	
	/**
   	 *  Validacion de un valor obligatorio
     *  @param   nombreCampo   Nombre del campo que estamos validando
   	 *  @return  valor  valor a validar como obligatorio
   	 */
	private static ArrayList isOblig(ArrayList errors, String nombreCampo,String valor) {
		if(valor==null 
		 		|| valor.equals("")){
		 	//Entonces el campo debe ser obligatorio
		 	P06BError error = new P06BError();
			error.setNombreCampo(nombreCampo);
			error.setCodigo(P06BErrores.P06B_ERROR_0005);
			errors.add(error);
			return errors;
		}
		return errors;
   	}
	
	/**
   	 *  Validacion de un valor como decimal 
   	 * 		ejemplo: 123.456,67
     *  @param   nombreCampo   Nombre del campo que estamos validando
   	 *  @return  valor  valor a validar como decimal
   	 */
	private static ArrayList isDecimal(ArrayList errors, String nombreCampo,String valor,double valorMaximo) {
		if(valor!=null 
			&& !valor.equals("")){
			try{
				//Compruebo si todo es un numero
				if(!P06BUtil.isNumero(valor))
					throw new Exception("Excepcion forzada");
				//TODO Cambiarlo a expresiones regulares: No está del todo OK
				String valorDouble = valor;
				//Miro que la coma no esté antes que el punto
				if(valorDouble.indexOf(",")!=-1
				   && valorDouble.indexOf(".")!=-1
				   && valorDouble.indexOf(",") < valorDouble.indexOf(".")){
					throw new Exception("Forzamos la excepcion");
				}
				//Tengo separar por punto y si cada porción son 3 números
				if(valorDouble.indexOf(".")!=-1){
					StringTokenizer st = new StringTokenizer(valorDouble,".");
					boolean primero = true;
					while(st.hasMoreTokens()){
						String ele= st.nextToken();
						if(ele.indexOf(",")!=-1){
							StringTokenizer st2 = new StringTokenizer(ele,",");
							String ele2 = st2.nextToken();
							if(!primero&&ele2.length()!=3){
								throw new Exception("Forzamos la excepcion");
							}
						}else{
							if(!primero&&ele.length()!=3){
								throw new Exception("Forzamos la excepcion");
							}
						}
						if(primero)
							primero = false;
					}
				}
				
				//Transformo los puntos en nada, y las comas en punto y lo transformo en Double
				//Si hubiera un caracter que no fuera numero o punto (ejm: 2323.45= daria una excepcion
				valorDouble = valorDouble.replaceAll("\\.","");
				valorDouble = valorDouble.replaceAll(",",".");
				Double.parseDouble(valorDouble);
				
				//Comprobar si el numero sobrepasa el valor maximo
				if (valorMaximo != 0 && Double.parseDouble(valorDouble) > valorMaximo){
					P06BError error = new P06BError();
					error.setNombreCampo(nombreCampo);
					error.setCodigo(P06BErrores.P06B_ERROR_0017);
					errors.add(error);
				}
			}catch(Exception e){
				P06BError error = new P06BError();
				error.setNombreCampo(nombreCampo);
				error.setCodigo(P06BErrores.P06B_ERROR_0006);
				errors.add(error);
				return errors;
			}
		}
		return errors;
   	}
	
	/**
   	 *  Validacion de un valor como fecha  dd/MM/YYYY
     *  @param   nombreCampo   Nombre del campo que estamos validando
   	 *  @return  valor  valor a validar como decimal
   	 */
	private static ArrayList isDate(ArrayList errors, String nombreCampo,String valor,String idioma) {
		if(valor!=null 
			&& !valor.equals("")){
				if(!P06BFecha.isFechaValida(valor,idioma)){
					P06BError error = new P06BError();
					error.setNombreCampo(nombreCampo);
					error.setCodigo(P06BErrores.P06B_ERROR_0007);
					errors.add(error);
					return errors;
				}
		}
		return errors;
   	}
	
	/**
   	 *  Validacion de un valor como fecha  dd/MM/YYYY
     *  @param   nombreCampo   Nombre del campo que estamos validando
   	 *  @return  valor  valor a validar como decimal
   	 */
	private static ArrayList isDate(ArrayList errors, String nombreCampo,Date fecha,String idioma) {
		if(fecha==null){
			P06BError error = new P06BError();
			error.setNombreCampo(nombreCampo);
			error.setCodigo(P06BErrores.P06B_ERROR_0007);
			errors.add(error);
			return errors;
		}
		return errors;
   	}

	/**
   	 *  Validacion de un valor como hora:minutos valida
     *  @param   nombreCampo   Nombre del campo que estamos validando
   	 *  @return  valor  valor a validar como hora:minutos
   	 */
	private static ArrayList isHoraM(ArrayList errors, String nombreCampo,String valor) {
		if(valor!=null 
			&& !valor.equals("")){
				if(!P06BFecha.isHoraValida(valor)){
					P06BError error = new P06BError();
					error.setNombreCampo(nombreCampo);
					error.setCodigo(P06BErrores.P06B_ERROR_0008);
					errors.add(error);
					return errors;
				}
		}
		return errors;
   	}
	
	/**
   	 *  Validacion de 2 fechas -> fecha desde (valor 1) y fecha hasta (valor 2)
   	 *  @return  lista de errores
	 * @throws Exception
	 * @throws ParseException
   	 */
	private static ArrayList isDateBefore(ArrayList errors, String nombreCampo1, String nombreCampo2 ,String valor1, String valor2 ,String idioma) throws Exception {
		try{
			if((valor1!=null 
				&& !valor1.equals(""))
				&&(valor2!=null 
						&& !valor2.equals(""))){
					if(!P06BFecha.isFechaBefore(valor1,valor2,idioma)){
						P06BError error = new P06BError();
						error.setNombreCampo(nombreCampo1);
						error.setCodigo(P06BErrores.P06B_ERROR_0011);
						errors.add(error);
						return errors;
					}
			}
		}catch(Exception e){
			throw new Exception(e);
		}
		return errors;
   	}
	
	/**
   	 *  Validacion de un valor como telefono
     *  @param   nombreCampo   Nombre del campo que estamos validando
   	 *  @return  valor  valor a validar como telefono
   	 */
	private static ArrayList isTelefono(ArrayList errors, String nombreCampo,String valor) {
		if(valor!=null && !valor.equals("")){
			try{
				/*valor = valor.replaceAll("\\.","");
				valor = valor.replaceAll(",","");
				valor = valor.replaceAll("-","");
				valor = valor.replaceAll(" ","");
				Integer.parseInt(valor);
				if (valor.length() < 9){
					P06BError error = new P06BError();
					error.setNombreCampo(nombreCampo);
					error.setCodigo(P06BErrores.P06B_ERROR_0018);
					errors.add(error);					
				}*/
				//Se valida con expresiones regulares. Se deben introducir exactamente 9 números.
				Pattern p = Pattern.compile("\\d{9}");
			    Matcher m = p.matcher(valor);
			    if (!m.find()){
			      	P06BError error = new P06BError();
					error.setNombreCampo(nombreCampo);
					error.setCodigo(P06BErrores.P06B_ERROR_0018);
					errors.add(error);
					return errors;
			    }
			}catch(Exception e){
				P06BError error = new P06BError();
				error.setNombreCampo(nombreCampo);
				error.setCodigo(P06BErrores.P06B_ERROR_0018);
				errors.add(error);
				return errors;
			}
		}
		return errors;
   	}
	
	
	/**
   	 *  Validacion de un valor como ejercicio
     *  @param   nombreCampo   Nombre del campo que estamos validando
   	 *  @return  valor  valor a validar como ejercicio
   	 */
	private static ArrayList isEjercicio(ArrayList errors, String nombreCampo,String valor) {
		if(valor!=null && !valor.equals("")){
			try{
				/*valor = valor.replaceAll("\\.","");
				valor = valor.replaceAll(",","");
				valor = valor.replaceAll("-","");
				valor = valor.replaceAll(" ","");
				Integer.parseInt(valor);
				if (valor.length() < 9){
					P06BError error = new P06BError();
					error.setNombreCampo(nombreCampo);
					error.setCodigo(P06BErrores.P06B_ERROR_0018);
					errors.add(error);					
				}*/
				//Se valida con expresiones regulares. Se deben introducir exactamente 9 números.
				Pattern p = Pattern.compile("\\d{4}");
			    Matcher m = p.matcher(valor);
			    if (!m.find()){
			      	P06BError error = new P06BError();
					error.setNombreCampo(nombreCampo);
					error.setCodigo(P06BErrores.P06B_ERROR_0027);
					errors.add(error);
					return errors;
			    }
			}catch(Exception e){
				P06BError error = new P06BError();
				error.setNombreCampo(nombreCampo);
				error.setCodigo(P06BErrores.P06B_ERROR_0027);
				errors.add(error);
				return errors;
			}
		}
		return errors;
   	}
	
	
	/**
   	 *  Validacion de un valor como mail
     *  @param   nombreCampo   Nombre del campo que estamos validando
   	 *  @return  valor  valor a validar como telefono
   	 */
	private static ArrayList isMail(ArrayList errors, String nombreCampo,String valor) {
		if(valor!=null && !valor.equals("")){
			try{
				//Se valida con expresiones regulares.
				//Pattern p = Pattern.compile("[^@\\s]+@[^@\\.\\s]+(\\.[^@\\.\\s]+)+");
				Pattern p = Pattern.compile("\\w+([\\.-]?\\w+)*@\\w+([\\.-]?\\w+)*(\\.\\w{2,3})+");
				Matcher m = p.matcher(valor);
			    if (!m.matches()){
			      	P06BError error = new P06BError();
					error.setNombreCampo(nombreCampo);
					error.setCodigo(P06BErrores.P06B_ERROR_0019);
					errors.add(error);
					return errors;
			    }
			}catch(Exception e){
				P06BError error = new P06BError();
				error.setNombreCampo(nombreCampo);
				error.setCodigo(P06BErrores.P06B_ERROR_0019);
				errors.add(error);
				return errors;
			}
		}
		return errors;
   	}
	

	/**
   	 *  Validacion de la longitud de un valor contra un maximo
     *  @param   nombreCampo   Nombre del campo que estamos validando
   	 *  @return  valor  valor a validar su longitud
   	 */
	private static ArrayList compruebaLong(ArrayList errors, String nombreCampo,String valor, double longMaxima) {
		if(valor!=null && !valor.equals("")){
			int longitudMaxima = (new Double(longMaxima)).intValue();
			if (valor.length()>longMaxima){
				P06BError error = new P06BError();
				error.setNombreCampo(nombreCampo);
				error.setCodigo(P06BErrores.P06B_ERROR_0020);
				errors.add(error);
				return errors;			
			}
		}
		return errors;
   	}


}	