/*
 * 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.ab39a.filter;

import java.io.IOException;
import java.util.Properties;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
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.security.core.context.SecurityContextHolder;

import com.ejie.x38.security.ExcludeFilter;
import com.ejie.ab39a.constantes.Constantes;
import com.ejie.ab39a.seguridad.UsuarioConectado;
import com.ejie.ab39a.util.UtilidadesWar;
import com.ejie.ab39a.utils.Utilidades;

/**
 * 
 *  
 * 
 */
public class FiltroCertificado implements ExcludeFilter, Filter {

	private String accessDeniedUrl;

	@Autowired
	private Properties certificados;
	private static final String PARAM_CERTIFICATES = "certificates";
	private static final String PARAM_VALIDAR_CERTIFICADOS = "validarcertificados";
	private static final String PARAM_CERTIFICATE_SEPARATOR = ",";
	private static final String VALIDAR_CERTIFICADOS = "1";

	private static final Logger logger = LoggerFactory.getLogger(FiltroCertificado.class);

	/**
	 * Method 'getAccessDeniedUrl'
	 * 
	 * @return Url de acceso denegado
	 */
	@Override
	public String getAccessDeniedUrl() {
		return this.accessDeniedUrl;
	}

	/**
	 * Method 'setAccessDeniedUrl'
	 * 
	 * @param accessDeniedUrl
	 *            String
	 */
	@Override
	public void setAccessDeniedUrl(String accessDeniedUrl) {
		this.accessDeniedUrl = accessDeniedUrl;
	}

	/**
	 * Aplica el filtro de seguridad especificado, a cualquier usuario que desee
	 * entrar a la aplicacion.
	 * 
	 * @param httpRequest
	 *            HttpServletRequest
	 * @param httpResponse
	 *            HttpServletResponse
	 * @return boolean
	 */
	@Override
	public boolean accept(HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
		FiltroCertificado.logger.debug("INI FiltroCertificado.accept");

		boolean accept = false;

		if (SecurityContextHolder.getContext().getAuthentication() == null) {
			FiltroCertificado.logger.debug("SecurityContextHolder.getContext().getAuthentication() == null es NULO");
			return true;
		}

		UsuarioConectado usuarioConectado = (UsuarioConectado) SecurityContextHolder.getContext().getAuthentication()
				.getCredentials();

		if (usuarioConectado == null || !usuarioConectado.isEsValidado()) {
			FiltroCertificado.logger.debug("FiltroCertificado: usuario es NULO o NO VALIDADO");
			return accept;
		}

		String policy = (usuarioConectado != null && usuarioConectado.getIsCertificate()) ? usuarioConectado.getPolicy()
				: null;

		boolean continuarValidacion = true;

		if (usuarioConectado.isTecnicoHps()) {
			FiltroCertificado.logger.debug("Es tecnico HPS");
			return true;
		}
		if (!usuarioConectado.isTecnicoHps() && !usuarioConectado.getIsCertificate()) {
			FiltroCertificado.logger.debug("TIENE XLNET PERO NO PERFIL DE ACCESO NI CERTIFICADO PARA SER DE ENTIDAD");
			return false;
		}

		// si es tecnico entidad siemore tiene que tener certificado
		if (usuarioConectado.getIsCertificate()) {

			if (Constantes.POLITICA_JUEGOBARCOS.equalsIgnoreCase(policy)) {
				FiltroCertificado.logger.debug("POLICY es JUEGO DE  BARCOS");
				accept = true;
			} else {

				FiltroCertificado.logger.debug("El usuario tiene certificado.");

				if (policy == null || policy.trim().length() == 0) {
					FiltroCertificado.logger.debug("POLICY es NULO - NO SE PUEDE ENTRAR");
					accept = false;
					continuarValidacion = false;
				}
				String validar = this.certificados.getProperty(FiltroCertificado.PARAM_VALIDAR_CERTIFICADOS);

				if (continuarValidacion
						&& (validar == null || !FiltroCertificado.VALIDAR_CERTIFICADOS.equals(validar))) {
					FiltroCertificado.logger.debug("NO SE VALIDAN LOS CERTIFICADOS");
					accept = true;
					continuarValidacion = false;

				}

				FiltroCertificado.logger.debug(Utilidades.obtenerCadena("Politica del usuario conectado: ", policy));
				String strCert = (String) this.certificados.get(FiltroCertificado.PARAM_CERTIFICATES);
				FiltroCertificado.logger.debug(Utilidades.obtenerCadena("Politicas aceptadas: ", strCert));
				if (continuarValidacion && strCert != null && !strCert.isEmpty() && policy != null
						&& policy.trim().length() > 0) {
					// Recogemos los certificados válidos
					String[] arrayCertificados = strCert.split(FiltroCertificado.PARAM_CERTIFICATE_SEPARATOR);
					for (int i = 0; i < arrayCertificados.length; i++) {
						accept = arrayCertificados[i].trim().equalsIgnoreCase(policy.trim());
						if (accept) {
							break;
						}
					}
				}
			}
		}
		// en este punto la validacion del certificado es correcto, validar
		// negocio

		if (accept) {
			if (usuarioConectado.isTecnicoBaja()) {
				FiltroCertificado.logger.debug(Utilidades.obtenerCadena("Esta de baja:"));
				accept = false;
			}
			if (accept && !usuarioConectado.isTieneEntidadesAsociadas()) {
				FiltroCertificado.logger
						.debug(Utilidades.obtenerCadena("Esta de baja o no tiene entidades asociadas: "));
				accept = false;
			}
		}

		FiltroCertificado.logger.debug("FIN FiltroCertificado.accept: " + accept);
		return accept;
	}

	@Override
	public void destroy() {
		FiltroCertificado.logger.debug("FIN FiltroCertificado.destroy: ");
	}

	@Override
	public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
			throws IOException, ServletException {
		FiltroCertificado.logger.debug("FiltroCertificado.doFilter: ");
		HttpServletRequest request = (HttpServletRequest) arg0;
		HttpServletResponse response = (HttpServletResponse) arg1;

		boolean accept = this.accept(request, response);

		FiltroCertificado.logger.debug("FiltroCertificado.doFilter:accept:".concat(String.valueOf(accept)));
		if (accept) {
			FiltroCertificado.logger.debug("FiltroCertificado.doFilter:doFilter");
			arg2.doFilter(arg0, arg1);
		} else {
			FiltroCertificado.logger.debug("FiltroCertificado.doFilter:No aceptado: a accessDenied");

			StringBuilder str = new StringBuilder(Constantes.STRING_BUILDER_INIT);
			str.append(UtilidadesWar.recuperarPartePortalSinWar(request));
			// String strUrl = str.toString();
			// if (strUrl != null && strUrl.trim().length() > 0 &&
			// !strUrl.endsWith("/")) {
			// str.append("/");
			// }
			str.append(this.accessDeniedUrl);
			FiltroCertificado.logger.debug("FiltroCertificado.doFilter:urlAccesDenied:".concat(str.toString()));
			response.sendRedirect(str.toString());

		}
		FiltroCertificado.logger.debug("FiltroCertificado.doFilter:Saliendo");
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		FiltroCertificado.logger.debug("FiltroCertificado.INIT: ");
	}
}