package lu.tudor.santec.gecamed.letter.ejb.session.beans;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import lu.tudor.santec.gecamed.core.utils.NamedParameterBean;
import lu.tudor.santec.gecamed.letter.ejb.entity.beans.LetterPlaceholder;
import lu.tudor.santec.gecamed.letter.ejb.session.interfaces.LetterPlaceholderInterface;

import org.apache.log4j.Logger;

@Stateless
@Remote(LetterPlaceholderInterface.class)

public class LetterPlaceholderBean implements LetterPlaceholderInterface
{
	/* ======================================== */
	// 		MEMBERS
	/* ======================================== */
	
	/** the logger Object for this class */
	private static Logger logger = Logger.getLogger(LetterPlaceholderBean.class.getName());
	
	
	@PersistenceContext(unitName = "gecam")
	private EntityManager em;
	
	
	
	/* ======================================== */
	// 		CLASS BODY
	/* ======================================== */
	
	public List<String> getPlaceholderTypes ()
	{
		@SuppressWarnings("unchecked")
		List<String> results	= em.createNamedQuery(LetterPlaceholder.GET_PLACEHOLDER_TYPES)
				.getResultList();
		return results;
	}
	
	
	public List<String> getPlaceholderNamesByType (String type)
	{
		@SuppressWarnings("unchecked")
		List<String> results	= em.createNamedQuery(LetterPlaceholder.GET_PLACEHOLDER_NAMES_BY_TYPE)
				.setParameter("type", type)
				.getResultList();
		return results;
	}
	
	
	public List<LetterPlaceholder> getPlaceholdersByType(String type)
	{
		@SuppressWarnings("unchecked")
		List<LetterPlaceholder> results	= em.createNamedQuery(LetterPlaceholder.GET_PLACEHOLDERS_BY_TYPE)
				.setParameter("type", type)
				.getResultList();
		return results;
	}
	
	
	public List<LetterPlaceholder> getPlaceholdersByName (Collection<String> names)
	{
		if (names == null || names.isEmpty())
			return new ArrayList<LetterPlaceholder>(0);
		
		@SuppressWarnings("unchecked")
		List<LetterPlaceholder> results	= em.createNamedQuery(LetterPlaceholder.GET_PLACEHOLDERS_BY_NAMES)
				.setParameter("names", names)
				.getResultList();
		return results;
	}
	
	
	public List<String> getPlaceholderNamesByName (Collection<String> names)
	{
		if (names == null || names.isEmpty())
			return new ArrayList<String>(0);
		
		@SuppressWarnings("unchecked")
		List<String> results	= em.createNamedQuery(LetterPlaceholder.GET_PLACEHOLDER_NAMES_BY_NAMES)
				.setParameter("names", names)
				.getResultList();
		return results;
	}
	
	
	public List<String> getContactPlaceholderNames()
	{
		@SuppressWarnings("unchecked")
		List<String> result = em.createNamedQuery(LetterPlaceholder.GET_CONTACT_PLACEHOLDER_NAMES)
				.getResultList();
		return result;
	}
	
	
	public List<?> doHqlQuery(String queryString, Integer firstResult, Integer maxResult, Object ... parameters)
	{
		Query				query = em.createQuery(queryString);
		Boolean				useNamedParameters;
		NamedParameterBean	namedParam;
		
		
		if (parameters != null && parameters.length > 0)
		{
			useNamedParameters = parameters[0] instanceof NamedParameterBean ? Boolean.TRUE : Boolean.FALSE;
			
			for (int i = 0; i < parameters.length; i++)
			{
				if (parameters[i] instanceof NamedParameterBean)
				{
					if (!useNamedParameters)
						throw new RuntimeException("No simultaneously use of positional and named parameters in one query!");
					
					namedParam = (NamedParameterBean) parameters[i];
					query.setParameter(namedParam.getName(), namedParam.getValue());
				}
				else
				{
					if (useNamedParameters)
						throw new RuntimeException("No simultaneously use of positional and named parameters in one query!");
					
					query.setParameter(i + 1, parameters[i]);
				}
			}
		}
		
		if (firstResult != null)
			query.setFirstResult(firstResult.intValue());
		if (maxResult != null)
			query.setMaxResults(maxResult.intValue());
		
		return query.getResultList();
	}
	
	
	public List<?> doNativeQuery(String queryString, Object ... parameters)
	{
		Query				query				= em.createNativeQuery(queryString);
		Boolean				useNamedParameters;
		Object				param;
		NamedParameterBean	namedParam;
		
		
		if (parameters != null && parameters.length > 0)
		{
			useNamedParameters = parameters[0] instanceof NamedParameterBean ? Boolean.TRUE : Boolean.FALSE;
			
			for (int i = 0; i < parameters.length; i++)
			{
				param = parameters[i];
				if (param instanceof NamedParameterBean)
				{
					if (!useNamedParameters)
						throw new RuntimeException("No simultaneously use of positional and named parameters in one query!");
					
					namedParam = (NamedParameterBean) param;
					query.setParameter(namedParam.getName(), namedParam.getValue());
				}
				else
				{
					if (useNamedParameters)
						throw new RuntimeException("No simultaneously use of positional and named parameters in one query!");
					
					query.setParameter(i, param);
				}
			}
		}
		
		return query.getResultList();
	}
	
	
	public List<LetterPlaceholder> getFunctions(Collection<String> types)
	{
		@SuppressWarnings("unchecked")
		List<LetterPlaceholder> functions = em.createNamedQuery(LetterPlaceholder.GET_FUNCTIONS_FOR_TYPES)
				.setParameter("types", types)
				.getResultList();
		
		return functions;
	}
	
	
	public String getFunctions (String type)
	{
		LetterPlaceholder functions;
		
		try
		{
			if (type == null)
			{
				functions = (LetterPlaceholder) em.createQuery(
								"SELECT OBJECT(f) FROM LetterPlaceholder f " +
								"WHERE name IS NULL AND type IS NULL")
						.setMaxResults(1)
						.getSingleResult();
			}
			else
			{
				functions = (LetterPlaceholder) em.createNamedQuery(LetterPlaceholder.GET_FUNCTIONS_FOR_TYPE)
						.setParameter("type", type)
						.setMaxResults(1)
						.getSingleResult();
			}
			return functions.getScript();
		}
		catch (NoResultException e)
		{
			logger.warn("No functions found for type \""+type+"\"");
			return "";
		}
	}
}
