package com.ejie.ab39a.seguridad;

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

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.context.SecurityContextHolder;
import org.w3c.dom.Document;

import com.ejie.ab39a.constantes.Constantes;
import com.ejie.ab39a.model.Entidades;
import com.ejie.ab39a.utils.UtilProperties;
import com.ejie.ab39a.utils.Utilidades;

import n38a.exe.N38APISesion;

/**
 * Clase de utilidades utilizada para el acceso al objeto de seguridad
 * UsuarioConectado
 * 
 *  
 * 
 */
public class UtilSeguridad {

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

	/**
	 * Constructor de Utilidades
	 */
	private UtilSeguridad() {
	}

	/**
	 * Devuelve el objeto UsuarioConectado guardado en el contexto.
	 * 
	 * @return UsuarioConectado
	 */
	public static UsuarioConectado getUsuarioConectado() {
		return (UsuarioConectado) SecurityContextHolder.getContext().getAuthentication().getCredentials();
	}

	/**
	 * Devuelve un String con el token de sesion
	 * 
	 * @param idAplic
	 *            String idAplic
	 * @return String String
	 */
	public static String getTokenXLNets(String idAplic) {

		String token = null;

		try {
			String simulacion = UtilProperties.Props.en_oficina.getValue();
			if (simulacion != null && Boolean.valueOf(simulacion)) {

				if (Constantes.APLICACION.equals(idAplic)) {
					return UtilProperties.getProperty(UtilProperties.Props.token_oficina.getValue());
				}
			} else {
				N38APISesion miAPISesion = new N38APISesion();
				Document miSesion;
				miSesion = miAPISesion.n38APISesionCrearApp(idAplic);
				return UtilSeguridad.dom2String(miSesion);
			}

		} catch (Exception e) {
			UtilSeguridad.logger.error("getTokenXLNets", "Error al obtener el TOKEN", e);
			return null;
		}

		return token;
	}

	/**
	 * Devuelve el token de sesion de la aplicacion pasada por parametro
	 * 
	 * @param idAplic
	 *            String idAplic
	 * @return String String
	 */
	public static Document getTokenDocumentXLNets(String idAplic) {
		UtilSeguridad.logger.trace("getTokenDocumentXLNets INI", idAplic);

		Document token = null;

		try {
			String simulacion = UtilProperties.Props.en_oficina.getValue();
			if (simulacion != null && Boolean.valueOf(simulacion)) {
				UtilSeguridad.logger.debug("La aplicacion esta en oficina. Se simula la obtencion del token.");
				if (Constantes.APLICACION.equals(idAplic)) {
					token = Utilidades.parseStringToDocument(UtilProperties.Props.token_oficina.getValue());
				}
			} else {
				N38APISesion miAPISesion = new N38APISesion();
				token = miAPISesion.n38APISesionCrearApp(idAplic);
			}

		} catch (Exception e) {
			UtilSeguridad.logger.error("getTokenXLNets: Error al obtener el TOKEN", e);
		}

		UtilSeguridad.logger.trace("getTokenDocumentXLNets FIN", Utilidades.parseDocumentToString(token));
		return token;
	}

	/**
	 * Convierte en String un documento org.w3c.dom.Document
	 * 
	 * @param doc
	 *            Document (Documento de tipo org.w3c.dom.Document)
	 * @return String (en el que se ha convertido el Document)
	 */
	public static String dom2String(Document doc) {

		TransformerFactory transformerFactory = TransformerFactory.newInstance();
		Transformer transformer = null;

		try {
			transformer = transformerFactory.newTransformer();
		} catch (javax.xml.transform.TransformerConfigurationException error) {
			UtilSeguridad.logger.error("dom2String: Error al crear la instancia de Transformer", error);
		}

		Source source = new DOMSource(doc);
		StringWriter writer = new StringWriter();
		Result result = new StreamResult(writer);

		try {
			transformer.transform(source, result);
		} catch (javax.xml.transform.TransformerException error) {
			UtilSeguridad.logger.error("dom2String: Error al transformar el Document", error);
		}

		return writer.toString();
	}

	/**
	 * Metodo que, a partir de una lista de entidades, devuelve otra lista de
	 * entidades a las cuales les falta por rellenar los campos email, telefono,
	 * numero de trabajadores o distribución por sexo
	 * 
	 * @param listaEntidades
	 *            List<Entidades> listaEntidades
	 * @return List<Entidades> lista
	 */
	// CHECKSTYLE:OFF
	public static List<Entidades> listaEntidadesDatosNoInformados(List<Entidades> listaEntidades) {
		List<Entidades> listaEntidadesDatosNoInformados = new ArrayList<Entidades>();
		if (listaEntidades != null && !listaEntidades.isEmpty()) {
			for (Entidades entidades : listaEntidades) {
				if (Entidades.tieneDatosTecnicoEntidadSincompletar(entidades)) {
					listaEntidadesDatosNoInformados.add(entidades);
				}
			}
		}
		return listaEntidadesDatosNoInformados;
	}

	// CHECKSTYLE:ON
	/**
	 * Metodo que devuelve si la entidad tiene todos los datos que debe meter el
	 * tecnico de entidad completados los campos email, telefono, numero de
	 * trabajadores o distribución por sexo
	 * 
	 * @param entidad
	 *            Entidades entidad
	 * @return boolean indica si la entidad tiene los datos informados
	 */

	public static boolean hayEntidadDatosNoInformados(Entidades entidad) {
		return Entidades.tieneDatosTecnicoEntidadSincompletar(entidad);
	}

}