package com.ejie.m62fb.utils.bean;

import java.io.IOException;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.StringTokenizer;

import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.map.MappingJsonFactory;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.util.StringUtils;

import com.ejie.m62fb.utils.error.UFException;
import com.ejie.m62fb.utils.constants.AppConstantes;

/**
 * <p>
 * Clase pata utilidades de los Beans
 * </p>
 * 
XXXX
XXXX
 * 
 */
public abstract class BeanUtils {
	private static final String PUNTO = ".";

	/**
	 * 
	 * @param modelo
	 *            campo que queremos encontrar y objeto que lo contiene
	 * @param classNames
	 *            Clases que implementan la entidad abstracta en la que deseamos
	 *            buscar una propiedad dentro de sus herencias
	 * @return Object valor del campo
	 */
	public static final Object getValor(BeanAccess modelo, String[] classNames) {
		// acceso (ejemploexpediente.vivienda.idvivienda)
		// valor (objeto ejemplo expediente)
		String classModel = modelo.getObjeto().getClass().getSimpleName();
		boolean find = false;
		for (String className : classNames) {
			if (classModel.equalsIgnoreCase(className)) {
				find = true;
				break;
			}
		}
		// If find is true we want to take the value
		if (find) {
			return getValor(modelo);
			// if (acceso!= null && acceso.contains(PUNTO))
			// {
			// try {
			// StringTokenizer token = new StringTokenizer(acceso,PUNTO);
			// //el primer token no sirve de nada aquí
			// token.nextToken();
			// valorAtributo = modelo;
			// do{
			// Class<? extends Object> clase =
			// Class.forName(valorAtributo.getClass().getName());
			// final String atributo = token.nextToken();
			// final String atributoCapitalizado =
			// StringUtils.capitalize(atributo);
			// final String objeto = "get" + atributoCapitalizado;
			// Method getter = clase.getMethod(objeto.toString(), new Class[0]);
			// valorAtributo = getter.invoke(valorAtributo, new Object[0]);
			// //si el dato es nulo se devuelve null y se
			// if (valorAtributo==null){
			// return null;
			// }
			// }while(token.hasMoreTokens());
			// }
			// catch (ClassNotFoundException e) {e.printStackTrace();}
			// catch (SecurityException e) {e.printStackTrace();}
			// catch (NoSuchMethodException e) {e.printStackTrace();}
			// catch (IllegalArgumentException e) {e.printStackTrace();}
			// catch (IllegalAccessException e) {e.printStackTrace();}
			// catch (InvocationTargetException e) {e.printStackTrace();}
			// }
			// else
			// {
			// valorAtributo = modelo;
			// }
			// return valorAtributo;
		}
		return null;
	}

	/**
	 * 
	 * @param modelo
	 *            Campo que queremos encontrar y objeto que lo contiene
	 * @return Object valor del campo
	 */
	public static Object getValor(BeanAccess modelo) {
		Object valorAtributo = null;
		if (modelo.getAcceso() != null && modelo.getAcceso().contains(PUNTO)) {

			try {
				StringTokenizer token = new StringTokenizer(modelo.getAcceso(),
						PUNTO);
				// el primer token no sirve de nada aquí
				token.nextToken();
				valorAtributo = modelo.getObjeto();
				do {

					Class<? extends Object> clase = Class.forName(valorAtributo
							.getClass().getName());
					final String atributo = token.nextToken();
					final String atributoCapitalizado = StringUtils
							.capitalize(atributo);
					final String objeto = "get" + atributoCapitalizado;
					Method getter = clase.getMethod(objeto.toString(),
							new Class[0]);
					valorAtributo = getter.invoke(valorAtributo, new Object[0]);
					// si el dato es nulo se devuelve null y se
					if (valorAtributo == null) {
						return null;
					}
				} while (token.hasMoreTokens());
			} catch (ClassNotFoundException e) {
				throw new UFException(e.getMessage(), e);
			} catch (SecurityException e) {
				throw new UFException(e.getMessage(), e);
			} catch (NoSuchMethodException e) {
				throw new UFException(e.getMessage(), e);
			} catch (IllegalArgumentException e) {
				throw new UFException(e.getMessage(), e);
			} catch (IllegalAccessException e) {
				throw new UFException(e.getMessage(), e);
			} catch (InvocationTargetException e) {
				throw new UFException(e.getMessage(), e);
			}
		} else {
			valorAtributo = modelo.getObjeto();
		}
		return (valorAtributo instanceof String ?((String) valorAtributo).trim():valorAtributo);
	}

	/**
	 * 
	 * @param valor
	 * @return
	 */
	public static int getInt(Integer valor) {
		if (valor != null) {
			return valor.intValue();
		}
		return 0;

	}

	/**
	 * 
	 * @param v
	 * @return
	 */
	public static String numberWithoutZero(String dni) {
		if (dni != null) {
			for (int i = 0; i < dni.length(); i++) {
				if (dni.charAt(0) == '0') {
					dni = dni.substring(1);
				} else {
					break;
				}
			}
		}
		return dni;
	}

	/**
	 * Metodo utilizado para realizar la serialización de un objeto en formato
	 * JSON para poder usarse con un elemento RUP Autocomplete.
	 * 
	 * @param obj
	 *            Objeto a serializar.
	 * @param label
	 *            Nombre de la propiedad que tiene el texto a mostrar
	 * @param value
	 *            Nombre de la propiedad que tiene el <code>value</code> del
	 *            objeto
	 * @return Serialización del objeto en formato JSON.
	 */
	public static String serialize(Object obj, String label, String value) {
		StringWriter sw = new StringWriter();
		ObjectMapper mapper = new ObjectMapper();
		MappingJsonFactory jsonFactory = new MappingJsonFactory();
		try {
			JsonGenerator jsonGenerator = jsonFactory.createJsonGenerator(sw);
			mapper.writeValue(jsonGenerator, obj);
			sw.close();

			return sw.getBuffer().toString().replaceAll(label, "label")
					.replaceAll(value, "value");
		} catch (IOException e) {
			throw new UFException(e.getMessage(), e);
		}
	}
	
	/***
	 * Method to convert a String in a Boolean. The data only could have the 
	 * S or N values
	 * @param data
	 * @return
	 */
	public static Boolean getBoolean(String data) {
			if(data.equals(AppConstantes.FALSE)){
				return false;
			}else if(data.equals(AppConstantes.TRUE)){
				return true;
			}else{
				throw new UFException("Not a valid Boolean value");
			}
	}
	
	public static String getBooleanBD(Boolean value) {
		if(!value){
			return AppConstantes.FALSE;
		}else if(value){
			return AppConstantes.TRUE;
		}else{
			throw new UFException("Not a valid Boolean value");
		}
}
}
