/*
 * 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.system;

import com.arrebol.taxiservicios.controller.connection.ConnectionManager;
import com.arrebol.taxiservicios.controller.util.HibernateUtil;
import com.arrebol.taxiservicios.model.core.SystemProperty;
import com.arrebol.taxiservicios.model.enums.SystemPropertyType;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.CriteriaUpdate;
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>
 */
public class SystemPropertyController extends ConnectionManager implements Serializable {

    /**
     *
     * @param propertyName
     * @return
     */
    public SystemProperty findSystemPropertyControllerByPropertyName(SystemPropertyType propertyName) {
        logger.info("findSystemPropertyControllerByPropertyName");

        SystemProperty systemProperty;
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<SystemProperty> query = builder.createQuery(SystemProperty.class);
            Root<SystemProperty> root = query.from(SystemProperty.class);

            Path<String> id = root.get("id");
            Path<String> propertyValue = root.get("propertyValue");

            query.select(builder.construct(SystemProperty.class, id, propertyValue));
            query.where(builder.equal(root.get("propertyName"), propertyName));

            systemProperty = session.createQuery(query).getSingleResult();

            transaction.commit();

            logger.info("System Property loaded " + systemProperty);
        } catch (HibernateException e) {
            logger.error("System property cannot be loaded ", e);
            rollback(transaction);
            systemProperty = new SystemProperty("ERROR-ID", SystemPropertyType.FEE, "50");
        } catch (Exception e) {
            logger.error("Method findSystemPropertyControllerByPropertyName() ", e);
            rollback(transaction);
            systemProperty = new SystemProperty("ERROR-ID", SystemPropertyType.FEE, "50");
        }

        return systemProperty;
    }

    /**
     *
     * @return
     */
    public List<SystemProperty> getAllSystemProperties() {
        logger.info("getAllSystemProperties");

        List<SystemProperty> results = new ArrayList<>();
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<SystemProperty> query = builder.createQuery(SystemProperty.class);
            Root<SystemProperty> root = query.from(SystemProperty.class);

            Path<String> id = root.get("id");
            Path<SystemPropertyType> propertyName = root.get("propertyName");
            Path<String> propertyValue = root.get("propertyValue");

            query.select(builder.construct(SystemProperty.class, id, propertyName, propertyValue));

            results = session.createQuery(query).getResultList();

            transaction.commit();
            logger.info("System properties loaded " + results.size());
        } catch (HibernateException e) {
            logger.error("System properties cannot be loaded ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method getAllSystemProperties() ", e);
            rollback(transaction);
        }

        return results;
    }

    /**
     *
     * @param systemProperties
     * @return
     */
    public boolean updateSystemProperties(List<SystemProperty> systemProperties) {
        logger.info("updateSystemProperties");

        boolean success = false;

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

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaUpdate<SystemProperty> updateQuery = builder.createCriteriaUpdate(SystemProperty.class);
            Root<SystemProperty> root = updateQuery.from(SystemProperty.class);

            systemProperties.forEach(property -> {

                updateQuery.set(root.get("propertyValue"), property.getPropertyValue());
                updateQuery.where(builder.equal(root.get("id"), property.getId()));

                session.createQuery(updateQuery).executeUpdate();
                logger.info("System Property "
                        + property.getPropertyName().getType()
                        + " will update, new value "
                        + property.getPropertyValue());
            });

            transaction.commit();
            success = true;
        } catch (HibernateException e) {
            logger.error("System properties cannot be loaded ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method getAllSystemProperties() ", e);
            rollback(transaction);
        }

        return success;
    }

    private static final long serialVersionUID = -1L;

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