package com.ejie.ab04b.exception;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

import com.ejie.ab04b.util.ErroresViewHelper;
import com.ejie.ab04b.util.UtilidadesWar;
import com.ejie.x38.util.IframeXHREmulationUtils;
import com.gfi.utils.Utilities;

/**
 * Manejador de excepciones
 * 
 * @author GFI
 * 
 */
public class AB04BExceptionHandler {

	/**
	 * Tiles de error
	 */
	public static final String TILES_ERROR = "customError";

	/**
	 * Tiles de acceso denegado
	 */
	private static final String TILES_DENEGADO = "accessDenied";

	/**
	 * Literal de error de aplicación
	 */
	public static final String ERROR_APLIC = "error.aplicacion";
	/**
	 * Literal de acceso denegado
	 */
	private static final String ERROR_ACCESO_DENEGADO = "error.accesoDenegado";
	/**
	 * Parametro de la respuesta de Ajax
	 */
	private static final String RESPUESTA_AJAX = "X-Requested-With";

	@Autowired()
	private ReloadableResourceBundleMessageSource messageSource;

	private static final Logger LOGGER = LoggerFactory
			.getLogger(AB04BExceptionHandler.class);

	/**
	 * Manejador de excepciones controladas del tipo 'ErrorGenericoException'.
	 * 
	 * exception ErrorGenericoException request HttpServletRequest response
	 * HttpServletResponse ModelAndView
	 * 
	 * exception the exception request the request response the response the
	 * model and view
	 *
	 * @param exception
	 *            the exception
	 * @param request
	 *            the request
	 * @param response
	 *            the response
	 * @return the model and view
	 * @throws IOException
	 *             IOException
	 */
	@ExceptionHandler(value = ErrorGenericoException.class)
	public ModelAndView handleErrorGenericoException(
			ErrorGenericoException exception, HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		ModelAndView modelAndView = new ModelAndView();
		if (request.getHeaders(AB04BExceptionHandler.RESPUESTA_AJAX)
				.hasMoreElements()) {
			UtilidadesWar.sendError(ErroresViewHelper.obtenerErrorRup(
					this.messageSource, exception.getErrorsFields()), response);
		} else if (IframeXHREmulationUtils.isIframeEmulationRequired(request)) {
			ErroresViewHelper.writeRdoIframe(request, response,
					exception.isGeneraTextArea(),
					ErroresViewHelper.obtenerErrorRup(this.messageSource,
							exception.getErrorsFields()));
		} else {
			// Informar Mensaje de error
			request.setAttribute("errorMessage",
					ErroresViewHelper.obtenerErrorRup(this.messageSource,
							exception.getErrorsFields()));
			if (!Utilities.isEmpty(exception.getTiles())) {
				modelAndView.setViewName(exception.getTiles());
			} else {
				modelAndView.setViewName(AB04BExceptionHandler.TILES_ERROR);
			}
		}
		return modelAndView;
	}

	/**
	 * Manejador de excepciones controladas del tipo 'ErrorNoFeedbackException'.
	 * 
	 * exception ErrorNoFeedbackException request HttpServletRequest response
	 * HttpServletResponse ModelAndView
	 * 
	 * exception the exception request the request response the response the
	 * string
	 *
	 * @param exception
	 *            the exception
	 * @param request
	 *            the request
	 * @param response
	 *            the response
	 * @return the string
	 * @throws IOException
	 *             IOException
	 */
	@ExceptionHandler(value = ErrorNoFeedbackException.class)
	public String handleErrorNoFeedbackException(
			ErrorNoFeedbackException exception, HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		String modelAndView = null;
		if (request.getHeaders(AB04BExceptionHandler.RESPUESTA_AJAX)
				.hasMoreElements()) {
			UtilidadesWar.sendError(exception.getErrorCode(), response);
		} else if (IframeXHREmulationUtils.isIframeEmulationRequired(request)) {
			ErroresViewHelper.writeRdoIframe(request, response, false,
					exception.getErrorCode());
		} else {
			// Informar Mensaje de error
			request.setAttribute("errorMessage", exception.getErrorCode());
			if (!Utilities.isEmpty(exception.getTiles())) {
				modelAndView = exception.getTiles();
			} else {
				modelAndView = AB04BExceptionHandler.TILES_ERROR;
			}
		}
		return modelAndView;
	}

	/**
	 * Manejador de excepciones controladas del tipo 'AccesoDenegadoException'.
	 * Se producen cuando el usuario no tiene permiso para acceder a la
	 * funcionalidad
	 * 
	 * exception AccesoDenegadoException request HttpServletRequest response
	 * HttpServletResponse ModelAndView
	 * 
	 * exception the exception request the request response the response the
	 * string
	 *
	 * @param exception
	 *            the exception
	 * @param request
	 *            the request
	 * @param response
	 *            the response
	 * @return the string
	 * @throws IOException
	 *             IOException
	 */
	@ExceptionHandler(value = AccesoDenegadoException.class)
	public String handleAccessDeniedException(AccesoDenegadoException exception,
			HttpServletRequest request, HttpServletResponse response)
			throws IOException {
		String modelAndView = null;
		List<ErrorField> errorFields = new ArrayList<ErrorField>();
		errorFields.add(new ErrorField(null,
				AB04BExceptionHandler.ERROR_ACCESO_DENEGADO));
		if (request.getHeaders(AB04BExceptionHandler.RESPUESTA_AJAX)
				.hasMoreElements()) {
			UtilidadesWar.sendError(ErroresViewHelper.obtenerErrorRup(
					this.messageSource, errorFields), response);
		} else if (IframeXHREmulationUtils.isIframeEmulationRequired(request)) {
			ErroresViewHelper.writeRdoIframe(request, response, false,
					ErroresViewHelper.obtenerErrorRup(this.messageSource,
							errorFields));
		} else {
			if (request.getAttribute("esRecargaPasoExcepcion") == null) {
				modelAndView = AB04BExceptionHandler.TILES_DENEGADO;
			} else {
				request.setAttribute("errorsMessages", null);
				modelAndView = AB04BExceptionHandler.TILES_DENEGADO;
			}
		}
		return modelAndView;
	}

	/**
	 * Manejador de excepciones controladas del tipo 'DatosIdentidadException'.
	 * 
	 * exception DatosIdentidadException request HttpServletRequest response
	 * HttpServletResponse ModelAndView
	 * 
	 * exception the exception request the request response the response the
	 * string
	 *
	 * @param exception
	 *            the exception
	 * @param request
	 *            the request
	 * @param response
	 *            the response
	 * @return the string
	 * @throws IOException
	 *             IOException
	 */
	@ExceptionHandler(value = DatosIdentidadException.class)
	public String handleDatosIdentidadException(
			DatosIdentidadException exception, HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		String modelAndView = null;
		if (request.getHeaders(AB04BExceptionHandler.RESPUESTA_AJAX)
				.hasMoreElements()) {
			List<ErrorField> errorFields = new ArrayList<ErrorField>();
			errorFields.add(new ErrorField("maint.expediente.dni",
					exception.getCodLiteralError()));
			UtilidadesWar.sendError(ErroresViewHelper.obtenerErrorRup(
					this.messageSource, errorFields), response);
		} else {
			this.handleGeneral(exception, request, response);
		}
		return modelAndView;
	}

	/**
	 * Gestiona el resto de excepciones.
	 * 
	 * exception Exception request HttpServletRequest response
	 * HttpServletResponse ModelAndView
	 * 
	 * exception the exception request the request response the response the
	 * model and view
	 *
	 * @param exception
	 *            the exception
	 * @param request
	 *            the request
	 * @param response
	 *            the response
	 * @return the model and view
	 * @throws IOException
	 *             e
	 */
	@ExceptionHandler()
	public ModelAndView handleGeneral(Exception exception,
			HttpServletRequest request, HttpServletResponse response)
			throws IOException {

		AB04BExceptionHandler.LOGGER.error(
				"Error!!! -> Se ha producido una excepcion!!!", exception);

		ModelAndView modelAndView = null;
		List<ErrorField> errorFields = new ArrayList<ErrorField>();
		errorFields
				.add(new ErrorField(null, AB04BExceptionHandler.ERROR_APLIC));
		// Llamada Ajax
		if (request.getHeaders(AB04BExceptionHandler.RESPUESTA_AJAX)
				.hasMoreElements()) {
			response.sendError(HttpServletResponse.SC_NOT_ACCEPTABLE,
					ErroresViewHelper.obtenerErrorRup(this.messageSource,
							errorFields));
			return modelAndView;
		} else if (IframeXHREmulationUtils.isIframeEmulationRequired(request)) {
			ErroresViewHelper.writeRdoIframe(request, response, false,
					ErroresViewHelper.obtenerErrorRup(this.messageSource,
							errorFields));
		} else {
			modelAndView = new ModelAndView();
			modelAndView.setViewName(AB04BExceptionHandler.TILES_ERROR);
		}
		return modelAndView;
	}

}
