/*******************************************************************************
 * This file is part of GECAMed.
 * 
 * GECAMed is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License (L-GPL) as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * GECAMed is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License (L-GPL)
 * along with GECAMed.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * GECAMed is Copyrighted by the Centre de Recherche Public Henri Tudor (http://www.tudor.lu)
 * (c) CRP Henri Tudor, Luxembourg, 2008
 *******************************************************************************/
package lu.tudor.santec.gecamed.core.ejb.session.beans;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.annotation.security.RolesAllowed;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import lu.tudor.santec.gecamed.core.ejb.entity.beans.GECAMedEntityBean;
import lu.tudor.santec.gecamed.core.ejb.entity.beans.GECAMedLocale;
import lu.tudor.santec.gecamed.core.ejb.entity.beans.NationalHoliday;
import lu.tudor.santec.gecamed.core.ejb.session.interfaces.ListManagerInterface;
import lu.tudor.santec.gecamed.core.utils.ServerConfig;
import lu.tudor.santec.gecamed.usermanagement.ejb.entity.beans.GecamedInfo;

import org.apache.log4j.Logger;

/**
 *	This SessionBean class manages the getter access to the static lists like
 *	Languages, Titles, Genders etc...
 * It allthough provides a method to retrieve some server-infos like server-build date etc..
 * 
 * @author Johannes Hermen johannes.hermen(at)tudor.lu
 * 
 * @Version
 * <br>$Log: ListManagerBean.java,v $
 * <br>Revision 1.20  2013-12-27 18:09:22  donak
 * <br>Cleanup of imports
 * <br>
 * <br>Revision 1.19  2013-11-05 14:50:00  ferring
 * <br>method added to save / merge a bean
 * <br>
 * <br>Revision 1.18  2013-10-31 14:05:41  ferring
 * <br>methods added to get any bean by class and ID
 * <br>
 * <br>Revision 1.17  2013-02-19 12:07:34  ferring
 * <br>GECAMedLists changed. Will now automatically load list of all beans
 * <br>
 * <br>Revision 1.16  2012-02-07 10:42:22  ferring
 * <br>Java properties are now also shown at the server properties
 * <br>
 * <br>Revision 1.15  2009-06-03 09:22:53  hermen
 * <br>show core.info table in about dialog
 * <br>
 * <br>Revision 1.14  2009-05-15 07:34:04  hermen
 * <br>show core.info in about dialog
 * <br>
 * <br>Revision 1.13  2009-05-13 12:54:01  hermen
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.12  2009-05-08 07:59:27  hermen
 * <br>open help website on firstrun
 * <br>
 * <br>Revision 1.11  2008-09-25 09:43:07  heinemann
 * <br>fixed copyrights
 * <br>
 * <br>Revision 1.10  2008-01-15 10:44:12  hermen
 * <br>updated Javadoc and refactured code
 * <br>
 */


@Remote({ListManagerInterface.class})
@Stateless
public class ListManagerBean implements ListManagerInterface 
{
    //~ Static fields/initializers =============================================
    
//    private static final long serialVersionUID = 1L;
	
    /**
     * static logger for this class
     */
    private static Logger logger = Logger.getLogger(ListManagerBean.class.getName());
    
    private static Map<Class<?>, List<?>> lists	= new Hashtable<Class<?>, List<?>>();
    
    @PersistenceContext (unitName="gecam")
	EntityManager em;
	
    
    //~ Methods ================================================================

    /* (non-Javadoc)
	 * @see lu.tudor.santec.gecamed.core.ejb.session.beans.ListManagerInterface#getGenders()
	 */
    @SuppressWarnings("unchecked")
	@RolesAllowed("gecam")
    public String[] getGenders() throws Exception
    {
        Query q = em.createQuery("SELECT DISTINCT gender.value " + 
        		"FROM Gender AS gender");
		Collection l = q.getResultList();
		return (String[]) l.toArray(new String[0]);
	}
    
    /* (non-Javadoc)
	 * @see lu.tudor.santec.gecamed.core.ejb.session.beans.ListManagerInterface#getLanguages()
	 */
    @SuppressWarnings("unchecked")
	@RolesAllowed("gecam")
    public String[] getLanguages() throws Exception
    {
        Query q = em.createQuery("SELECT DISTINCT language.value " + 
        		"FROM Language AS language");
		Collection l = q.getResultList();
		return (String[]) l.toArray(new String[0]);
	}
    
    /* (non-Javadoc)
	 * @see lu.tudor.santec.gecamed.core.ejb.session.beans.ListManagerInterface#getMaritalStates()
	 */
    @SuppressWarnings("unchecked")
	@RolesAllowed("gecam")
    public String[] getMaritalStates() throws Exception
    {
        Query q = em.createQuery("SELECT DISTINCT maritalstatus.value " + 
        		"FROM MaritalStatus AS maritalstatus");
		Collection l = q.getResultList();
		return (String[]) l.toArray(new String[0]);
	}
    
    /* (non-Javadoc)
	 * @see lu.tudor.santec.gecamed.core.ejb.session.beans.ListManagerInterface#getNationalities()
	 */
    @SuppressWarnings("unchecked")
	@RolesAllowed("gecam")
    public String[] getNationalities() throws Exception
    {
        Query q = em.createQuery("SELECT DISTINCT nationality.value " + 
        		"FROM Nationality AS nationality");
		Collection l = q.getResultList();
		return (String[]) l.toArray(new String[0]);
	}
    
    /* (non-Javadoc)
	 * @see lu.tudor.santec.gecamed.core.ejb.session.beans.ListManagerInterface#getPhoneTypes()
	 */
    @SuppressWarnings("unchecked")
	@RolesAllowed("gecam")
    public String[] getPhoneTypes() throws Exception
    {
        Query q = em.createQuery("SELECT DISTINCT phonetype.value " + 
        		"FROM PhoneType AS phonetype");
		Collection l = q.getResultList();
		return (String[]) l.toArray(new String[0]);
	}
    
    /* (non-Javadoc)
	 * @see lu.tudor.santec.gecamed.core.ejb.session.beans.ListManagerInterface#getPhoneTypes()
	 */
    @SuppressWarnings("unchecked")
	@RolesAllowed("gecam")
    public GECAMedLocale[] getGECAMedLocales() throws Exception
    {
        Query q = em.createNamedQuery("findAllGECAMedLocales"); 
        ArrayList<GECAMedLocale> l = new ArrayList(q.getResultList());
		return l.toArray(new GECAMedLocale[0]);
	}
    
    /* (non-Javadoc)
	 * @see lu.tudor.santec.gecamed.core.ejb.session.beans.ListManagerInterface#getTitles()
	 */
    @SuppressWarnings("unchecked")
	@RolesAllowed("gecam")
    public String[] getTitles() throws Exception
    {
        Query q = em.createQuery("SELECT DISTINCT title.value " + 
        		"FROM Title AS title");
		Collection l = q.getResultList();
		return (String[]) l.toArray(new String[0]);
	}
    
    /* (non-Javadoc)
	 * @see lu.tudor.santec.gecamed.core.ejb.session.beans.ListManagerInterface#getTitles()
	 */
    @SuppressWarnings("unchecked")
	@RolesAllowed("gecam")
    public String[] getDrTitles() throws Exception
    {
        Query q = em.createQuery("SELECT DISTINCT drTitle.value " + 
        		"FROM DrTitle AS drTitle");
		Collection l = q.getResultList();
		return (String[]) l.toArray(new String[0]);
	}
    
    
    /* (non-Javadoc)
     * @see lu.tudor.santec.gecamed.core.ejb.session.interfaces.ListManagerInterface#getServerInfos()
     */
    @SuppressWarnings("unchecked")
	@RolesAllowed("gecam")
	public Properties getServerInfos() {
		// load version infos and add them to system properties
		Properties version = new Properties();
		try {
			version.load(ListManagerBean.class.getResourceAsStream("VERSION.properties"));
			for (Iterator iter = version.keySet().iterator(); iter.hasNext();) {
				String element = (String) iter.next();
				if (element != null && element.length() > 0) {
					System.setProperty(element, version.getProperty(element));					
				}
			}
		} catch (IOException e) {
		}
		version.put(JBOSS_DIR, ServerConfig.JBOSS_DIR);
		version.put(GECAMED_DIR, ServerConfig.GECAMED_DIR);
		
		for (Object prop : System.getProperties().keySet())
			version.put(prop, System.getProperty((String) prop));
		
		String ips = ServerConfig.getJBossIPs();
		logger.info("JBoss IPs:\n" + ips);
		version.put("IPs", ips);
		
		return version;
	}
    
    	@SuppressWarnings("unchecked")
	public List<GecamedInfo> getCoreInfos() {
            	try {
        	    return (List<GecamedInfo>) em.createNamedQuery(GecamedInfo.FIND_ALL_INFOS).getResultList();
        	} catch (Exception e) {
        	    e.printStackTrace();
        	}
        	return null;
    	}
    	
    	

	/* (non-Javadoc)
	 * @see lu.tudor.santec.gecamed.core.ejb.session.interfaces.ListManagerInterface#getNationalHolidays()
	 */
	@SuppressWarnings("unchecked")
	public NationalHoliday[] getNationalHolidays() throws Exception {
		Collection<NationalHoliday> days = em.createNamedQuery("getAllNationalHolidays").getResultList();
		return days.toArray(new NationalHoliday[0]);
	}
	
	
	@SuppressWarnings("unchecked")
	public <T> List<T> getAllBeans (Class<T> clazz)
	{
		return em.createQuery("SELECT OBJECT(o) FROM "+clazz.getSimpleName()+" o")
				.getResultList();
	}
	
	
	public <T> T getBean (Class<T> clazz, Integer id)
	{
		return em.find(clazz, id);
	}
	
	
	public <T extends GECAMedEntityBean> T saveBean (T bean)
	{
		return em.merge(bean);
	}
	
	
	public <T extends GECAMedEntityBean> void removeBean (T bean)
	{
		em.remove(bean);
	}
	
	
	@SuppressWarnings("unchecked")
	public <T extends GECAMedEntityBean> List<T> getListReference (Class<T> clazz)
	{
		List<?> listReference = lists.get(clazz);
		
		if (listReference == null)
		{
			listReference	= getAllBeans(clazz);
			lists.put(clazz, listReference);
		}
		
		return (List<T>) listReference;
	}
	
	
	public void resetList (Class<?> clazz)
	{
		lists.remove(clazz);
	}
}
