package es.ejie.frmk.presentacion.iu.taglib.base;

import java.util.Enumeration;
import java.util.List;
import java.util.Locale;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;

import org.displaytag.exception.TablePropertiesLoadException;
import org.displaytag.export.MediaTypeEnum;
import org.displaytag.properties.DisplayPropertiesLoaderServlet;

import es.ejie.frmk.infraestructura.internacionalizacion.Q70GestorMensajesException;
import es.ejie.frmk.infraestructura.internacionalizacion.Q70GestorMensajesi18n;
import es.ejie.frmk.infraestructura.traza.Q70TraceLevel;
import es.ejie.frmk.infraestructura.traza.Q70Traza;
import es.ejie.frmk.listeners.base.Q70ListenerUtils;

/**
 * The properties used by the Table tags. The properties are loaded in the following order, in increasing order of
 * priority.
 * <ol>
 * <li>First, from the Q70TableTag.properties included with the DisplayTag distribution.</li>
 * <li>Then, from the file displaytag.properties, if it is present; these properties are intended to be set by the
 * user for sitewide application.</li>
 * <li>Finally, if this class has a userProperties defined, all of the properties from that Properties object are
 * copied in as well. The userProperties Properties can be set by the {@link DisplayPropertiesLoaderServlet}if it is
 * configured.</li>
 * </ol>
 * @author fgiust
 * @author rapruitt
 * @version 1.0
 * @see DisplayPropertiesLoaderServlet
 */
public class Q70TableProperties
{
	/**
	 * Constante que indica el componente al que pertenece dicha clase. Es
	 * necesario para el uso del log de trazas.
	 */
	private static final String COMPONENTE = Q70Constants.COMPONENTE_CUSTOM_TAG;
	
	/**
	 * Instancia del log de trazas
	 */
	private static Q70Traza tr = Q70Traza.getSingleton();

	/**
	  * Lista de ambitos manejados por esta clase y que serán los de la tabla que crea este objeto.
	  */
	protected List listaI18nKey = null;

	/**
	  * Lenguaje con que es creado este objeto.
	  */
	private String languageTableProperties;

	/**
	  * Loaded properties
	  */
	private Properties properties = null;

	 /**
	  * prefix used for all the properties related to export ("export")
	  */
	private static final String PROPERTY_BOOLEAN_EXPORT_PREFIX = "export";
	 /**
	  * Field PROPERTY_STRING_EXPORT_LABEL
	  */
	private static final String PROPERTY_STRING_EXPORT_LABEL = "label";
	 /**
	  * Field PROPERTY_BOOLEAN_EXPORT_HEADER
	  */
	private static final String PROPERTY_BOOLEAN_EXPORT_HEADER = "include_header";
	 /**
	  * Field PROPERTY_STRING_EXPORTBANNER
	  */
	private static final String PROPERTY_STRING_EXPORTBANNER = "export.banner";
	 /**
	  * Field PROPERTY_STRING_EXPORTBANNER_SEPARATOR
	  */
	private static final String PROPERTY_STRING_EXPORTBANNER_SEPARATOR = "export.banner.sepchar";
	 /**
	  * Field PROPERTY_BOOLEAN_EXPORTDECORATED
	  */
	private static final String PROPERTY_BOOLEAN_EXPORTDECORATED = "export.decorated";
	 /**
	  * Field PROPERTY_STRING_EXPORTAMOUNT
	  */
	private static final String PROPERTY_STRING_EXPORTAMOUNT = "export.amount";  
	 /**
	  * Field PROPERTY_STRING_EXPORT_FILENAME
	  */
	private static final String PROPERTY_STRING_EXPORT_FILENAME = "export.filename";
	 /**
	  * Field PROPERTY_BOOLEAN_SHOWHEADER
	  */
	private static final String PROPERTY_BOOLEAN_SHOWHEADER = "basic.show.header";
	 /**
	  * Field PROPERTY_STRING_EMPTYLIST_MESSAGE
	  */
	private static final String PROPERTY_STRING_EMPTYLIST_MESSAGE = "basic.msg.empty_list";
	 /**
	  * Field PROPERTY_STRING_BANNER_PLACEMENT
	  */
	private static final String PROPERTY_STRING_BANNER_PLACEMENT = "paging.banner.placement";
	 /**
	  * Field PROPERTY_STRING_PAGING_INVALIDPAGE
	  */
	private static final String PROPERTY_STRING_PAGING_INVALIDPAGE = "error.msg.invalid_page";
	 /**
	  * Field PROPERTY_STRING_PAGING_ITEM_NAME
	  */
	private static final String PROPERTY_STRING_PAGING_ITEM_NAME = "paging.banner.item_name";
	 /**
	  * Field PROPERTY_STRING_PAGING_ITEMS_NAME
	  */
	private static final String PROPERTY_STRING_PAGING_ITEMS_NAME = "paging.banner.items_name";
	 /**
	  * Field PROPERTY_STRING_PAGING_NOITEMS
	  */
	private static final String PROPERTY_STRING_PAGING_NOITEMS = "paging.banner.no_items_found";
	 /**
	  * Field PROPERTY_STRING_PAGING_FOUND_ONEITEM
	  */
	private static final String PROPERTY_STRING_PAGING_FOUND_ONEITEM = "paging.banner.one_item_found";
	 /**
	  * Field PROPERTY_STRING_PAGING_FOUND_ALLITEMS
	  */
	private static final String PROPERTY_STRING_PAGING_FOUND_ALLITEMS = "paging.banner.all_items_found";
	 /**
	  * Field PROPERTY_STRING_PAGING_FOUND_SOMEITEMS
	  */
	private static final String PROPERTY_STRING_PAGING_FOUND_SOMEITEMS = "paging.banner.some_items_found";
	 /**
	  * Field PROPERTY_INT_PAGING_GROUPSIZE
	  */
	private static final String PROPERTY_INT_PAGING_GROUPSIZE = "paging.banner.group_size";
	 /**
	  * Field PROPERTY_STRING_PAGING_BANNER_ONEPAGE
	  */
	private static final String PROPERTY_STRING_PAGING_BANNER_ONEPAGE = "paging.banner.onepage";
	 /**
	  * Field PROPERTY_STRING_PAGING_BANNER_FIRST
	  */
	private static final String PROPERTY_STRING_PAGING_BANNER_FIRST = "paging.banner.first";
 	 /**
	  * Field PROPERTY_STRING_PAGING_BANNER_LAST
	  */
	private static final String PROPERTY_STRING_PAGING_BANNER_LAST = "paging.banner.last";
	 /**
	  * Field PROPERTY_STRING_PAGING_BANNER_FULL
	  */
	private static final String PROPERTY_STRING_PAGING_BANNER_FULL = "paging.banner.full";
 	 /**
	  * Field PROPERTY_STRING_PAGING_PAGE_LINK
	  */
	private static final String PROPERTY_STRING_PAGING_PAGE_LINK = "paging.banner.page.link";
	 /**
	  * Field PROPERTY_STRING_PAGING_PAGE_SELECTED
	  */
	private static final String PROPERTY_STRING_PAGING_PAGE_SELECTED = "paging.banner.page.selected";
 	 /**
	  * Field PROPERTY_STRING_PAGING_PAGE_SPARATOR
	  */
	private static final String PROPERTY_STRING_PAGING_PAGE_SPARATOR = "paging.banner.page.separator";
	 /**
	  * unused property
	  * @todo add the ability to set the exported file name
	  */
	private static final String PROPERTY_STRING_SAVE_EXCEL_FILENAME = "save.excel.filename";
	 /**
	  * unused property
	  * @todo check references and remove
	  */
	private static final String PROPERTY_STRING_SAVE_EXCEL_BANNER = "save.excel.banner";
	
	
    /**
     * The userProperties are local, non-default properties; these settings override the defaults from
     * displaytag.properties and Q70TableTag.properties.
     */
    private static Properties userProperties = new Properties();


	//-----------------------------------------------------------------------------


    /**
     * Local, non-default properties; these settings override the defaults from displaytag.properties and
     * Q70TableTag.properties.
     * @return the Properties that was set
     */
    public static Properties getUserProperties()
    {
        return userProperties;
    }

    /**
     * Local, non-default properties; these settings override the defaults from displaytag.properties and
     * Q70TableTag.properties. Please note that the values are copied in, so that multiple calls with non-overlapping
     * properties will be merged, not overwritten.
     * @param overrideProperties - The local, non-default properties
     */
    public static void setUserProperties(Properties overrideProperties)
    {
        Enumeration enumAux = overrideProperties.keys();
        while (enumAux.hasMoreElements())
        {
            String key = (String) enumAux.nextElement();
            if (key != null && overrideProperties.get(key) != null)
            {
                userProperties.setProperty(key, (String) overrideProperties.get(key));
            }
        }
    }

 
    /**
     * Method getPagingInvalidPage
     * @return String
     * @throws Q70CustomTagException 
     */
    public String getPagingInvalidPage() throws Q70CustomTagException
    {
        return getProperty(PROPERTY_STRING_PAGING_INVALIDPAGE);
    }

    /**
     * Method getPagingItemName
     * @return String
     * @throws Q70CustomTagException 
     */
    public String getPagingItemName() throws Q70CustomTagException
    {
        return getProperty(PROPERTY_STRING_PAGING_ITEM_NAME);
    }

    /**
     * Method getPagingItemsName
     * @return String
     * @throws Q70CustomTagException 
     */
    public String getPagingItemsName() throws Q70CustomTagException
    {
        return getProperty(PROPERTY_STRING_PAGING_ITEMS_NAME);
    }

    /**
     * Method getPagingFoundNoItems
     * @return String
     * @throws Q70CustomTagException 
     */
    public String getPagingFoundNoItems() throws Q70CustomTagException
    {
        return getProperty(PROPERTY_STRING_PAGING_NOITEMS);
    }

    /**
     * Method getPagingFoundOneItem
     * @return String
     * @throws Q70CustomTagException 
     */
    public String getPagingFoundOneItem() throws Q70CustomTagException
    {
        return getProperty(PROPERTY_STRING_PAGING_FOUND_ONEITEM);
    }

    /**
     * Method getPagingFoundAllItems
     * @return String
     * @throws Q70CustomTagException 
     */
    public String getPagingFoundAllItems() throws Q70CustomTagException
    {
        return getProperty(PROPERTY_STRING_PAGING_FOUND_ALLITEMS);
    }

    /**
     * Method getPagingFoundSomeItems
     * @return String
     * @throws Q70CustomTagException 
     */
    public String getPagingFoundSomeItems() throws Q70CustomTagException
    {
        return getProperty(PROPERTY_STRING_PAGING_FOUND_SOMEITEMS);
    }

    /**
     * Method getPagingGroupSize
     * @param defaultValue int
     * @return int
     * @throws Q70CustomTagException 
     */
    public int getPagingGroupSize(int defaultValue) throws Q70CustomTagException
    {
        return getIntProperty(PROPERTY_INT_PAGING_GROUPSIZE, defaultValue);
    }

    /**
     * Method getPagingBannerOnePage
     * @return String
     * @throws Q70CustomTagException 
     */
    public String getPagingBannerOnePage() throws Q70CustomTagException
    {
        return getProperty(PROPERTY_STRING_PAGING_BANNER_ONEPAGE);
    }

    /**
     * Method getPagingBannerFirst
     * @return String
     * @throws Q70CustomTagException 
     */
    public String getPagingBannerFirst() throws Q70CustomTagException
    {
        return getProperty(PROPERTY_STRING_PAGING_BANNER_FIRST);
    }

    /**
     * Method getPagingBannerLast
     * @return String
     * @throws Q70CustomTagException 
     */
    public String getPagingBannerLast() throws Q70CustomTagException
    {
        return getProperty(PROPERTY_STRING_PAGING_BANNER_LAST);
    }

    /**
     * Method getPagingBannerFull
     * @return String
     * @throws Q70CustomTagException 
     */
    public String getPagingBannerFull() throws Q70CustomTagException
    {
        return getProperty(PROPERTY_STRING_PAGING_BANNER_FULL);
    }

    /**
     * Method getPagingPageLink
     * @return String
     * @throws Q70CustomTagException 
     */
    public String getPagingPageLink() throws Q70CustomTagException
    {
        return getProperty(PROPERTY_STRING_PAGING_PAGE_LINK);
    }

    /**
     * Method getPagingPageSelected
     * @return String
     * @throws Q70CustomTagException 
     */
    public String getPagingPageSelected() throws Q70CustomTagException
    {
        return getProperty(PROPERTY_STRING_PAGING_PAGE_SELECTED);
    }

    /**
     * Method getPagingPageSeparator
     * @return String
     * @throws Q70CustomTagException 
     */
    public String getPagingPageSeparator() throws Q70CustomTagException
    {
        return getProperty(PROPERTY_STRING_PAGING_PAGE_SPARATOR);
    }

    /**
     * Is the given export option enabled?
     * @param exportType instance of MediaTypeEnum
     * @return boolean true if export is enabled
     * @throws Q70CustomTagException 
     */
    public boolean getAddExport(MediaTypeEnum exportType) throws Q70CustomTagException
    {
        return getBooleanProperty(PROPERTY_BOOLEAN_EXPORT_PREFIX + "." + exportType.getName());
    }

    /**
     * Should headers be included in given export type?
     * @param exportType instance of MediaTypeEnum
     * @return boolean true if export should include headers
     * @throws Q70CustomTagException 
     */
    public boolean getExportHeader(MediaTypeEnum exportType) throws Q70CustomTagException
    {
        return getBooleanProperty(
            PROPERTY_BOOLEAN_EXPORT_PREFIX + "." + exportType + "." + PROPERTY_BOOLEAN_EXPORT_HEADER);
    }

    /**
     * Returns the label for the given export option
     * @param exportType instance of MediaTypeEnum
     * @return String label
     * @throws Q70CustomTagException 
     */
    public String getExportLabel(MediaTypeEnum exportType) throws Q70CustomTagException
    {
        return getProperty(PROPERTY_BOOLEAN_EXPORT_PREFIX + "." + exportType + "." + PROPERTY_STRING_EXPORT_LABEL);
    }

    /**
     * Method getExportDecorated
     * @return boolean
     * @throws Q70CustomTagException 
     */
    public boolean getExportDecorated() throws Q70CustomTagException
    {
        return getBooleanProperty(PROPERTY_BOOLEAN_EXPORTDECORATED);
    }

    /**
     * Method getExportFileName
     * @return String
     * @throws Q70CustomTagException 
     */
    public String getExportFileName() throws Q70CustomTagException
    {
        return getProperty(PROPERTY_STRING_EXPORT_FILENAME);
    }

    /**
     * Method getExportBanner
     * @return String
     * @throws Q70CustomTagException 
     */
    public String getExportBanner() throws Q70CustomTagException
    {
        return getProperty(PROPERTY_STRING_EXPORTBANNER);
    }

    /**
     * Method getExportBannerSeparator
     * @return String
     * @throws Q70CustomTagException 
     */
    public String getExportBannerSeparator() throws Q70CustomTagException
    {
        return getProperty(PROPERTY_STRING_EXPORTBANNER_SEPARATOR);
    }

    /**
     * Method getShowHeader
     * @return boolean
     * @throws Q70CustomTagException 
     */
    public boolean getShowHeader() throws Q70CustomTagException
    {
        return getBooleanProperty(PROPERTY_BOOLEAN_SHOWHEADER);
    }

    /**
     * Method getEmptyListMessage
     * @return String
     * @throws Q70CustomTagException 
     */
    public String getEmptyListMessage() throws Q70CustomTagException
    {
        return getProperty(PROPERTY_STRING_EMPTYLIST_MESSAGE);
    }

    /**
     * Method getExportFullList
     * @return boolean
     * @throws Q70CustomTagException 
     */
    public boolean getExportFullList() throws Q70CustomTagException
    {
        return "list".equals(getProperty(PROPERTY_STRING_EXPORTAMOUNT));
    }

    /**
     * Method getAddPagingBannerTop
     * @return boolean
     * @throws Q70CustomTagException 
     */
    public boolean getAddPagingBannerTop() throws Q70CustomTagException
    {
        String placement = getProperty(PROPERTY_STRING_BANNER_PLACEMENT);
        return "top".equals(placement) || "both".equals(placement);
    }

    /**
     * Method getAddPagingBannerBottom
     * @return boolean
     * @throws Q70CustomTagException 
     */
    public boolean getAddPagingBannerBottom() throws Q70CustomTagException
    {
        String placement = getProperty(PROPERTY_STRING_BANNER_PLACEMENT);
        return "bottom".equals(placement) || "both".equals(placement);
    }

    /**
     * Method getSaveExcelFilename
     * @return String
     * @throws Q70CustomTagException 
     */
    public String getSaveExcelFilename() throws Q70CustomTagException
    {
        return getProperty(PROPERTY_STRING_SAVE_EXCEL_FILENAME);
    }

    /**
     * Method getSaveExcelBanner
     * @return String
     * @throws Q70CustomTagException 
     */
    public String getSaveExcelBanner() throws Q70CustomTagException
    {
        return getProperty(PROPERTY_STRING_SAVE_EXCEL_BANNER);
    }

    /**
     * Method getNoColumnMessage
     * @return String
     */
    public String getNoColumnMessage()
    {
        return "Please provide column tags";
    }

    /**
	 * Inicializa un nuevo objeto Q70TableProperties cargando el fichero de propiedades por defecto
	 * definido para todo Geremua. Además, añade a estas propiedades, las obtenidas del fichero
	 * por defecto definido para la aplicacion o las obtenidas del fichero asociado al parametro i18nKey. 
	 * Ambas opciones son dependientes de la configuracion local recivida por parametro.
	 * 
	 * @throws TablePropertiesLoadException para los errores ocurridos durante la carga de las propiedades
	 */
	public Q70TableProperties(List i18nKeyLista, Locale locale, HttpServletRequest req) throws TablePropertiesLoadException
	{		
		listaI18nKey = i18nKeyLista;
		languageTableProperties = locale.getLanguage();
		
		//Obtener (si existe) el idioma Geremua, y usarlo en lugar del recibido por parametro.
		String languageGeremua = Q70ListenerUtils.getLanguage(req);

		if (null!=languageGeremua)
			languageTableProperties = languageGeremua;
		
		if (tr.isTraceActive())
		{
			tr.trace(COMPONENTE, Q70TraceLevel.INFO, "Las propiedades de la tabla vienen dadas segun los parametros: \r\n"
												   + "-i18nKey: " + listaI18nKey + "\r\n" 
												   + "-language: " + languageTableProperties);
		}
		
		// Now copy in the user properties
		properties = new Properties();
		Enumeration keys = userProperties.keys();
		while (keys.hasMoreElements())
		{
			String key = (String) keys.nextElement();
			if (key != null)
			{
				properties.setProperty(key, (String) userProperties.get(key));
			}
		}
	}

	/**
     * Method getProperty
     * @param key String
     * @return String
	 * @throws Q70CustomTagException 
     */
    private String getProperty(String key) throws Q70CustomTagException 
    {
    	if (properties.containsKey(key)){
            return properties.getProperty(key);
    	}
    	try {
			return Q70GestorMensajesi18n.getSingleton().getMessage(listaI18nKey, key, languageTableProperties, null);
		} catch (Q70GestorMensajesException e) {
			throw new Q70CustomTagException(this.getClass().toString(),"getProperty","Error al recuperar una propiedad de la tabla, mediante el Gestor de Mensajes i18nKey",e);
		}
    }

    /**
     * Method setProperty
     * @param key String
     * @param value String
     */
    public void setProperty(String key, String value)
    {
        properties.setProperty(key, value);
    }

    /**
     * Method getBooleanProperty
     * @param key String
     * @return boolean
     * @throws Q70CustomTagException 
     */
    private boolean getBooleanProperty(String key) throws Q70CustomTagException
    {
        return Boolean.TRUE.toString().equals(getProperty(key));
    }

    /**
     * Method getIntProperty
     * @param key String
     * @param defaultValue int
     * @return int
     * @throws Q70CustomTagException 
     */
    private int getIntProperty(String key, int defaultValue) throws Q70CustomTagException
    {   	
        int intValue = defaultValue;

        try
        {
            intValue = Integer.parseInt(getProperty(key));
        }
        catch (NumberFormatException e)
        {
            // Don't care, use default
			if (tr.isTraceActive())
			{
				tr.trace(COMPONENTE, Q70TraceLevel.ERROR, "Valor incorrecto asignado a la propiedad \"pPropertyName\": value=\""
					  					  				+ getProperty(key)
										  				+ "\". Se usara el valor por defecto \"pDefault\"");
			}

        }

        return intValue;
    }

}