/*
 * Arrebol Consultancy copyright.
 * 
 * This code belongs to Arrebol Consultancy
 * its use, redistribution or modification are prohibited 
 * without written authorization from Arrebol Consultancy.
 */
package com.arrebol.taxiservicios.controller.login;

import com.arrebol.taxiservicios.controller.connection.ConnectionManager;
import com.arrebol.taxiservicios.controller.util.HibernateUtil;
import com.arrebol.taxiservicios.model.catalog.Location;
import com.arrebol.taxiservicios.model.core.Person;
import com.arrebol.taxiservicios.model.core.User;
import com.arrebol.taxiservicios.model.view.jaas.SecurityAuthorization;
import java.io.Serializable;
import java.util.List;
import javax.enterprise.context.SessionScoped;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Root;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

/**
 *
 * @author Carlos Janitzio Zavala Lopez <janitzio.zavala@arrebol.com.mx>
 */
@SessionScoped
public class LoginServiceImpl extends ConnectionManager implements LoginService, Serializable {

    private static final long serialVersionUID = -7222793821578056285L;

    final Logger logger = LogManager.getLogger(getClass());

    @Override
    public User loadUserSigned(String userName) {
        logger.info("loadUserSigned: " + userName);

        Transaction transaction = null;
        User user = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<User> criteria = builder.createQuery(User.class);
            Root<User> userRoot = criteria.from(User.class);

            Path<String> idPath = userRoot.get("id");
            Path<String> userNamePath = userRoot.get("userName");
            Path<Person> personPath = userRoot.get("person");
            Path<Boolean> rootPath = userRoot.get("root");
            Path<Location> locationPath = userRoot.get("location");

            criteria.select(builder.construct(User.class, idPath, userNamePath, personPath, rootPath, locationPath));
            criteria.where(builder.equal(userRoot.get("userName"), userName));

            user = session.createQuery(criteria).uniqueResult();

            transaction.commit();
            logger.info("User " + userName + " successfully loaded");
        } catch (HibernateException e) {
            logger.error("User " + userName + " can not be readed ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method loadUserSigned(" + userName + ")", e);
            rollback(transaction);
        }

        return user;
    }

    @Override
    public List<String> loadGrantsByUser(String userName) {
        logger.info("Start loadGrantsByUser");

        Transaction transaction = null;
        List<String> grants = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<String> criteria = builder.createQuery(String.class);
            Root<SecurityAuthorization> roleRoot = criteria.from(SecurityAuthorization.class);

            criteria.select(roleRoot.get("permission"));
            criteria.where(
                    builder.equal(roleRoot.get("userName"), userName)
            );

            grants = session.createQuery(criteria).getResultList();

            transaction.commit();
            logger.info("User " + userName + " grants successfully loaded");
            logger.info("Grants:  " + grants);
        } catch (HibernateException e) {
            logger.error("User mobile " + userName + " can not be readed ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method loadGrantsByUser(" + userName + ")", e);
        }
        return grants;
    }
}
