/**
 * 
 */
package com.ejie.y42b.utils.exception;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map.Entry;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.NoSuchMessageException;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.dao.DataAccessException;
import org.springframework.web.servlet.i18n.CookieLocaleResolver;

/**
 *  
 * 
 */
public class Y42bUDAErrorManager {

	@Resource
	private ReloadableResourceBundleMessageSource messageSource;

	@Autowired
	private CookieLocaleResolver localeResolver;

	private Y42bUDAException ex;
	private Locale currentLanguage;

	public Y42bUDAErrorManager() {
	}

	public String process(Y42bUDAException ex, HttpServletRequest request) {

		this.ex = ex;

		if (!(ex instanceof Y42bUDAException)) {

			// throw new
			// Exception("A00UDAErrorManager initialization exception.");
		}

		this.currentLanguage = localeResolver.resolveLocale(request);
		this.messageSource.setFallbackToSystemLocale(false);

		return this.proccessExcetion();
	}

	/*
	 * Metodo que se emplea para analizar excepciones conocidaa, como por
	 * ejemplo las de base de datos, para crear mensajes internacionalizados en
	 * cada caso.
	 */
	private String proccessExcetion() {

		String i18nMessage = "";
		List<String> userMessages = new ArrayList<String>();

		for (Entry<String, Boolean> m : this.ex.getMessages().entrySet()) {

			String key = m.getKey();

			/*
			 * Si es una excecion de usuario (isUserException=true) se trata
			 * directamente y no se modifica los mensajes.
			 * 
			 * En caso de no ser una excepción de usuario
			 * (isUserException=false) se aplican tratramientos adicionales de
			 * excepciones, que pueden modificar el mensajae de la excepción.
			 */

			if (!(Boolean) m.getValue()) {

				/*
				 * Excepción no de usuario. Se aplican filtros de excepciones,
				 * que pueden modificar el mensaje de la excepción.
				 */

				key = this.filterExcetion(key, ex.getException());

			}

			/*
			 * Traducir el mensaje de excepción.
			 * 
			 * Try to get the interpolated Message in this order: 1- War, 2-EAR,
			 * 3- Hibernate's Default
			 */
			try {
				i18nMessage = messageSource.getMessage(key, null,
						this.currentLanguage);

			} catch (NoSuchMessageException e) {

				i18nMessage = key;
			}

			if (ex.getInfoException() != null) {
				StringBuffer userMessage = new StringBuffer();
				userMessage.append(i18nMessage).append(ex.getInfoException());

				userMessages.add(userMessage.toString());
			} else {
				userMessages.add(i18nMessage.toString());
			}
		}

		/*
		 * Formatear a JSON y generar XXXConflictingOperationException.
		 */
		StringBuffer formater = new StringBuffer();
		int count = 0;

		for (String error : userMessages) {

			if (0 == count) {

				formater.append(error);

			} else {

				formater.append("\", \"").append(error);
			}
			count++;
		}

		return "[\"" + formater.toString() + "\"]";
	}

	private String filterExcetion(String key, Throwable e) {

		String output = key;

		if (e instanceof DataAccessException) {

			/*
			 * TODO: Pendiente de implementación
			 */
			output = "SQL Exception";

		}

		return output + "Prueba filterException";
	}

	/**
	 * @return the messageSource
	 */
	public ReloadableResourceBundleMessageSource getMessageSource() {
		return messageSource;
	}

	/**
	 * @param messageSource
	 *            the messageSource to set
	 */
	public void setMessageSource(
			ReloadableResourceBundleMessageSource messageSource) {
		this.messageSource = messageSource;
	}

	/**
	 * @return the localeResolver
	 */
	public CookieLocaleResolver getLocaleResolver() {
		return localeResolver;
	}

	/**
	 * @param localeResolver
	 *            the localeResolver to set
	 */
	public void setLocaleResolver(CookieLocaleResolver localeResolver) {
		this.localeResolver = localeResolver;
	}

}
