/*
 * ESTE COMPONENTE FUE REALIZADO BAJO LA METODOLOGÍA DE DESARROLLO
 * DE FUNERALES MODERNOS Y SE ENCUENTRA PROTEGIDO
 * POR LAS LEYES DE DERECHOS DE AUTOR.
 * @author Jorge Galvez
 */
package sv.com.fm.business.ejb;

import javax.ejb.Stateless;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceException;
import javax.persistence.Query;
import sv.com.fm.business.exception.FmBusinessRolledbackException;
import sv.com.fm.business.util.Constants;

/**
 *
 * @author Jorge Galvez
 */
@Stateless(mappedName = "ejb/GenericDaoServiceBean")
public class GenericDaoServiceBean implements GenericDaoServiceBeanLocal {

    Logger logger = Logger.getLogger(GenericDaoServiceBean.class.getName());
    @PersistenceContext(unitName = "FunerariaEJBPU")
    private EntityManager em;

    /**
     *
     * @param <T>
     * @param t
     * @return
     * @throws FmBusinessRolledbackException
     */
    @Override
    public <T> T create(T t) throws FmBusinessRolledbackException {
        logger.info("[GenericDaoServiceBean][create]INFO");
        logger.info("[create]Type entity=" + t.getClass().getCanonicalName());
        try {
            em.persist(t);
            em.flush();
            em.refresh(t);
        } catch (Exception e) {
            logger.severe("[Exception]" + e);
            e.printStackTrace();
            throw new FmBusinessRolledbackException(Constants.CODE_OPERATION_FALLIDA, "No se pudo actualizar crear registro");
        }
        return t;
    }

    @Override
    public <T> T createMerge(T t) throws FmBusinessRolledbackException {
        logger.info("[GenericDaoServiceBean][create]INFO");
        logger.info("[create]Type entity=" + t.getClass().getCanonicalName());
        try {
            em.merge(t);
            em.flush();
            em.refresh(t);
        } catch (Exception e) {
            logger.severe("[Exception]" + e);
            e.printStackTrace();
            throw new FmBusinessRolledbackException(Constants.CODE_OPERATION_FALLIDA, "No se pudo actualizar crear registro");
        }
        return t;
    }

    /**
     *
     * @param <T>
     * @param pEntityClass
     * @param id
     * @return
     */
    @Override
    public <T> T find(Class<T> pEntityClass, Object id) {
        logger.log(Level.INFO, "[GenericDaoServiceBean]find");
        try {
            return this.em.find(pEntityClass, id);
        } catch (NoResultException e) {
            logger.severe("[NoResultException]" + e);
            e.printStackTrace();
        } catch (Exception e) {
            logger.severe("[Exception]" + e);
            e.printStackTrace();
        }
        return null;
    }

    /**
     *
     * @param <T>
     * @param entity
     * @return
     * @throws FmBusinessRolledbackException
     */
    @Override
    public <T> Boolean delete(T entity) throws FmBusinessRolledbackException {
        logger.log(Level.INFO, "[GenericDaoServiceBean]delete");
        try {
            em.remove(em.merge(entity));
            return true;
        } catch (PersistenceException p) {
            logger.severe("[PersistenceException]" + p);
            throw new FmBusinessRolledbackException(Constants.CODE_OPERATION_FALLIDA, "PersistenceException, no se pudo eliminar registro");
        } catch (Exception e) {
            logger.severe("[Exception]" + e);
            e.printStackTrace();
            throw new FmBusinessRolledbackException(Constants.CODE_OPERATION_FALLIDA, "Exception, no se pudo eliminar registro");
        }
    }

    /**
     *
     * @param <T>
     * @param t
     * @return
     * @throws FmBusinessRolledbackException
     */
    @Override
    public <T> T update(T t) throws FmBusinessRolledbackException {
        logger.log(Level.INFO, "[GenericDaoServiceBean]update");
        try {
            em.merge(t);
//            em.flush();
//            em.getEntityManagerFactory().getCache().evictAll();
            return t;
        } catch (Exception e) {
            e.printStackTrace();
            logger.severe("[Exception]" + e);
            throw new FmBusinessRolledbackException(Constants.CODE_OPERATION_FALLIDA, "No se pudo actualizar registro");

        }
    }

    /**
     *
     * @param <T>
     * @param queryName
     * @return
     */
    @Override
    public <T> List<T> findByNamedQuery(String queryName) {
        logger.log(Level.INFO, "[GenericDaoServiceBean]findByNamedQuery");
        List<T> response = null;
        try {
            response = this.em.createNamedQuery(queryName).getResultList();
        } catch (NoResultException e) {
            logger.severe("[NoResultException]" + e);
            logger.log(Level.INFO, "[GenericDaoServiceBean]findByNamedQuery=No se encontraron registros");
            e.printStackTrace();
        } catch (Exception e) {
            logger.severe("[Exception]" + e);
            e.printStackTrace();
        }
        return response;
    }

    /**
     *
     * @param <T>
     * @param queryName
     * @param resultLimit
     * @return
     */
    @Override
    public <T> List<T> findByNamedQuery(String queryName, int resultLimit) {
        logger.log(Level.INFO, "[GenericDaoServiceBean]findByNamedQuery");
        List<T> response = null;
        try {
            return this.em.createNamedQuery(queryName).setMaxResults(resultLimit).getResultList();
        } catch (NoResultException e) {
            logger.severe("[NoResultException]" + e);
            logger.log(Level.INFO, "[GenericDaoServiceBean]findByNamedQuery=No se encontraron registros");
            e.printStackTrace();
        } catch (Exception e) {
            logger.severe("[Exception]" + e);
            e.printStackTrace();
        }
        return response;
    }

    /**
     *
     * @param <T>
     * @param t
     * @return
     */
    @Override
    public <T> List<T> findAll(Class<T> t) {
        logger.log(Level.INFO, "[GenericDaoServiceBean]findAll ");
        List<T> response = null;
        Query query = null;
        try {
            query = em.createQuery("from " + t.getName());
            //     javax.persistence.criteria.CriteriaQuery cq = em.get.getCriteriaBuilder().createQuery();
            // cq.select(cq.from(t));
            response = query.getResultList();
            // response = em.createQuery(cq).getResultList();
        } catch (NoResultException e) {
            logger.severe("[NoResultException]" + e);
            logger.log(Level.INFO, "[GenericDaoServiceBean]findAll=No se encontraron registros");
            e.printStackTrace();
        } catch (Exception e) {
            logger.severe("[Exception]" + e);
            e.printStackTrace();
        }
        return response;
    }

    /**
     *
     * @param lista
     */
    @Override
    public void saveOrUpdate(List lista) {
        logger.log(Level.INFO, "[GenericDaoServiceBean]create");
        try {
            if (lista != null) {
                for (Object e : lista) {
                    em.persist(e);
                    em.flush();
                    em.refresh(e);
                }
            }
        } catch (Exception e) {
            logger.severe("[Exception]" + e);
            e.printStackTrace();
        }
    }

    /**
     *
     * @param <T>
     * @param sql
     * @param pEntityClass
     * @return
     */
    @Override
    public <T> List<T> findByNativeQuery(String sql, Class<T> pEntityClass) {
        List<T> response = null;
        try {
            response = this.em.createNativeQuery(sql, pEntityClass).getResultList();
        } catch (NoResultException e) {
            logger.severe("[NoResultException]" + e);
            logger.log(Level.INFO, "[GenericDaoServiceBean]findByNamedQuery=No se encontraron registros");
            e.printStackTrace();
        } catch (Exception e) {
            logger.severe("[Exception]" + e);
            e.printStackTrace();
        }
        return response;
    }
}