package m05bLdap;

import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Locale;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;

import m05bClasses.m05bConstantes;
import m05bClasses.m05bFileLog;
import m05bIdioma.m05bCResources;
import n38a.exe.N38APISesion;
import n38c.exe.N38API;
import n38c.exe.N38Estructura;

import org.apache.xpath.XPathAPI;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

/**
 * Clase auxiliar para tratar con LDAP
 */
public class SecurityHelpperXLNets implements ISecurityInfo {

    private HttpServletRequest request;
    private N38API n38API;
    private m05bFileLog miLog = new m05bFileLog();

    public SecurityHelpperXLNets() {
    }

    /* Asociar la request de la sesión N38 */
    public void setHttpRequest(HttpServletRequest request) throws SecurityHelpperException {
        try {
            this.request = request;
            n38API = new N38API(request);
        } catch(Exception e) {
            throw new SecurityHelpperException("Error al obtener instancia del api N38");
        }
    }

    /**
	 * Devuelve una string con el contenido del xml de sesión
	 *
	 * @return String con token Aplicación
	 */
	public String getTokenAplicacion() {
		N38APISesion n38apiSesion = new N38APISesion();
		Document tokenAplicacionDocument = n38apiSesion.n38APISesionCrearApp(m05bConstantes.CODIGO_APLICACION);
		return this.documentToString(tokenAplicacionDocument);
	}

    /* Obtener los perfiles asociados al Usuario que realiza Login.*/
    public String[] getPerfiles() throws SecurityHelpperException {
        try {
            String[] perfiles = this.n38API.n38ItemSesion("n38perfiles");
            return perfiles;
        } catch (Throwable e) {
            throw new SecurityHelpperException("SecurityHelpper:getPerfiles");
        }
    }

    /* Obtener el idioma asociado al Usuario que realiza Login.*/
    public String getIdioma() throws SecurityHelpperException {
        try {
            return n38API.n38ItemSesion("n38idioma")[0];
        } catch (Exception e) {
            throw new SecurityHelpperException("SecurityHelpper:getIdioma");
        }
    }

    /* Obtener la Persona asociada al Usuario que realiza Login.*/
    public String getPersonaNombre() throws SecurityHelpperException {
        try {
            String uidPersona = this.getPersonaUID();
            Document personaDocument = this.n38API.n38ItemObtenerPersonas("n38PuestoUID="+uidPersona);
            //SysLog.logLine("m05b",m05bXLNetsPrintWritter.print(personaDocument));

            String filtro = "//elemento[@subtipo=\"n38persona\"]/parametro[@id=\"cn\"]/valor/text()";
            //El cn contiene el nombre y apellidos de la persona.
            String nombre = XPathAPI.selectNodeList(personaDocument,filtro).item(0).getNodeValue();
            return nombre;
        } catch (Exception e) {
            throw new SecurityHelpperException("SecurityHelpper:getPersonaNombre");
        }
    }

    /* Obtener el código del usuario al Usuario que realiza Login.*/
    public String getUsuario() throws SecurityHelpperException {
    	try {
    		try {
    			return n38API.n38ItemSesion("n38personauid")[0];
    		} catch(Exception e) {
   				String filtro = "n38/elementos//elemento[@subtipo=\"N38Sesion\"]/parametro[@id=\"n38personauid\"]/valor/text()";
   				return XPathAPI.selectSingleNode(n38API.n38ItemSesion(), filtro).getNodeValue();
    		}
        } catch (Exception e) {
            throw new SecurityHelpperException("SecurityHelpper:getUsuario");
        }
    }

    /* Obtener el uid del usuario que realiza Login.*/
    public String getPersonaUID() throws SecurityHelpperException {
        try {
            return n38API.n38ItemSesion("n38puestouid")[0];
        } catch (Exception e) {
            throw new SecurityHelpperException("SecurityHelpper:getPersonaUID");
        }
    }

    /* Obtener el uid del usuario que realiza Login.*/
    public String getPersonaDni() throws SecurityHelpperException {
        try {
            return n38API.n38ItemSesion("dni")[0];
        } catch (Exception e) {
            throw new SecurityHelpperException("SecurityHelpper:getPersonaUID");
        }
    }

    /* Comprobar si el usuario tiene permiso para la función dada */
    public boolean hasPermission(String uidFuncion) throws SecurityHelpperException {
        NodeList lista;
        try {
            Document itemSeguridad = n38API.n38ItemSeguridad(uidFuncion);
            lista = XPathAPI.selectNodeList(itemSeguridad,"//elementos");
        } catch (Exception e) {
            throw new SecurityHelpperException("SecurityHelpperXLNets:hasPermision");
        }
        return ( lista.getLength() != 0 );
    }


    /**
     * Crea un objecto de seguridad para una funcion dada.
     * Si devuelve Null es que no se tiene permiso para esa Función o recurso de LDAP.
     */
    public SecurityObject getSecurityObject(String uidFuncion)throws SecurityHelpperException {
        SecurityObject objetoSeguridad = null;
        String clocLocale = "ES";
        String XLNetsIdioma = "";

        try {
            objetoSeguridad = new SecurityObject(n38API.n38ItemSesion("n38puestouid")[0]);
            objetoSeguridad.setPerfiles(this.getPerfiles());
			XLNetsIdioma=this.getIdioma();
            //miLog.addTraza("User", "SecurityHelpperXLNets", "GET IDIOMA ACTUAL: " + XLNetsIdioma, m05bConstantes.LOG_NIVEL_ALTO);
            if (XLNetsIdioma != null) {
	            objetoSeguridad.setIdioma(XLNetsIdioma);
	            if (XLNetsIdioma.equals("1"))
	            	clocLocale = "ES";
	            else
					clocLocale = "EU";
				objetoSeguridad.setPersona(this.getPersonaNombre());
				objetoSeguridad.setUsuario(this.getUsuario());
				objetoSeguridad.setDni(this.getPersonaDni());
	      		//clocLocale = new Locale(XLNetsIdioma, "");
            	//miLog.addTraza(m05bConstantes.LOG_NO_USER, m05bConstantes.LOG_NO_SRC, "IDIOMA ACTUAL-1: " + clocLocale, m05bConstantes.LOG_NIVEL_ALTO);
				m05bCResources idioma = new m05bCResources(new Locale(clocLocale,""));
	            idioma.setIdiomaActual(clocLocale);
            	//miLog.addTraza(m05bConstantes.LOG_NO_USER, m05bConstantes.LOG_NO_SRC, "IDIOMA ACTUAL-2: " + idioma.getIdiomaActual(), m05bConstantes.LOG_NIVEL_ALTO);
	            HttpSession session = request.getSession(true);
	            session.setAttribute("IdiomaActual",idioma);
	        }
        } catch (Exception e) {
            miLog.addTraza("persona", "Security Helpper XLNets", "EXCEPTION: " + e, m05bConstantes.LOG_NIVEL_ALTO);
            throw new SecurityException("SecurityHelpperException:getSecurityObject: "+e);
        }
        return objetoSeguridad;
    }

    public ArrayList getDepartamentosGrupoOrganicoXLNETs(String grupoOrganico) throws SecurityHelpperException {

    	ArrayList listaDepartamentos = new ArrayList();
    	try
    	{
	    	N38Estructura estructura = new N38Estructura();
	    	estructura.setTipoEntrada("GO");
	    	estructura.setUidEntrada(grupoOrganico);
	    	Document document = n38API.n38ItemOrganizacion(estructura);
	    	
	    	NodeList lista;
	    	try {
				//lista = XPathAPI.selectNodeList(document, "/n38/elementos/elemento/elemento[@subtipo=\"n38gruposorganicos\"]");
	    		lista = XPathAPI.selectNodeList(document, "//elemento[@subtipo=\"n38gruposorganicos\"]");
			} catch (TransformerException e) {
				// TODO Auto-generated catch block
				miLog.addTraza("iniro", "getDepartamentosXLNETs error1:", e.getMessage(), 1);
				throw new SecurityHelpperException("SecurityHelpperXLNets:getDepartamentosXLNETs");
			}
	
			m05bDepartamentoXLNET departamento;

			if (lista != null) {
			    int nNodos = lista.getLength();
			    if (nNodos > 0) {
			    	for (int i = 0; i < nNodos; i++) {
			    		if (lista.item(i).getChildNodes().getLength() > 0) {

			    			String v1 = XPathAPI.selectNodeList(lista.item(i), "parametro[@id=\"n38uidgrupoorganico\"]/valor/text()").item(0).getNodeValue();
			    			String v2 = XPathAPI.selectNodeList(lista.item(i), "parametro[@id=\"n38cadescripcion\"]/valor/text()").item(0).getNodeValue();
			    			String v3 = XPathAPI.selectNodeList(lista.item(i), "parametro[@id=\"n38eudescripcion\"]/valor/text()").item(0).getNodeValue();

			    			departamento = new m05bDepartamentoXLNET();
			    			departamento.setCodigo(v1);
			    			departamento.setDescC(v2);
			    			departamento.setDescE(v3);

			    			//miLog.addTraza("iniro", "getDepartamentosXLNETs v1", v1, 1);
			    			//miLog.addTraza("iniro", "getDepartamentosXLNETs v2", v2, 1);
			    			//miLog.addTraza("iniro", "getDepartamentosXLNETs v3", v3, 1);

			    			listaDepartamentos.add(departamento);
			    		}
			    	}
			    }
			}
    	}
    	catch (Exception e) {
    		miLog.addTraza("iniro", "getDepartamentosXLNETs error2:", e.getMessage(), 1);
    	}

	    return listaDepartamentos;
	}

    public ArrayList getDepartamentosXLNETs() throws SecurityHelpperException {

    	ArrayList listaDepartamentos = new ArrayList();
    	try
    	{
	    	N38Estructura estructura = new N38Estructura();
	    	estructura.setTipoEntrada("ALL");
	    	estructura.setUidEntrada("1");
	    	Document document = n38API.n38ItemOrganizacion(estructura); //"ALL", "1"
	    	
	    	NodeList lista;
	    	try {
				//lista = XPathAPI.selectNodeList(document, "/n38/elementos/elemento/elemento[@subtipo=\"n38gruposorganicos\"]");
	    		lista = XPathAPI.selectNodeList(document, "//elemento[@subtipo=\"n38gruposorganicos\"]");
			} catch (TransformerException e) {
				// TODO Auto-generated catch block
				miLog.addTraza("iniro", "getDepartamentosXLNETs error1:", e.getMessage(), 1);
				throw new SecurityHelpperException("SecurityHelpperXLNets:getDepartamentosXLNETs");
			}
	
			m05bDepartamentoXLNET departamento;

			if (lista != null) {
			    int nNodos = lista.getLength();
			    if (nNodos > 0) {
			    	for (int i = 0; i < nNodos; i++) {
			    		if (lista.item(i).getChildNodes().getLength() > 0) {

			    			String v1 = XPathAPI.selectNodeList(lista.item(i), "parametro[@id=\"n38uidgrupoorganico\"]/valor/text()").item(0).getNodeValue();
			    			String v2 = XPathAPI.selectNodeList(lista.item(i), "parametro[@id=\"n38cadescripcion\"]/valor/text()").item(0).getNodeValue();
			    			String v3 = XPathAPI.selectNodeList(lista.item(i), "parametro[@id=\"n38eudescripcion\"]/valor/text()").item(0).getNodeValue();

			    			departamento = new m05bDepartamentoXLNET();
			    			departamento.setCodigo(v1);
			    			departamento.setDescC(v2);
			    			departamento.setDescE(v3);

			    			//miLog.addTraza("iniro", "getDepartamentosXLNETs v1", v1, 1);
			    			//miLog.addTraza("iniro", "getDepartamentosXLNETs v2", v2, 1);
			    			//miLog.addTraza("iniro", "getDepartamentosXLNETs v3", v3, 1);

			    			listaDepartamentos.add(departamento);
			    		}
			    	}
			    }
			}
    	}
    	catch (Exception e) {
    		miLog.addTraza("iniro", "getDepartamentosXLNETs error2:", e.getMessage(), 1);
    	}

	    return listaDepartamentos;
	}

    public ArrayList getDepartamentosYOrganismosXLNETs() throws SecurityHelpperException {

    	ArrayList listaDepartamentos = new ArrayList();
    	try
    	{
	    	N38Estructura estructura = new N38Estructura();
	    	estructura.setTipoEntrada("ALL");
	    	estructura.setUidEntrada("ALL");
	    	Document document = n38API.n38ItemOrganizacion(estructura); //"ALL", "ALL"

	    	NodeList lista;
	    	try {
	    		lista = XPathAPI.selectNodeList(document, "//elemento[@subtipo=\"n38organization\"]");
			} catch (TransformerException e) {
				// TODO Auto-generated catch block
				miLog.addTraza("iniro", "getDepartamentosYOrganismosXLNETs error1:", e.getMessage(), 1);
				throw new SecurityHelpperException("SecurityHelpperXLNets:getDepartamentosYOrganismosXLNETs");
			}

			m05bDepartamentoXLNET departamento;

			if (lista != null) {
			    int nNodos = lista.getLength();
			    if (nNodos > 0) {
			    	for (int i = 0; i < nNodos; i++) {
			    		if (lista.item(i).getChildNodes().getLength() > 0) {

			    			String v1 = XPathAPI.selectNodeList(lista.item(i), "parametro[@id=\"n38uidorg\"]/valor/text()").item(0).getNodeValue();
                            if (v1.equals("1")) //GV
                            {
                                //El grupo órganico del GV no lo tratamos porque para el cogemos todos sus departamentos
                                //con la función getDepartamentosXLNETs
                            	ArrayList departamentosGV = this.getDepartamentosXLNETs();
                            	listaDepartamentos.addAll(departamentosGV);
                            }
                            else
                            {
                                String v2 = XPathAPI.selectNodeList(lista.item(i), "parametro[@id=\"n38cadescripcion\"]/valor/text()").item(0).getNodeValue();
                                String v3 = XPathAPI.selectNodeList(lista.item(i), "parametro[@id=\"n38eudescripcion\"]/valor/text()").item(0).getNodeValue();
                                
    			    			departamento = new m05bDepartamentoXLNET();
    			    			departamento.setCodigo(v1);
    			    			departamento.setDescC(v2);
    			    			departamento.setDescE(v3);
    			    			
    			    			listaDepartamentos.add(departamento);
                            }
			    		}
			    	}
			    }
			}
    	}
    	catch (Exception e) {
    		miLog.addTraza("iniro", "getDepartamentosYOrganismosXLNETs error2:", e.getMessage(), 1);
    	}

	    return listaDepartamentos;
	}

    public ArrayList getPersonasXLNETs(String codigo,
    								   String dni,
    								   String nombre,
    								   String apellidos) throws SecurityHelpperException {

    	ArrayList listaPersonas = new ArrayList();
    	ArrayList listaDepartamentos;
    	try
    	{
    		String filtro = "";
    		if (codigo != null && !codigo.equals("")) {
				filtro = filtro + "uid=" + codigo;
    		}
    		if (dni != null && !dni.equals("")) {
				filtro = filtro + "dni=" + dni;
    		}
    		if (nombre != null && !nombre.equals("")) {
				filtro = filtro + "givenname=" + nombre;
    		}
    		if (apellidos != null && !apellidos.equals("")) {
				filtro = filtro + "sn=" + apellidos;
    		}

	    	Document document = n38API.n38ItemObtenerPersonas(filtro);
	    	Document documentDepto;

	    	NodeList lista;
	    	NodeList listaDepto;
	    	try {
	    		lista = XPathAPI.selectNodeList(document, "//elemento[@subtipo=\"n38persona\"]");
			} catch (TransformerException e) {
				// TODO Auto-generated catch block
				miLog.addTraza("iniro", "getPersonasXLNETs error al obtener persona con código=" + codigo, e.getMessage(), 1);
				throw new SecurityHelpperException("SecurityHelpperXLNets:getPersonasXLNETs");
			}

			m05bPersonaXLNET persona;

			if (lista != null) {
			    int nNodos = lista.getLength();
			    if (nNodos > 0) {
			    	for (int i = 0; i < nNodos; i++) {
			    		if (lista.item(i).getChildNodes().getLength() > 0) {
			    			String v1 = XPathAPI.selectNodeList(lista.item(i), "parametro[@id=\"uid\"]/valor/text()").item(0).getNodeValue();
	                        String v2 = XPathAPI.selectNodeList(lista.item(i), "parametro[@id=\"dni\"]/valor/text()").item(0).getNodeValue();
	                        String v3 = XPathAPI.selectNodeList(lista.item(i), "parametro[@id=\"givenname\"]/valor/text()").item(0).getNodeValue();
	                        String v4 = XPathAPI.selectNodeList(lista.item(i), "parametro[@id=\"sn\"]/valor/text()").item(0).getNodeValue();
	                        String v5 = XPathAPI.selectNodeList(lista.item(i), "parametro[@id=\"n38puestouid\"]/valor/text()").item(0).getNodeValue();
	                        String v6 = "";
			    			String v7 = "";
			    			String v8 = "";
			    			String v9 = "";
			    			NodeList nlm = XPathAPI.selectNodeList(lista.item(i), "parametro[@id=\"mail\"]/valor/text()");
			    			if (nlm.getLength() > 0) {
			    				v9 = nlm.item(0).getNodeValue();
			    			}

	                        persona = new m05bPersonaXLNET();
	                        persona.setCodigo(v1);
	                        persona.setDni(v2);
	                        persona.setNombre(v3);
	                        persona.setApellidos(v4);
	                        persona.setEMail(v9);

	                        /*CON EL PUESTO OBTENEMOS EL DEPARTAMENTO*/
	                        try {
	                            documentDepto = n38API.n38ItemObtenerPuestos("n38uidpuesto=" + v5);
		                        listaDepto = XPathAPI.selectNodeList(documentDepto, "//elemento[@subtipo=\"n38puesto\"]");

		                        v6 = XPathAPI.selectNodeList(listaDepto.item(0), "parametro[@id=\"n38grupoorganicouid\"]/valor/text()").item(0).getNodeValue();

		                        listaDepartamentos = this.getDepartamentosGrupoOrganicoXLNETs(v6);
		                        if (listaDepartamentos != null && listaDepartamentos.size() > 0) {
		                        	v6 = ((m05bDepartamentoXLNET)listaDepartamentos.get(0)).getCodigo();
		                        	v7 = ((m05bDepartamentoXLNET)listaDepartamentos.get(0)).getDescC();
					    			v8 = ((m05bDepartamentoXLNET)listaDepartamentos.get(0)).getDescE();
		                        }
	                        } catch (Exception e) {
	                        	miLog.addTraza("iniro", "getPersonasXLNETs exception e: " + e.getMessage(), v1, 1);
	                        }
	                        /**/

	                        persona.setCodDepto(v6);
	                        persona.setDescDeptoC(v7);
	                        persona.setDescDeptoE(v8);
	                        persona.setCargo("");

			    			//miLog.addTraza("iniro", "getPersonasXLNETs v1", v1, 1);
	                        //miLog.addTraza("iniro", "getPersonasXLNETs v2", v2, 1);
	                        //miLog.addTraza("iniro", "getPersonasXLNETs v3", v3, 1);
	                        //miLog.addTraza("iniro", "getPersonasXLNETs v4", v4, 1);
	                        //miLog.addTraza("iniro", "getPersonasXLNETs v5", v5, 1);
	                        //miLog.addTraza("iniro", "getPersonasXLNETs v6", v6, 1);
	                        //miLog.addTraza("iniro", "getPersonasXLNETs v7", v7, 1);
	                        //miLog.addTraza("iniro", "getPersonasXLNETs v8", v8, 1);

			    			listaPersonas.add(persona);
			    		}
			    	}
			    }
			}
    	}
    	catch (Exception e) {
    		miLog.addTraza("iniro", "getPersonasXLNETs error al obtener persona con código=" + codigo, e.getMessage(), 1);
    	}

	    return listaPersonas;
	}


    public String documentToString(Document document) {
    	Source source = new DOMSource(document);
		StringWriter stringWriter = new StringWriter();
		Result result = new StreamResult(stringWriter);
		try {
			Transformer transformer = TransformerFactory.newInstance().newTransformer();
			transformer.transform(source, result);
			return stringWriter.getBuffer().toString();
		} catch (TransformerException e) {
			m05bFileLog miLog = new m05bFileLog();
        	miLog.addTraza(e);	
			return null;
		}
	}

    /**
	 * Obtiene el token XLNets de aplicacion
	 * @param idAplic la ID de aplicacion
	 * @return el token de aplicacion
	 */
	public static String getTokenXLNets(String idAplic) {
		String token = null;

		try {
			N38APISesion miAPISesion = new N38APISesion();
			Document miSesion;
			miSesion=miAPISesion.n38APISesionCrearApp(idAplic);
			token = SecurityHelpperXLNets.DOM2String(miSesion);
		} catch (Exception e) {
	        m05bFileLog miLog = new m05bFileLog();
        	miLog.addTraza("", "P43XLNetsUtils->getTokenXLNets", "Excepcion creando el token de aplicacion", m05bConstantes.LOG_NIVEL_BAJO);
        	
        	miLog.addTraza(e);	
		}
		return token;
	}

	/**
	 * Convierte en String un documento org.w3c.dom.Document
	 * @param doc 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) {
			m05bFileLog miLog = new m05bFileLog();
	       	miLog.addTraza("", "m05bUtil", "m05bPlateaUtils.DOM2String - Error al crear la instancia de Transformer", m05bConstantes.LOG_NIVEL_BAJO);
		}

		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) {
			m05bFileLog miLog = new m05bFileLog();
	       	miLog.addTraza("", "m05bUtil", "m05bPlateaUtils.DOM2String - Error al transformar el Document", m05bConstantes.LOG_NIVEL_BAJO);
		}

		return writer.toString();
	}
}