package com.ejie.ab39a.filter;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.ejie.ab39a.model.Entidades;
import com.ejie.ab39a.model.TecnicosEntidad;
import com.ejie.ab39a.seguridad.UsuarioConectado;
import com.ejie.ab39a.seguridad.UtilSeguridad;
import com.ejie.ab39a.service.EntidadesService;
import com.ejie.ab39a.service.TecnicosEntidadService;
import com.ejie.ab39a.service.client.PlateaService;
import com.ejie.x38.security.PreAuthenticateProcessingFilter;
import com.ejie.x38.security.UserCredentials;
import com.ejie.ab39a.constantes.Constantes;

/**
 * Y98aPreAuthenticateProcessingFilter.
 * 
 *  
 * 
 */
public class AB39aPreAuthenticateProcessingFilter extends PreAuthenticateProcessingFilter {

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

	private static final int STRINGBUILDER_TRAZA = 4096;

	@Autowired
	private TecnicosEntidadService tecnicosEntidadService;

	@Autowired
	private EntidadesService entidadesService;

	@Autowired
	private PlateaService plateaService;

	/**
	 * Funcion que crea el usuario conectado, con los datos basicos del
	 * userCredential y los datos necesarios para nuestra aplicacion
	 * 
	 * @param request
	 *            HttpServletRequest
	 * 
	 * @return Object
	 */
	@Override
	protected synchronized Object getPreAuthenticatedCredentials(HttpServletRequest request) {

		AB39aPreAuthenticateProcessingFilter.logger.debug("getPreAuthenticatedCredentials - Inicio");
		UsuarioConectado usuarioConectado = null;

		try {

			UserCredentials user = (UserCredentials) super.getPreAuthenticatedCredentials(request);

			usuarioConectado = (UsuarioConectado) user;

			if (usuarioConectado.isPrimeraVez()) {
				AB39aPreAuthenticateProcessingFilter.logger.debug("getPreAuthenticatedCredentials - ES PRIMERA VEZ");
				usuarioConectado.setPrimeraVez(false);
			} else {
				AB39aPreAuthenticateProcessingFilter.logger.debug("getPreAuthenticatedCredentials - NO ES PRIMERA VEZ");
			}

			if (usuarioConectado.isTecnicoEntidad()) {
				TecnicosEntidad tecnicosEntidad = new TecnicosEntidad();
				tecnicosEntidad.setDocidentificacion(usuarioConectado.getNif());
				List<TecnicosEntidad> listaTecnicosEntidad = this.tecnicosEntidadService.findAll(tecnicosEntidad, null);

				if (listaTecnicosEntidad != null && !listaTecnicosEntidad.isEmpty()) {

					tecnicosEntidad = listaTecnicosEntidad.get(0);
					Entidades entidades = new Entidades();
					TecnicosEntidad tecnicosEntidadAux = new TecnicosEntidad();
					tecnicosEntidadAux.setCodtecnico(tecnicosEntidad.getCodtecnico());
					entidades.setTecnicosEntidad(tecnicosEntidadAux);
					tecnicosEntidad.setEntidadeses(this.entidadesService.findAll(entidades, null));
					usuarioConectado.setTecnicosEntidad(tecnicosEntidad);

					if (tecnicosEntidad.getEntidadeses() == null || tecnicosEntidad.getEntidadeses().isEmpty()) {
						usuarioConectado.setEsValidado(false);
						AB39aPreAuthenticateProcessingFilter.logger.debug("Tecnico de Entidad: NO TIENE ENTIDADES");
					} else if (!usuarioConectado.isCertificadoAccesoDirecto()) {
						AB39aPreAuthenticateProcessingFilter.logger
								.debug("Tecnico de Entidad:NO es certificado de entidad");

						List<Entidades> listaEntidades = this.plateaService.getEntidadesTrabajaTecnico(tecnicosEntidad);
						usuarioConectado.setListaEntidadesRdr(listaEntidades);
						// solo hay que tener en cuenta las entidades en las que
						// trabaje y
						// esten dadas de alta en el RdR
						if (listaEntidades != null && !listaEntidades.isEmpty()) {

							AB39aPreAuthenticateProcessingFilter.logger
									.debug("La lista de entidades en el RDR NO es vacia");
							usuarioConectado.verificarEntidadesTrabaja(listaEntidades);

							if (tecnicosEntidad.getEntidadeses() != null) {
								AB39aPreAuthenticateProcessingFilter.logger.debug("La lista de entidades tras MERGE:"
										.concat((tecnicosEntidad.getEntidadeses() != null
												? String.valueOf(tecnicosEntidad.getEntidadeses().size()) : "")));
							}
							if (tecnicosEntidad.getEntidadeses() == null
									|| tecnicosEntidad.getEntidadeses().isEmpty()) {
								AB39aPreAuthenticateProcessingFilter.logger
										.debug("La lista de entidades tras MERGE es vacia o nula");
								usuarioConectado.setEsValidado(false);
							} else {

								List<Entidades> listaEntidadesDatosNoInformados = UtilSeguridad
										.listaEntidadesDatosNoInformados(tecnicosEntidad.getEntidadeses());
								usuarioConectado.setListaEntidadesNoCompletas(listaEntidadesDatosNoInformados);

								if (listaEntidadesDatosNoInformados != null
										&& !listaEntidadesDatosNoInformados.isEmpty()) {
									AB39aPreAuthenticateProcessingFilter.logger
											.debug("La lista de entidades tiene alguna no completa");
									usuarioConectado.setRellenarDatosIncompletos(true);
								} else {
									AB39aPreAuthenticateProcessingFilter.logger
											.debug("La lista de entidades tiene todas completas");
								}
								if (tecnicosEntidad.getEntidadeses() != null
										&& tecnicosEntidad.getEntidadeses().size() == 1) {
									usuarioConectado.setEntidadPrincipal(tecnicosEntidad.getEntidadeses().get(0));
									Entidades xaux = tecnicosEntidad.getEntidadeses().get(0);
									AB39aPreAuthenticateProcessingFilter.logger.debug(
											"SE PONE ENTIDAD PRINCIPAL:".concat(String.valueOf(xaux.getCodentidad()))
													.concat("-cif:").concat(xaux.getCifnif()));
								} else if (request.getSession()
                                        .getAttribute(Constantes.SESSION_ENTIDAD_PRINCIPAL) != null) {
                                    tecnicosEntidad.setEntidadPrincipal((Entidades) request.getSession()
                                            .getAttribute(Constantes.SESSION_ENTIDAD_PRINCIPAL));
                                } else {
									AB39aPreAuthenticateProcessingFilter.logger.debug("NO SE PONE ENTIDAD PRINCIPAL");
								}
							}
						} else {
							AB39aPreAuthenticateProcessingFilter.logger
									.debug("La lista de entidades en el RDR es vacia o nula");

							usuarioConectado.getTecnicosEntidad().setEntidadeses(null);
							usuarioConectado.setEsValidado(false);

						}
					} else if (usuarioConectado.getIsCertificate()) {
						// ha accedido con txartela de entidad
						Entidades entidad = new Entidades();
						String cif = usuarioConectado.getCifEntidadFormCertificado();
						AB39aPreAuthenticateProcessingFilter.logger
								.debug("Tecnico de Entidad - Txartela de Entidad:".concat((cif == null ? "" : cif)));

						if (cif == null || cif.trim().length() == 0) {
							usuarioConectado.setEsValidado(false);
						} else {

							entidad.setCifnif(cif);

							List<Entidades> listaEntidad = this.entidadesService.findAll(entidad, null);
							if (listaEntidad != null && !listaEntidad.isEmpty()) {
								if (listaEntidad.size() > 1) {
									AB39aPreAuthenticateProcessingFilter.logger.debug(
											"Tecnico de Entidad - Txartela de Entidad: devuelve mas de una entidad para ese DNI");
								}
								entidad = listaEntidad.get(0);
								usuarioConectado.setEntidadPrincipal(entidad);

								if (UtilSeguridad.hayEntidadDatosNoInformados(entidad)) {
									usuarioConectado.setRellenarDatosIncompletos(true);
									listaEntidad = new ArrayList<Entidades>();
									listaEntidad.add(entidad);
									usuarioConectado.setListaEntidadesNoCompletas(listaEntidad);
								} else {
									List<Entidades> listaEntidadesDatosNoInformados = UtilSeguridad
											.listaEntidadesDatosNoInformados(tecnicosEntidad.getEntidadeses());
									usuarioConectado.setListaEntidadesNoCompletas(listaEntidadesDatosNoInformados);
									if (listaEntidadesDatosNoInformados != null
											&& !listaEntidadesDatosNoInformados.isEmpty()) {
										usuarioConectado.setRellenarDatosIncompletos(true);
									}
								}

							} else {
								AB39aPreAuthenticateProcessingFilter.logger
										.debug("Tecnico de Entidad - Txartela de Entidad: NO TIENE ENTIDADES");
								usuarioConectado.setEsValidado(false);
							}
						}
					}

				} else {
					AB39aPreAuthenticateProcessingFilter.logger.debug("Tecnico de Entidad NO EXISTE en BBDD");
					usuarioConectado.setEsValidado(false);
				}
			}

			AB39aPreAuthenticateProcessingFilter.pintaLogAtributos(usuarioConectado);
			AB39aPreAuthenticateProcessingFilter.logger.trace("Fin - Inicio");
		} catch (Exception e) {
			usuarioConectado = null;
			AB39aPreAuthenticateProcessingFilter.logger.error("getPreAuthenticatedCredentials", e);
			AB39aPreAuthenticateProcessingFilter.logger.debug("getPreAuthenticatedCredentials".concat(e.getMessage()));
		}

		return usuarioConectado;
	}

	/**
	 * Funcion que agrupa la traza que pinta los atributos del usuario conectado
	 * (para uso en desarrollo, se puede eliminar al pasar a produccion)
	 * 
	 * @param usuarioConectado
	 *            UsuarioConectado
	 */
	private static void pintaLogAtributos(UsuarioConectado usuarioConectado) {
		// Traza para ver todos los atributos del certificado:

		if (usuarioConectado == null) {
			AB39aPreAuthenticateProcessingFilter.logger.debug("pintaLogAtributos: USUARIO es NULO");
			return;
		}

		StringBuilder sbTraza = new StringBuilder(AB39aPreAuthenticateProcessingFilter.STRINGBUILDER_TRAZA);
		sbTraza.append("Parametros del objeto credentials del usuario conectado:\r\nparam: userName = ")
				.append(usuarioConectado.getSubjectCert("userName"));
		// sbTraza.append("\r\nparam: name =
		// ").append(usuarioConectado.getName());
		// sbTraza.append("\r\nparam: surname =
		// ").append(usuarioConectado.getSurname());
		// sbTraza.append("\r\nparam: fullName =
		// ").append(usuarioConectado.getFullName());
		sbTraza.append("\r\nparam: nif = ").append(usuarioConectado.getNif());
		sbTraza.append("\r\nparam: policy = ").append(usuarioConectado.getPolicy());
		sbTraza.append("\r\nparam: position = ").append(usuarioConectado.getPosition());
		sbTraza.append("\r\nparam: isCertificate = ").append(usuarioConectado.getIsCertificate());

		sbTraza.append("\r\nparam: SERIALNUMBER = ").append(usuarioConectado.getSubjectCert("SERIALNUMBER"));
		sbTraza.append("\r\nparam: surname = ").append(usuarioConectado.getSubjectCert("surname"));
		// sbTraza.append("\r\nparam: GIVENNAME =
		// ").append(usuarioConectado.getSubjectCert("GIVENNAME"));
		// sbTraza.append("\r\nparam: CN =
		// ").append(usuarioConectado.getSubjectCert("CN"));
		sbTraza.append("\r\nparam: DNQ = ").append(usuarioConectado.getSubjectCert("DNQ"));
		sbTraza.append("\r\nparam: OU = ").append(usuarioConectado.getSubjectCert("OU"));
		sbTraza.append("\r\nparam: O = ").append(usuarioConectado.getSubjectCert("O"));
		sbTraza.append("\r\nparam: C = ").append(usuarioConectado.getSubjectCert("C"));

		AB39aPreAuthenticateProcessingFilter.logger.debug(sbTraza.toString());
	}

}