/*
 * Fecha: 02-mar-04
 */
package es.ejie.frmk.listeners.base;

import java.util.Locale;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import es.ejie.frmk.Q70Factoria;
import es.ejie.frmk.control.arranque.Q70GestorArranqueConfiguracionServidor;
import es.ejie.frmk.control.excepciones.Q70FrameworkException;
import es.ejie.frmk.infraestructura.traza.Q70TraceLevel;
import es.ejie.frmk.infraestructura.traza.Q70TrazaInterface;
import es.ejie.frmk.infraestructura.utilidades.constantes.Q70UtilidadesConstantes;
import es.ejie.frmk.infraestructura.utilidades.excepciones.Q70GenerarUtilidadesExcepcion;
import es.ejie.frmk.presentacion.operacion.Q70OperacionDePresentacionException;
import es.ejie.frmk.presentacion.sesiondatos.Q70ContextoEJIE;
import es.ejie.frmk.presentacion.sesiondatos.Q70SesionDatos;

/**
 * Clase de utilidades para obtener funcionalidades dentro de Geremua y de las apliaciones.
 * Obtener propiedades de ficheros, gestionar el idioma del usuario conectado a una aplicacion,
 * desconectar usuario de las aplicaciones de Geremua.
 * 
 * @version 1.0
 * Fecha: 02-mar-04
 */
public class Q70ListenerUtils {

	/**
	 * Instancia del log de trazas
	 */
	private static Q70TrazaInterface tr = Q70Factoria.getTraza();
	
	//Valor de la constante de org.apache.struts -> Globals.LOCALE_KEY 
	private static String LOCALE_KEY = "org.apache.struts.action.LOCALE";
	
	/**
	 * Metodo para obtener el idioma de aplicacion por politica de grupo de aplicaciones o por idioma
	 * compartido entre WARs.
	 * 
	 * @param req Request en uso
	 * @param componente Nombre del componente que llama al metodo. Utilizado para tracear.
	 * @return Idioma actual del usuario
	 */
	public static String getGlobalLanguage(HttpServletRequest req, String componente) 
	{
		String globalLanguage = getAppGroupLanguage(req,null);
		
		if (globalLanguage==null){
			globalLanguage = getSharedLanguage(req,null);
		}

		return globalLanguage;
	}
	
	
	
	/**
	 * Metodo para obtener el idioma de aplicacion por politica de grupo de aplicaciones
	 * 
	 * @param req Request en uso
	 * @param componente Nombre del componente que llama al metodo. Utilizado para tracear.
	 * @return Idioma actual del usuario
	 */
	public static String getAppGroupLanguage(HttpServletRequest req, String componente) 
	{
		String globalLanguage = null;
			
		if (componente!=null && componente.trim().length()>0 && tr.isTraceActive())	
		{
			tr.trace(componente, Q70TraceLevel.DEBUG, "Comenzando a recuperar idioma global de aplicacion...");
		}
	
		//Recuperar el Nombre del atributo de Contexto de Grupo de Aplicaciones donde se deposita el idioma por defecto (si necesario) 
		String globalLanguageKey = (String) req.getSession().getServletContext().
									getInitParameter(es.ejie.frmk.presentacion.base.Q70Constantes.GLOBAL_LANGUAGE_KEY);	
		if (null!=globalLanguageKey) 
		{
			//Obtener del contexto el valor del idioma global(por politica de Grupo de Aplicaciones) usando la clave de idioma recuperada 
			Q70ContextoEJIE contextoEJIE = (Q70ContextoEJIE) req.getSession().
											getAttribute(es.ejie.frmk.presentacion.base.Q70Constantes.CONTEXT);
													
			Object tmpLanguage = contextoEJIE.get(globalLanguageKey); 
			if (null!=tmpLanguage && 0<tmpLanguage.toString().trim().length())
			{
				globalLanguage = tmpLanguage.toString();
	
				if (componente!=null && componente.trim().length()>0 && tr.isTraceActive())	
				{
					tr.trace(componente, Q70TraceLevel.DEBUG, "Recuperado idioma global de aplicacion, con valor '" +globalLanguage+ "'.");
				}
	
			}				 
		}
				
		return globalLanguage;
	}
	
	
	/**
	 * Metodo para obtener el idioma compartido entre WARs
	 * 
	 * @param req Request en uso
	 * @param componente Nombre del componente que llama al metodo. Utilizado para tracear.
	 * @return Idioma actual del usuario
	 */
	public static String getSharedLanguage(HttpServletRequest req, String componente)
	{
		String sharedLanguage = null;

		//Recuperar el Nombre del atributo de Contexto de Aplicacion donde se deposita el idioma compartido 
		String sharedLanguageKey = (String) req.getSession().getServletContext().
									getInitParameter(es.ejie.frmk.presentacion.base.Q70Constantes.SHARED_LANGUAGE_KEY);	

		if (null!=sharedLanguageKey) 
		{
			//Obtener del contexto el valor del idioma compartido (entre WARs) usando la clave de idioma recuperada 
			Q70ContextoEJIE contextoEJIE = (Q70ContextoEJIE) req.getSession().
												getAttribute(es.ejie.frmk.presentacion.base.Q70Constantes.CONTEXT);
			Object tmpLanguage = null;
			if(contextoEJIE != null)
				tmpLanguage = contextoEJIE.get(sharedLanguageKey); 
			if (null!=tmpLanguage && 0<tmpLanguage.toString().trim().length())
			{
				sharedLanguage = tmpLanguage.toString();

				if (componente!=null && componente.trim().length()>0 && tr.isTraceActive())	
				{
					tr.trace(componente, Q70TraceLevel.DEBUG, "Recuperado idioma compartido de aplicacion, con valor '" +sharedLanguage+ "'.");
				}	
			}	
		}			
		
		//Actualizar el objeto de idioma de la HttpSession
		if (req.getSession().getAttribute(LOCALE_KEY) == null
			|| !((Locale) req.getSession().getAttribute(LOCALE_KEY)).getLanguage().equals(sharedLanguage)) 
		{
			if (null != sharedLanguage && 0 < sharedLanguage.toString().trim().length()) {
				req.getSession().setAttribute(LOCALE_KEY, new Locale(sharedLanguage, sharedLanguage));
			}
		}
		
		return sharedLanguage;		
	}
	
	/**
	 * Metodo que actualiza el valor del idioma compartido entre WARs (si definido)
	 * y ademas el del HttpSession
	 * @param req Request en uso
	 * @param newLanguage Valor del nuevo lenguaje
	 */
	public static void updateLanguage(HttpServletRequest req, String newLanguage)
	{
		if (null == newLanguage) {
			if (tr.isTraceActive())
			{
				tr.trace("OPERACION_PRESENTACION", Q70TraceLevel.ERROR, "Se esta intentando cambiar el idioma de las aplicaciones con el valor null. Entonces, se esta manteniendo el idioma anterior.");
			}
			return;
		}
		//Recuperar el Nombre del atributo de Contexto de Aplicacion donde se deposita el idioma compartido 
		String sharedLanguageKey = (String) req.getSession().getServletContext().
									getInitParameter(es.ejie.frmk.presentacion.base.Q70Constantes.SHARED_LANGUAGE_KEY);

		if (null!=sharedLanguageKey) {
			Q70ContextoEJIE contextoEJIE = (Q70ContextoEJIE) req.getSession().
												getAttribute(es.ejie.frmk.presentacion.base.Q70Constantes.CONTEXT);
			
			contextoEJIE.set(sharedLanguageKey,newLanguage); 
		}
		
		//Actualizar el objeto de idioma de la HttpSession
		req.getSession().setAttribute(LOCALE_KEY,new Locale(newLanguage,newLanguage));
	}
	
	
	
	
	/**
	 * Metodo para obtener el idioma de la aplicacion.
	 * Primero intenta recuperar el idioma global de aplicacion. 
	 * Si no existe, intenta recuperar el idioma compartido por WARs.
	 * Y si tampoco existe, se recuperar el idioma del war de la HttpSession. 
	 * 
	 * @param req Request en uso
	 * @return Idioma actual del usuario
	 */
	public static String getLanguage(HttpServletRequest req) 
	{
		String globalLanguage = null;
		globalLanguage = getGlobalLanguage(req,null);		
		
		if (null == globalLanguage)
		{
			Locale locale = (Locale) req.getSession().getAttribute(LOCALE_KEY);
			if (locale == null) {
				locale = Locale.getDefault();
			}
			return locale.getLanguage();
		}
		else
		{
			return globalLanguage;
		}
	}
	/**
	 * Método que busca una clave en un fichero de properties de aplicacion
	 *
	 * @param key clave del fichero de properties de aplicacion a buscar
	 * @return valor asociado a la clave 
	 */
	public static String getApplicationProperty (String key)
	{
		return Q70GestorArranqueConfiguracionServidor.getApplicationProperty("",null,key);
	}
	/**
	 * Método que busca una clave en un fichero de properties de aplicacion
	 *
	 * @param componenteTraza Nombre del componente que genera la traza
	 * @param propertiesPath path del fichero de properties de aplicacion
	 * @param key clave del fichero de properties de aplicacion a buscar
	 * @return valor asociado a la clave 
	 */
	public static String getApplicationProperty (String componenteTraza, String propertiesPath, String key)
	{
		return Q70GestorArranqueConfiguracionServidor.getApplicationProperty(componenteTraza,propertiesPath,key);
	}
	/**
	 * Método que busca una clave en el fichero de properties de Geremua (q70.properties)
	 *
	 * param key clave del fichero de properties de aplicacion a buscar
	 * @return valor asociado a la clave 
	 */
	public static String getGlobalProperty (String key)
	{
		return Q70GestorArranqueConfiguracionServidor.getGlobalProperty(key);
	}
	
	/**
	 * Método que devuelve un fichero de properties de aplicacion, indicado por parametro. Dicho fichero se puede 
	 * cachear en memoria indicandolo por parametro. El Componente Gestor de Cache de Geremua se encarga de 
	 * dicho cacheo, almacenandose en la cache para ficheros de propiedades de la aplicacion.
	 *
	 * @param propertiesPath Path y Nombre del fichero de properties a partir del directorio de configuracion.
	 * @param cachearProperties Si true, se cachea el fichero de properties. Si false, NO se cachea. 
	 * @return Properties del fichero en cuestion. 
	 */
	public static Properties loadProperties (String propertiesPath, boolean cachearProperties)
	{
		if (cachearProperties){
			return Q70GestorArranqueConfiguracionServidor.loadProperties("",propertiesPath, Thread.currentThread().getContextClassLoader());
		}
		return Q70GestorArranqueConfiguracionServidor.loadPropertiesFromFile("",propertiesPath, Thread.currentThread().getContextClassLoader());
	}
	
	/**
	 * Método que quita el prefijo a la uri con máscara &&&PREFIJO_URL$$$
	 *
	 * @param maskedURI Uri con máscara
	 * @param session Sesion para recuperar el contexto de Servlet
	 * @return La uri sin máscara. 
	 * @throws Q70OperacionDePresentacionException
	 */
	public static String getRemoteURI(String maskedURI, HttpSession session) throws Q70OperacionDePresentacionException 
	{
		String prefijo = null;
		String uri = null;
		
		try {
			if (maskedURI.startsWith("$$$"))
			{
				prefijo = maskedURI.substring(3,maskedURI.lastIndexOf("$$$"));
			}
			if (null != prefijo)
			{
				uri = maskedURI.substring(maskedURI.lastIndexOf("$$$")+3);
				//prefijo = getApplicationProperty("OPERACION_PRESENTACION",session.getServletContext().getInitParameter(Q70Constantes.ARCHIVO_PROPIEDADES_KEY),prefijo);
				prefijo = getApplicationProperty("OPERACION_PRESENTACION",null,prefijo);
			}
			if ((null == prefijo) || (null == uri))
			{
				throw new Q70OperacionDePresentacionException (Q70ListenerUtils.class.toString(),"getRemoteURI","El prefijo o la uri tiene un valor nulo.",null);
			}
			else
			{
				if (tr.isTraceActive())
				{
					tr.trace("OPERACION_PRESENTACION", Q70TraceLevel.DEBUG, "URI sin máscara de entorno: "+prefijo+uri);
				}
			}
		} catch (Exception e) {
			if (tr.isTraceActive())
			{
				tr.trace("OPERACION_PRESENTACION", Q70TraceLevel.ERROR, "La URI de la operación remota en el atributo parameter del fichero XML de configuración de la operación de presentación está mal construida.\nURI: "+maskedURI+"\nEjemplo: $$$PREFIJO_URL_REMOTO$$$/aplicacion/operacion/index.do");
			}
			throw new Q70OperacionDePresentacionException (Q70ListenerUtils.class.toString(),"getRemoteURI","La URI de la operación remota en el atributo parameter del fichero XML de configuración de la operación de presentaciónestá mal construida.",e);
		}
		
		return prefijo+uri;
	}
	/**
	 * Método que busca monta la dirección de un recurso estatico sacado de el fichero de properties de la aplicacion
	 *
	 * param key1 clave para prefijo
	 * param key2 clave para alias
	 * @return valor asociado a la clave 
	 */
	public static String getApplicationResourceURI(String key1,String key2)
	{
		return getApplicationProperty(key1)+ getApplicationProperty(key2);
	}	
	/**
	 * Método que busca monta la dirección de un recurso estatico sacado de el fichero de properties de Geremua
	 *
	 * param key1 clave para prefijo
	 * param key2 clave para alias
	 * @return valor asociado a la clave 
	 */
	public static String getGlobalResourceURI(String key1,String key2)
	{
		return Q70GestorArranqueConfiguracionServidor.getGlobalProperty(key1)+ Q70GestorArranqueConfiguracionServidor.getGlobalProperty(key2);
	}



	/**
	 * Desconecta un usuario de todas las intancias de Geremua que esten conectadas a la misma cola JMS de mensajes.
	 * Es decir, elimina la informacion de la memoria del servidor de aplicaciones y actualiza la tabla de sesions de bbdd.
	 * 
	 * @param contexto Contiene el identificativo del Contexto de Sesion Usuario
	 * @throws Q70FrameworkException
	 */
	public static void desconectarUsuario(Q70ContextoEJIE contexto) throws Q70FrameworkException {
		String idUsuario = null;
		try {
			idUsuario = Q70SesionDatos.getSingleton().getContexto(contexto, Q70SesionDatos.CTX_SESION_USUARIO).getIdContexto();
		} catch (RuntimeException e) {
			throw Q70GenerarUtilidadesExcepcion.createUtilityException(Q70UtilidadesConstantes.UTILIDADES_GENERAL,
					  "Q70UtilidadesGenerales", "desconectarUsuario()", "Error al recuperar el identificativo de Usuario del Contexto",e);
		}
		try {
			Q70GestorArranqueConfiguracionServidor.invocarAccionJMX("doInvalidateUsuarioJMS",
					new Object[] { idUsuario }, new String[] { "java.lang.String" },
					Q70GestorArranqueConfiguracionServidor.CODIGO_APLICACION_FRAMEWORK);
		} catch (Q70FrameworkException e) {
			throw Q70GenerarUtilidadesExcepcion.createUtilityException(Q70UtilidadesConstantes.UTILIDADES_GENERAL,
					  "Q70UtilidadesGenerales", "desconectarUsuario()", "Error al desconectar al Usuario de la instancia",e);
		}
	}	
}
