/*
 * Copyright 2012 E.J.I.E., S.A.
 *
 * Licencia con arreglo a la EUPL, Versión 1.1 exclusivamente (la «Licencia»);
 * Solo podrá usarse esta obra si se respeta la Licencia.
 * Puede obtenerse una copia de la Licencia en
 *
 * http://ec.europa.eu/idabc/eupl.html
 *
 * Salvo cuando lo exija la legislación aplicable o se acuerde por escrito,
 * el programa distribuido con arreglo a la Licencia se distribuye «TAL CUAL»,
 * SIN GARANTÍAS NI CONDICIONES DE NINGÚN TIPO, ni expresas ni implícitas.
 * Véase la Licencia en el idioma concreto que rige los permisos y limitaciones
 * que establece la Licencia.
 */
package com.ejie.u74a.control;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;

import javax.annotation.PostConstruct;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import org.springframework.web.servlet.i18n.CookieLocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.support.RequestContextUtils;

/**
 * 
 * Interceptor de UDA que se encarga de lo siguiente: 1- Gestiona las variables relativas a idioma por defecto e idiomas
 * de la aplicación. En caso de no definir alguna de las variables se producirá un error en despliegue indicando la
 * causa del error. 2- En la invocación a un controller gestiona la cookie y el parámetro para la gestión del lenguage
 * de la aplicación
 * 
 *  
 * 
 */
public class MvcInterceptor extends HandlerInterceptorAdapter {

	private String paramName = LocaleChangeInterceptor.DEFAULT_PARAM_NAME;
	private String defaultLanguage;
	private String availableLangs;

	@Autowired()
	private WebApplicationContext webApplicationContext;

	/**
	 * Comprobar que se han definido correctamente las variables necesarias para la aplicación: - defaultLanguage :
	 * Idioma por defecto - availableLangs: Idiomas permitidos en la aplicación
	 */
	@PostConstruct()
	public void postConstruct() {
		List<String> properties = new ArrayList<String>();
		if (this.defaultLanguage == null) {
			properties.add("defaultLanguage");
		}
		if (this.availableLangs == null) {
			properties.add("availableLangs");
		}
		if (!properties.isEmpty()) {
			String war = this.webApplicationContext.getServletContext().getContextPath().substring(1);
			throw new IllegalStateException(
					"No se ha definido correctamente el bean 'MvcInterceptor' en el fichero mvc-config.xml del proyecto <"
							+ war + ">. Revisar propiedad(es): " + properties.toString());
		}
	}

	/**
	 * Método que se ejecuta antes del método del Controller.
	 * 
	 * @param request Request
	 * @param response Response
	 * @param handler Handler
	 * 
	 * @return true, si se ejecuta correctamente
	 * 
	 * @throws Exception Excepción
	 */
	@Override()
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

		Locale locale = null;

		// Parámetro cambio idioma
		String languageParam = request.getParameter(this.paramName);

		// Viene de integración con la aplicación de Ibermática
		String languageSessionParam = (String) request.getSession().getAttribute(this.paramName);
		// /////////////

		if (languageParam != null && this.availableLangs.contains(languageParam)) {
			locale = new Locale(languageParam);
		} else if (languageSessionParam != null && this.availableLangs.contains(languageSessionParam)) { // por si viene
																											// de la
																											// integración
			locale = new Locale(languageSessionParam);
			request.getSession().removeAttribute(this.paramName); // eliminamos el atributo de la sesión
		} else {
			// Cookies
			String cookieName = ((CookieLocaleResolver) RequestContextUtils.getLocaleResolver(request)).getCookieName();
			Cookie cookie = getLanguageCookie(request.getCookies(), cookieName,
					Arrays.asList(this.availableLangs.trim().split("\\s*,\\s*")));
			if (cookie != null) {
				locale = new Locale(cookie.getValue());
			} else {
				locale = new Locale(this.defaultLanguage);
			}
		}

		// Modificación de la Locale y Cookie
		LocaleContextHolder.setLocale(locale);
		((CookieLocaleResolver) RequestContextUtils.getLocaleResolver(request)).setLocale(request, response, locale); // Sobreescribir
																														// cookie
		return true;
	}

	/**
	 * Función que busca la cookie de idioma y determina si es idioma válido (devuelve la cookie)
	 * 
	 * @param cookies Conjunto de cookies de la request
	 * @param cookieName Nombre de la cookie de idioma (default 'language')
	 * @param availableLangs Lista con los idiomas posibles (es, eu, en, fr)
	 * @return Si es un idioma válido devuelve la cookie, si no devuelve null
	 */
	private Cookie getLanguageCookie(Cookie cookies[], String cookieName, List<String> availableLangs) {
		if (cookies != null) {
			for (Cookie cookie : cookies) {
				if (cookie.getName().equals(cookieName) && availableLangs.contains(cookie.getValue())) {
					return cookie;
				}
			}
		}
		return null;
	}

	/**
	 * Obtiene el campo paramName
	 * 
	 * @return paramName
	 */
	public String getParamName() {
		return this.paramName;
	}

	/**
	 * Establece el campo paramName
	 * 
	 * @param paramName paramName
	 */
	public void setParamName(String paramName) {
		this.paramName = paramName;
	}

	/**
	 * Obtiene el campo defaultLanguage
	 * 
	 * @return defaultLanguage
	 */
	public String getDefaultLanguage() {
		return this.defaultLanguage;
	}

	/**
	 * Establece el campo defaultLanguage
	 * 
	 * @param defaultLanguage defaultLanguage
	 */
	public void setDefaultLanguage(String defaultLanguage) {
		this.defaultLanguage = defaultLanguage;
	}

	/**
	 * Obtiene el campo availableLangs
	 * 
	 * @return availableLangs
	 */
	public String getAvailableLangs() {
		return this.availableLangs;
	}

	/**
	 * Establece el campo availableLangs
	 * 
	 * @param availableLangs availableLangs
	 */
	public void setAvailableLangs(String availableLangs) {
		this.availableLangs = availableLangs;
	}

}
