package gov.va.vinci.dart.db.impl;

import java.util.List;

import javax.persistence.NoResultException;
import javax.persistence.Query;

import gov.va.vinci.dart.common.exception.ObjectNotFoundException;
import gov.va.vinci.dart.biz.PreparatoryRequest;
import gov.va.vinci.dart.biz.RequestStatus;
import gov.va.vinci.dart.db.PreparatoryRequestDAO;
import gov.va.vinci.dart.db.util.HibernateDAO;
import static gov.va.vinci.dart.common.ESAPIValidator.validateStringInput;
import static gov.va.vinci.dart.common.ESAPIValidationType.ACCESS_CONTROL_DB;


/**
 * The Class PreparatoryRequestDAOImpl.
 */
public class PreparatoryRequestDAOImpl extends HibernateDAO implements PreparatoryRequestDAO {

    /* (non-Javadoc)
     * @see gov.va.vinci.dart.db.PreparatoryRequestDAO#findById(int)
     */
    @Override
    public PreparatoryRequest findById(final int requestId) throws ObjectNotFoundException {
        Query q = createQuery("from PreparatoryRequest where id=:rid");
        q.setParameter("rid", getValidId(requestId));
        try {
            PreparatoryRequest result = (PreparatoryRequest) q.getSingleResult();

            if (result == null) {
                throw new ObjectNotFoundException("No Request found with id " + getValidId(requestId));
            }

            return result;
        } catch (NoResultException e) {
            throw new ObjectNotFoundException("No Request found with id " + getValidId(requestId), e);
        }

    }


    /* (non-Javadoc)
     * @see gov.va.vinci.dart.db.PreparatoryRequestDAO#listByActivityId(int)
     */
    @Override
    @SuppressWarnings("unchecked")
    public List<PreparatoryRequest> listByActivityId(final int activityId) {
        Query query = createQuery("from PreparatoryRequest where activity.id=:aid");
        query.setParameter("aid", getValidId(activityId));
        return (List<PreparatoryRequest>) query.getResultList();
    }


    /* (non-Javadoc)
     * @see gov.va.vinci.dart.db.PreparatoryRequestDAO#listByRequestor(int)
     */
    @Override
    @SuppressWarnings("unchecked")
    public List<PreparatoryRequest> listByRequestor(final int requestorId) {
        Query query = createQuery("from PreparatoryRequest where requestor.id=:rid");
        query.setParameter("rid", getValidId(requestorId));
        return (List<PreparatoryRequest>) query.getResultList();
    }

    /* (non-Javadoc)
     * @see gov.va.vinci.dart.db.PreparatoryRequestDAO#listAll()
     */
    @Override
    @SuppressWarnings("unchecked")
    public List<PreparatoryRequest> listAll() {
        Query query = createQuery("from PreparatoryRequest");
        return (List<PreparatoryRequest>) query.getResultList();
    }

    /* (non-Javadoc)
     * @see gov.va.vinci.dart.db.PreparatoryRequestDAO#listRecentByRequestor(int, int)
     */
    @Override
    @SuppressWarnings("unchecked")
    public List<PreparatoryRequest> listRecentByRequestor(final int requestorId, final int maxResults) {
        Query query = createQuery("from PreparatoryRequest where requestor.id=:rid order by updatedOn desc");
        query.setParameter("rid", getValidId(requestorId));
        query.setMaxResults(getValidId(maxResults));
        return (List<PreparatoryRequest>) query.getResultList();
    }

    /* (non-Javadoc)
     * @see gov.va.vinci.dart.db.PreparatoryRequestDAO#listByName(int, java.lang.String)
     */
    @Override
    @SuppressWarnings("unchecked")
    public List<PreparatoryRequest> listByName(final int requestorId, final String key) {
        String valideKey = validateStringInput(String.valueOf(key), ACCESS_CONTROL_DB);
        Query query = createQuery("from PreparatoryRequest where requestor.id=:rid "
                + "and (name like :rname or description like :rname or activity.trackingNumber like :rname "
                + "or activity.name like :rname or activity.officialName like :rname) order by createdOn desc");
        query.setParameter("rid", getValidId(requestorId));
        query.setParameter("rname", "%" + valideKey + "%");
        return (List<PreparatoryRequest>) query.getResultList();
    }

    /* (non-Javadoc)
     * @see gov.va.vinci.dart.db.PreparatoryRequestDAO#listAllButInitiated()
     */
    @Override
    @SuppressWarnings("unchecked")
    public List<PreparatoryRequest> listAllButInitiated() {
        Query query = createQuery("from PreparatoryRequest where status<>:stat");
        query.setParameter("stat", RequestStatus.INITIATED.getId());
        return (List<PreparatoryRequest>) query.getResultList();
    }

    /* (non-Javadoc)
     * @see gov.va.vinci.dart.db.PreparatoryRequestDAO#listAllSubmitted()
     */
    @Override
    @SuppressWarnings("unchecked")
    public List<PreparatoryRequest> listAllSubmitted() {
        Query query = createQuery("from PreparatoryRequest where status=:stat or status=:changed");
        query.setParameter("stat", RequestStatus.SUBMITTED.getId());
        query.setParameter("changed", RequestStatus.CHANGE_REQUESTED.getId());
        return (List<PreparatoryRequest>) query.getResultList();
    }

    /* (non-Javadoc)
     * @see gov.va.vinci.dart.db.PreparatoryRequestDAO#findMostRecentAmendment(int)
     */
    @Override
    @SuppressWarnings("unchecked")
    public PreparatoryRequest findMostRecentAmendment(final int headId) {

        Query query = createQuery("from PreparatoryRequest where headId=:head order by createdOn desc");

        query.setParameter("head", getValidId(headId));
        List<PreparatoryRequest> ll = (List<PreparatoryRequest>) query.getResultList();

        if (ll == null || ll.size() < 1) {
            return null;
        }

        return (PreparatoryRequest) ll.get(0);
    }
    
    private int getValidId(final int id) {
        String validId = validateStringInput(String.valueOf(id), ACCESS_CONTROL_DB);
        return Integer.valueOf(validId);
    }

    /* (non-Javadoc)
     * @see gov.va.vinci.dart.db.PreparatoryRequestDAO#save(gov.va.vinci.dart.biz.PreparatoryRequest)
     */
    @Override
    public void save(final PreparatoryRequest request) {

        if (request == null) {
            throw new IllegalArgumentException();
        }

        HibernateDAO.save(request);
    }
}
