package org.esupportail.portal.channels.CAnnuaire;
/** 
 * <p>Titre : Table</p>
 * <p>Description : table de valeurs</p>
 * <p>Copyright : Copyright (c) 2003</p>
 * <p>Société : esupPortail</p>
 * @author Sébatien GAUDIN
 * @version 1.0
 */

import java.util.*;
import javax.naming.*;
import javax.naming.directory.*;
import javax.naming.NamingEnumeration;

import org.jasig.portal.services.LogService;


public class userInterface {

	
	/**
	 * Represente l'objet de config (singleton)
	 */
	private config myConfig;
	
	/**
	 * Represente le serveur visible (si plusieurs, séparés par une virgule)
	 */
	private String serverView;
	
	/**
	 * Represente le serveur actif
	 */
	private String serverWork;
	
	/**
	 * Represente la liste des résultats
	 */
	private Vector result;
	
	/**
	 * Represente la liste des résultats
	 */
	private Vector eltDeFiltre = new Vector();
	
	private Hashtable criteres = new Hashtable();
	
	/**
	 * Represente le filtre de la requete
	 */
	//private String filtre;

	//
	public userInterface() {
	}

	//
	public userInterface(config C) {
		this.setConfig(C);
	}

	public void setConfig(config C) {
		myConfig = C;
	}

	/*******************************************************************************************/
	/****FORMULAIRE****/
	/*******************************************************************************************/

	/**
	 * 
	 * Transforme les caractères non affichable dans un fichier XML
	 * 
	 * @param entree : texte à formater en XML correcte
	 * @return une chaine xml formatée
	 */
	static String valueToXml(String entree) {
		String sortie = "";

		if (entree != null) {
			sortie = entree.replaceAll("&", "&amp;");
			sortie = sortie.replaceAll("\"", "'");
			sortie = sortie.replaceAll(">", "&gt;");
			sortie = sortie.replaceAll("<", "&lt;");
		}

		return sortie;
	}
	
	/*static String formateNewLine(String source) {  
	     StringBuffer result = new StringBuffer();  
	     char [] c = source.toCharArray();  
	  
	     for(int i=0;i<c.length;i++) {  
	          char tmp = c[i];  
	          switch(tmp) {  
	               case '$':result.append("<br/>");break;  
	               default:result.append(tmp);  
	          }  
	     }  
	     return result.toString();  
	}*/
	/**
	 * 
	 * Permet de créer le formulaire de recherche en se basant sur un annuaire
	 * 
	 * @param serveurKey : serveur sur lequel se basera la requete
	 * @return la chaine XML formant le formulaire
	 */
	public String getForm(boolean critRAZ) {
			
		/*INITIALISATION DES VALEURS*/
		String formXml = "";
		eltDeFiltre.clear();
		
		if ( critRAZ )criteres.clear();
		
		formXml = "<FORM>\n";
		if (serverWork == null)
			return (formXml + "</FORM>");

		Server monServeur = myConfig.getServer(serverWork);

		formXml += "<INTRO>" + monServeur.getIntro() + "</INTRO>";

		/*ECRITURE DU/DES SERVEUR(S) POTENTIEL(S)*/
		if ((serverView.equals("*")) || (serverView.equals(""))) {
			//récupération des serveurs lus en config
			Vector listeServer = myConfig.getAllServers();
			Iterator i = listeServer.iterator();
			while (i.hasNext()) {
				Server s = myConfig.getServer((String) i.next());
				formXml += addServerToForm(s);
			}
		} else {
				
			if (serverView.indexOf(",") == -1) {
				//s'il n'y a qu'un serveur
				//_serverView.matches(","); ne fonctionne pas	
				formXml += addServerToForm(myConfig.getServer(serverView));
			} else {
				//s'il y a plusieurs serveurs
				try {
					String[] tabView = serverView.split(",");
					for (int i = 0; i < tabView.length; i++) {
						formXml+= addServerToForm(myConfig.getServer(tabView[i]));
					}
				} catch (NullPointerException e) {
					LogService.log(
						LogService.ERROR,
						"userInterface::getForm():erreur dans la recherche des annuaires");
				}

			}
		}

		/*ECRITURE DES CHAMPS ACCESSIBLES POUR LA REQUETE*/
		if (monServeur != null) {
			Vector listeElt = monServeur.getQuery().getElements();
			if (listeElt != null) {
				Iterator j = listeElt.iterator();
				while (j.hasNext()) {
					String key = (String) j.next();
					ElmOfQuery e = monServeur.getQuery().getElement(key);
					formXml += addFieldToForm(e);
				}
			}
		} else {
			LogService.log(
				LogService.ERROR,
				"userInterface::getForm():" + serverWork + " non trouve");
			return "<ALERT>WARN_SERVER_NOT_FOUND</ALERT>\n";

		}

		formXml += "</FORM>\n";

		return (formXml);
	}

	/**
	 * @param s : le serveur (Server) que l'on doit ajouter à la liste des serveurs disponibles
	 * @return le code xml pour prendre en compte ce nouveau serveur
	 */
	private String addServerToForm(Server s) {
		String xml = "";
		if (s != null) {
			xml = "<SERVER ";
			xml += "name=\"" + s.getName() + "\" ";
			xml += "label=\"" + userInterface.valueToXml(s.getTitle()) + "\" ";
			xml += "/>\n";
		}
		return (xml);
	}

	/**
	 * @param e : élément (ElmOfQuery) de formulaire à ajouter.
	 * @return le code xml pour ajouter ce nouvel élément au formulaire
	 */
	private String addFieldToForm(ElmOfQuery e) {
		String xml = "";
		String[] critere = (String[])criteres.get(e.getNameHtml());
		String value="";
		if (critere!=null)value=critere[1];		
		if ((e.getType().equals("text"))
			|| (e.getType().equals("textTable"))) {
			xml = "<FIELD name=\"" + e.getNameHtml() + "\" ";
			xml += "label=\"" + userInterface.valueToXml(e.getLabel()) + "\" ";
			xml += "value=\"" + value + "\" ";
			xml += "saisie=\"1\" ";
			xml += "/>\n";
			eltDeFiltre.add(e);
		} else if (e.getType().equals("listTable")) {
			Table table = myConfig.getTable(e.getTable());
			if (table.getItems().size() > 0) {	
				xml = "<FIELD name=\"" + e.getNameHtml() + "\" ";
				xml += "label=\""
					+ userInterface.valueToXml(e.getLabel())
					+ "\" ";
				xml += "value=\"" + value + "\" ";
				xml += "saisie=\"1\" >\n";
				
				Enumeration enum = table.getItems().keys();
				while (enum.hasMoreElements()) {
					itemTable iT =
						(itemTable) table.getItems().get(
							(String) enum.nextElement());
					xml += "<FIELDVALUE code=\"" + iT.getCode() + "\" ";
					xml += "value=\""
						+ userInterface.valueToXml(iT.getValue())
						+ "\" ";
					xml += "order=\""
						+ userInterface.valueToXml(iT.getOrderValue())
						+ "\"";
					xml += "/>\n";
				}
				xml += "</FIELD>\n";

				eltDeFiltre.add(e);
			}
		} else if (e.getType().equals("direct")) {
			xml = "<FIELD name=\"" + e.getNameHtml() + "\" ";
			xml += "label=\"" + userInterface.valueToXml(e.getLabel()) + "\" ";
			xml += "value=\"" + e.getFilter() + "\" ";
			xml += "saisie=\"0\" ";
			xml += "/>\n";
			eltDeFiltre.add(e);
		}
		return (xml);
	}

	/*******************************************************************************************/
	/****EXECUTION REQUETE****/
	/*******************************************************************************************/

	/**
	 * @param value : filtre à costruire 
	 * @return true ou false selon que le filtre est bien mis à jour
	 *
	 */
	public boolean addIdToFilter(String value) {

		if ((value != null) && (value != "")) {
			String id = myConfig.getServer(serverWork).getQuery().getIdentifiant();
			String[] nouvCritere = new String[3];
			nouvCritere[0] = myConfig.getServer(serverWork).getQuery().getIdentifiantLabel();
			nouvCritere[1] = value;
			nouvCritere[2] = value;
			criteres.put("id", nouvCritere);
			return true;
		} else {
			criteres.remove("id");
			return false;
		}
	}

	/**
	 * 
	 * Met les paramètres reçus comme critère de recherche
	 * 
	 * @param listeParametres : parametres recus du formulaire
	 */

	public boolean updateFilter(Map listeParametres) {
		criteres.remove("id");
		boolean champTextMisAJour = false;	
		for (java.util.Iterator j = eltDeFiltre.iterator(); j.hasNext();) {
			ElmOfQuery e = (ElmOfQuery) j.next();
			String value = (String) listeParametres.get(e.getNameHtml());
				
			if (value.length() < e.getMinChar()) value = "";	
			
			if (e.getDelStarBool()) value = value.replaceAll("\\*", "");
				
			if ( (value!=null) && (!value.equals("")) ) {
				/*Un critère est composé de 3 parties : 
				 * critere[0] : le label à afficher 
				 * critere[1] : la valeur à tester 
				 * critere[2] : la valeur à afficher 
				 * */
				String[] nouvCritere = new String[3];
				nouvCritere[0] = e.getLabel();
				nouvCritere[1] = value;
				if (e.getType().equals("text")) {
					champTextMisAJour = true;
					nouvCritere[2] = value;
				} else if (e.getType().equals("listTable")) {
					champTextMisAJour = true;
					Table T = myConfig.getTable(e.getTable());
					nouvCritere[2] = ((itemTable)T.getItem(value)).getValue();
					criteres.put(e.getNameHtml(), nouvCritere);
				} else if (e.getType().equals("textTable")) {
					champTextMisAJour = true;
					Table T = myConfig.getTable(e.getTable());

					/*Met les attributs LDAP à récupérer dans un tableau de chaines*/
					String[] attrIDs = new String[1];
					attrIDs[0] = T.getAttrCode();
					LDAPHandler LDAP = new LDAPHandler();
					LDAP.setUrl(myConfig.getServer(serverWork).getUrl());
					LDAP.setAttributes(attrIDs);
					LDAP.setMaxEntries(e.getMaxEntries());
					LDAP.setBase(T.getBase());
					String filtreTmp =
						"(&"
							+ T.getFilter()
							+ "("
							+ T.getAttrValue()
							+ "="
							+ e.getSearchValue().replaceAll("%s", value)
							+ "))";
					LDAP.setFilter(filtreTmp);

					LDAP.setScope(T.getScopeNum());
					NamingEnumeration answer = LDAP.search();
					if (answer != null) {
						nouvCritere[2] = " contient '"+value+"'";
						criteres.put(e.getNameHtml(), nouvCritere);
						try {
							while (answer.hasMore()) {

								SearchResult sr;
								try {
									sr = (SearchResult) answer.next();
									
									String[] Critere = new String[3];
									Critere[0] = "";
									Critere[1] = e.getFilter().replaceAll(
									"%c",
									(String) sr.getAttributes().get(attrIDs[0]).get(0));	
									Critere[2] = Critere[1];
									criteres.put(e.getNameHtml(), Critere);	

								} catch (NamingException f) {
									LogService.log(
										LogService.ERROR,
										"Table::loadItems() : Parcours les réponses NullPointerException : "
											+ e.toString());
									break;
								}
							}
						} catch (NullPointerException f) {
							LogService.log(
								LogService.ERROR,
								"Table::loadItems() : aucune réponse : "
									+ e.toString());
						} catch (NamingException f) {
							LogService.log(
								LogService.ERROR,
								"Table::loadItems() : search : "
									+ e.toString());
						}
						finally{
							LDAP.close();
						}
					}
				}
				criteres.put(e.getNameHtml(), nouvCritere);
				
			}
			else{
				criteres.remove(e.getNameHtml());
			}
		}	
		
		if ((!champTextMisAJour)) {
			return false;
		} else {
			return true;
		}
	}
	/**
	 * 
	 * Execute la requete
	 * 
	 * @return L'ensemble des personnes réusltat sous forme de Vector
	 */
	public boolean executeQuery() {
		result = new Vector();
		if (getFiltreComplet() != "") {
			/*Prépare le tableau des attributs LDAP à récuperer*/
			String[] attrIDs =new String[myConfig.getServer(serverWork).getDisplay().getLines().size()+ 2];
			attrIDs[0] = myConfig.getServer(serverWork).getDisplay().getTri();
			attrIDs[1] = myConfig.getServer(serverWork).getQuery().getIdentifiant();
			int i = 2;
			for (java.util.Iterator j =myConfig.getServer(serverWork).getDisplay().getOrdre().iterator();j.hasNext();) {
				String nomAttr = (String) j.next();
				attrIDs[i] =((Line) myConfig.getServer(serverWork).getDisplay().getLines().get(nomAttr)).getAttribute();
				i++;
			}
			
			/*Créé et value l'objet LDAP*/
			LDAPHandler LDAP = new LDAPHandler();
			LDAP.setUrl(myConfig.getServer(serverWork).getUrl());
			LDAP.setAttributes(attrIDs);
			LDAP.setMaxEntries(myConfig.getServer(serverWork).getQuery().getMaxEntries());
			LDAP.setBase(myConfig.getServer(serverWork).getQuery().getBase());
			LDAP.setFilter(getFiltreComplet());
			LDAP.setScope(myConfig.getServer(serverWork).getQuery().getScope());
			
			/*Lance la recherche*/
			NamingEnumeration answer = LDAP.search();

			int nbRep = 0;
			if (answer != null) {

				try {
					/*Parcours les réponses*/
					while (answer.hasMore()) {
						Personne p = new Personne();
						SearchResult sr;
						try {
							sr = (SearchResult) answer.next();
							nbRep++;
						} catch (NamingException e) {
							LogService.log(
								LogService.ERROR,
								"userInterface:executeQuery() : "
									+ e.toString());
							return (false);
						}

						/*Ajoute l'attribut de tri pour la personne*/
						Attribute attrib = sr.getAttributes().get(attrIDs[0]);
						try {
							p.addTri((String) attrib.get());
						} catch (NullPointerException f) {
							LogService.log(
								LogService.ERROR,
								"userInterface:executeQuery() : L'attribut de tri est nul");
							return (false);
						} catch (NamingException f) {
							LogService.log(
								LogService.ERROR,
								"userInterface:executeQuery() : Impossible d'ajouter l'attribut de tri dans la réponse");
							return (false);
						}

						/*Ajoute l'attribut identifiant pour la personne*/
						attrib = sr.getAttributes().get(attrIDs[1]);
						try {
							p.setIdentifiant((String) attrib.get());
						} catch (NamingException f) {
							LogService.log(
								LogService.ERROR,
								"userInterface:executeQuery() : Impossible d'ajouter l'attribut identifiant dans la réponse");
							return (false);
						}

						/*Parcours les autres attributs de la réponse et les ajoute pour la perosnne*/
						for (i = 2; i < attrIDs.length; i++) {
							attrib = sr.getAttributes().get(attrIDs[i]);
							Line e = new Line();
							e.setAttribute(attrIDs[i]);
							e.setLabel(((Line) myConfig.getServer(serverWork).getDisplay().getLines().get(attrIDs[i])).getLabel());
							e.setList(((Line) myConfig.getServer(serverWork).getDisplay().getLines().get(attrIDs[i])).getList());
							e.setTabToCard(((Line) myConfig.getServer(serverWork).getDisplay().getLines().get(attrIDs[i])).getTabToCard());
							String type =((Line) myConfig.getServer(serverWork).getDisplay().getLines().get(attrIDs[i])).getType();

							if (type.equals("direct")) {
								/*Récupération directe dans LDAP de la (des) valeur(s) de cet attribut*/
								try {
									if (attrib != null) {
										e.setValues(attrib.getAll());
									} else {
										e.setValues(null);
									}
								} catch (NamingException f) {
									LogService.log(
										LogService.ERROR,
										"userInterface:executeQuery() : "
											+ f.toString());
									return (false);
								}
							} else if (type.equals("table")) {
								try {
									/*Récupération dans la table liée de la valeur de cet attribut*/
									if (attrib != null) {
										Line L =(Line) myConfig.getServer(serverWork).getDisplay().getLines().get(attrIDs[i]);
										String nomAttrib = L.getAttribute();
										String nomTable = L.getLinktable();
										Table T = myConfig.getTable(nomTable);
										String value =T.getItem(attrib.get(0).toString()).getValue();
										if (value != null) {
											attrib.clear();
											attrib.add(value);
										}
										e.setValues(attrib.getAll());
									} else {
										e.setValues(null);
									}
								} catch (NamingException f) {
									LogService.log(
										LogService.ERROR,
										"userInterface:executeQuery() : "
											+ f.toString());
									return (false);
								}
							}
							p.addAttributes(e);
						}
						result.add(p);
					}
				} catch (javax.naming.SizeLimitExceededException h) {
					LogService.log(
						LogService.INFO,
						"userInterface:executeQuery() : Nombre maximum de réponses atteind");
					//Il ne faut pas de return car une fois cette exception déclenchée, c'est que le nombre maximum de réponses a été atteind
				} catch (NamingException e) {
					LogService.log(
						LogService.ERROR,
						"userInterface:executeQuery() : " + e.toString());
					return (false);
				} finally {
					LDAP.close();
				}
			}

			LogService.log(
				LogService.INFO,
				"userInterface::executeQuery() : nb de réponses trouvée : "
					+ nbRep);

			return (true);
		} else {
			LogService.log(
				LogService.INFO,
				"userInterface:executeQuery() : Filtre vide : ");
			return (false);
		}
	}

	/*******************************************************************************************/
	/****AFFICHAGE RESULTAT****/
	/*******************************************************************************************/

	/**
	 * @return le code xml complet pour afficher le résultat
	 */
	public String getResultXml() {
		String xml = "<tagEnglobant ";
		xml += "link=\""
			+ myConfig.getServer(serverWork).getDisplay().getLink()
			+ "\"";
		xml += ">\n";

		xml += this.getCriteresXml();

		xml += this.getEnteteXml();

		xml += this.getReponseXml();

		xml += "</tagEnglobant>\n";

		if (this.getNbReponse()
			== myConfig.getServer(serverWork).getQuery().getMaxEntries()) {
			xml += "<ALERT>WARN_MAX_ENTRIES</ALERT>\n";
		}

		return xml;
	}

	/**
	 * @return le code xml des critères sélectionnés
	 */
	public String getCriteresXml() {
		String xml = "";
		for (java.util.Iterator j = criteres.keySet().iterator();
			j.hasNext();
			) {
			String cle = (String) j.next();
			String[] s = (String[]) criteres.get(cle);
			if (s[0]!=null){
				xml += "<critere ";
				xml += "label=\"" + s[0] + "\" value=\"" + s[2] + "\" ";
				xml += "/>\n";
			}
		}
		return xml;
	}

	/**
	 * @return le code xml des entetes de colonnes
	 */
	public String getEnteteXml() {
		String xml = "";
		/*Répertorie les attributs*/

		for (java.util.Iterator j =
			myConfig.getServer(serverWork).getDisplay().getOrdre().iterator();
			j.hasNext();
			) {
			String nomAttr = (String) j.next();
			Line e =
				(Line) myConfig
					.getServer(serverWork)
					.getDisplay()
					.getLines()
					.get(
					nomAttr);
			xml += "<attributEntete ";
			xml += "display=\""
				+ userInterface.valueToXml(e.getLabel())
				+ "\" ";
			if (e.getList())
				xml += "list=\"1\" ";
			else
				xml += "list=\"0\" ";
			xml += "/>\n";
		}

		return xml;
	}

	/**
	 * @return le code xml des réponses
	 */
	public String getReponseXml() {

		boolean hasResult = this.executeQuery();

		String xml = "";

		if (hasResult) {
			/*répertorie les résultats*/
			for (java.util.Iterator j = result.iterator(); j.hasNext();) {
				Personne e = (Personne) j.next();
				xml += e.toXml(myConfig.getServer(serverWork).getDisplay().getOrdre());
			}
		}
		xml += "<NBREPONSES>" + this.getNbReponse() + "</NBREPONSES>\n";

		return xml;
	}
	/**
	 * @return le nombre de résultat trouvés
	 */
	public int getNbReponse() {
		if (result != null)
			return result.size();
		else
			return (0);
	}

	/*******************************************************************************************/
	/****GETTER ET SETTER****/
	/*******************************************************************************************/

	/**
	 * @return Returns le filtre complètement généré
	 */
	public String getFiltreComplet() {
	    String filtre = "";
		filtre = "(&";
		
		Iterator i = criteres.keySet().iterator();
		while (i.hasNext()){
			String key = (String)i.next();
			String[] critere = (String[])criteres.get(key);
			String value = critere[1];
		
			if (key.equals("id")){
				filtre +="("+myConfig.getServer(serverWork).getQuery().getIdentifiant()+"="+value+")";
			}
			else{			
				ElmOfQuery e = (ElmOfQuery)myConfig.getServer(serverWork).getQuery().getElement(key); 	
				filtre += e.updateFilter(value,myConfig.getTable(e.getTable()),myConfig.getServer(serverWork).getUrl());				
			} 
		}
	
		filtre += ")";		
	
		return filtre;
	}

	/**
	 * @return Returns the _serverView.
	 */
	public Vector getEltDeFiltre() {
		return eltDeFiltre;
	}

	/**
	 * @return Returns the _serverView.
	 */
	public String getServerView() {
		return serverView;
	}

	/**
	 * @param view The _serverView to set.
	 */
	public void setServerView(String view) {
		serverView = view;

		boolean setOk = false;
		String work = "";

		/*ECRITURE DU/DES SERVEUR(S) POTENTIEL(S)*/
		if ((serverView.equals("*")) || (serverView.equals(""))) {
			//récupération des serveurs lus en config
			setOk = this.setServerWork(myConfig.getDefaultServeurKey());
			work = myConfig.getDefaultServeurKey();

		} else {
			//_serverView.matches(","); ne fonctionne pas
			if (serverView.indexOf(',') == -1) {
				setOk = this.setServerWork(serverView);
				work = serverView;
			} else {
				String[] tabView = serverView.split(",");
				setOk = this.setServerWork(tabView[0]);
				work = tabView[0];
			}
		}

		if (!setOk)
			LogService.log(
				LogService.ERROR,
				"userInterface::setServerView():Un serveur passé en paramètre d'instanciation n'est pas correct : "
					+ work);

	}

	/**
	 * @return Returns the _serverWork.
	 */
	public String getServerWork() {
		return serverWork;
	}

	/**
	 * Définit le "serveur de travail" c'est-à-dire le serveur actif 
	 * 
	 * @param le nom d'un serveur (présent en config)
	 * @return true si le serveur a été trouvé, false sinon
	 */
	public boolean setServerWork(String value) {

		if (myConfig.getServer(value) != null) {
			serverWork = value;
			return true;
		} else {
			serverWork = null;
			LogService.log(
				LogService.ERROR,
				"userInterface::setServerWork():serveur "
					+ value
					+ " introuvable en config.");
			return false;
		}
	}

	/**
	 * Retourne la liste des résultats
	 * 
	 * @return la liste des résultats
	 */
	public Vector getResult() {
		return result;
	}

}
