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

import com.arrebol.taxiservicios.controller.connection.ConnectionManager;
import com.arrebol.taxiservicios.controller.util.HibernateUtil;
import com.arrebol.taxiservicios.model.admin.ReleaseResource;
import com.arrebol.taxiservicios.model.admin.Taxi;
import com.arrebol.taxiservicios.model.core.Person;
import com.arrebol.taxiservicios.model.core.User;
import com.arrebol.taxiservicios.model.enums.GenericEnumType;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.CriteriaUpdate;
import javax.persistence.criteria.Predicate;
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 ReleaseResourceController extends ConnectionManager implements Serializable {

    /**
     *
     * @param releaseResource
     * @return
     */
    public boolean saveReleaseResource(ReleaseResource releaseResource) {
        logger.info("saveReleaseResource");

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

            session.save(releaseResource);

            commit(transaction);
            success = true;
            logger.info("The release resource was saved - " + releaseResource);
        } catch (HibernateException e) {
            logger.error("The release resource can not be saved - " + releaseResource, e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method saveReleaseResource(" + releaseResource + ")", e);
            rollback(transaction);
        }

        return success;
    }

    /**
     * If driver is null taxi must has value otherwise If taxi is null driver
     * must has value.
     *
     * @param driver
     * @param taxi
     * @param endDate
     * @param active
     * @param lastUpdatedBy
     * @param lastUpdatedOn
     * @return
     */
    public boolean updateReleaseResourceDetails(Person driver, Taxi taxi, Date endDate, GenericEnumType active, User lastUpdatedBy, Date lastUpdatedOn) {
        logger.info("updateReleaseResourceDetails");

        boolean success = false;
        Transaction transaction = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();

            transaction = session.beginTransaction();

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaUpdate<ReleaseResource> update = builder.createCriteriaUpdate(ReleaseResource.class);
            Root<ReleaseResource> root = update.from(ReleaseResource.class);
            Predicate predicate;

            update.set("endDate", endDate);
            update.set("active", active);
            update.set("lastUpdatedBy", lastUpdatedBy);
            update.set("lastUpdatedOn", lastUpdatedOn);

            if (null == driver) {
                predicate = builder.equal(root.get("taxi"), taxi);
            } else {
                predicate = builder.equal(root.get("driver"), driver);
            }

            update.where(builder.and(
                    predicate,
                    builder.equal(root.get("active"), GenericEnumType.ENABLED)
            ));

            session.createQuery(update).executeUpdate();

            commit(transaction);
            success = true;

            logger.info("Release resources was updated");
        } catch (HibernateException e) {
            logger.error("The release resource can not be updated", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method updateReleaseResourceDetails", e);
            rollback(transaction);
        }
        return success;
    }

    /**
     *
     * @param driverId
     * @return
     */
    public boolean existDriverEnebledInReleaseResource(String driverId) {
        logger.info("findDriverInReleaseResource");

        boolean exist = false;
        Transaction transaction = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();

            transaction = session.beginTransaction();

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

            query.where(builder.and(
                    builder.equal(root.get("driver"), new Person(driverId)),
                    builder.equal(root.get("active"), GenericEnumType.ENABLED)
            ));

            List<ReleaseResource> results = session.createQuery(query).getResultList();
            if (!results.isEmpty()) {
                exist = true;
            }

            commit(transaction);
            logger.info("Find driver in release resources");
        } catch (HibernateException e) {
            logger.error("Driver in release resources can not be found", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method findDriverInReleaseResource", e);
            rollback(transaction);
        }
        return exist;
    }

    /**
     *
     * @param id Driver ID or Taxi ID.
     * @param active
     * @param isDriver true is Driver entity, false is Taxi entity.
     * @return If the entity (Driver/Taxi) is founded return true otherwise
     * return false.
     */
    public boolean findReleaseResourcesByIdAndActiveStatus(String id, GenericEnumType active, boolean isDriver) {
        logger.info("findReleaseResourcesByIdAndActiveStatus");

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

            StringBuilder hql = new StringBuilder("SELECT COUNT(rr.id) FROM ReleaseResource rr");

            hql.append(" WHERE rr.active = :active");
            hql.append(" AND ");
            hql.append(isDriver ? "rr.driver = :driver" : "rr.taxy = :taxy");

            Long value = (Long) session.createQuery(hql.toString())
                    .setParameter("active", active)
                    .setParameter(isDriver ? "driver" : "taxy", isDriver ? new Person(id) : new Taxi(id))
                    .getSingleResult();

            commit(transaction);

            if (value.compareTo(new Long(1)) == 0) {
                exist = true;
            }
            logger.info("Find release resources");
        } catch (HibernateException e) {
            logger.error("Release resources can not be found", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method findReleaseResourcesByIdAndActiveStatus", e);
            rollback(transaction);
        }
        return exist;
    }

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

            transaction.commit();
            logger.info("Find release resources from add taxi");
        } catch (HibernateException e) {
            logger.error("Release resources can not be added from add taxi", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method releaseFromAddTaxi", e);
            rollback(transaction);
        }
    }

    private static final long serialVersionUID = -1L;

    final Logger logger = LogManager.getLogger(ReleaseResourceController.class);

    public ReleaseResourceController() {
    }

}
