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.OperationalRequest;
import gov.va.vinci.dart.biz.RequestStatus;
import gov.va.vinci.dart.db.OperationalRequestDAO;
import gov.va.vinci.dart.db.util.HibernateDAO;

public class OperationalRequestDAOImpl extends HibernateDAO implements OperationalRequestDAO {

	public void save(OperationalRequest request) {
		if (request == null) {
			throw new IllegalArgumentException();
		}
		
		HibernateDAO.save(request);
	}
	
	@Override
	public OperationalRequest findById(final int requestId) throws ObjectNotFoundException {
//		return (OperationalRequest)findById(OperationalRequest.class, requestId);
		Query q = createQuery("from OperationalRequest where id=:rid");
		q.setParameter("rid", requestId);
		try {
			OperationalRequest result = (OperationalRequest)q.getSingleResult();
			
			if (result == null) {
				throw new ObjectNotFoundException("No Request found with id " + requestId);
			}
			
			return result;
		} catch (NoResultException e) {
			throw new ObjectNotFoundException("No Request found with id " + requestId, e);
		}

	}

	// TODO- these return types imply widening conversions from DartRequest to Request which may not be appropriate.
	
	@Override
	@SuppressWarnings("unchecked") 
	public List<OperationalRequest> listByActivityId(final int activityId) {
		Query query = createQuery("from OperationalRequest where activity.id=:aid");
		query.setParameter("aid", activityId);
		return (List<OperationalRequest>)query.getResultList();
	}
	
	@Override
	@SuppressWarnings("unchecked")
	public List<OperationalRequest> listByRequestor(final int requestorId) {
		Query query = createQuery("from OperationalRequest where requestor.id=:rid");
		query.setParameter("rid", requestorId);
		return (List<OperationalRequest>)query.getResultList();
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<OperationalRequest> listAll() {
		Query query = createQuery("from OperationalRequest");
		return (List<OperationalRequest>)query.getResultList();
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<OperationalRequest> listRecentByRequestor(final int requestorId, final int maxResults) {
		Query query = createQuery("from OperationalRequest where requestor.id=:rid order by updatedOn desc");
		query.setParameter("rid", requestorId);
		query.setMaxResults(maxResults);
		return (List<OperationalRequest>)query.getResultList();
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<OperationalRequest> listByName(final int requestorId, final String key) {
		Query query = createQuery("from OperationalRequest 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", requestorId);
		query.setParameter("rname", "%"+key+"%");
		return (List<OperationalRequest>)query.getResultList();
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<OperationalRequest> listAllButInitiated() {
		Query query = createQuery("from OperationalRequest where status<>:stat");
		query.setParameter("stat", RequestStatus.INITIATED.getId());		
		return (List<OperationalRequest>)query.getResultList();
	}
	
	@Override
	@SuppressWarnings("unchecked")
	public List<OperationalRequest> listAllSubmitted() {
		Query query = createQuery("from OperationalRequest where status=:stat or status=:changed");
		query.setParameter("stat", RequestStatus.SUBMITTED.getId());
		query.setParameter("changed", RequestStatus.CHANGE_REQUESTED.getId());
		return (List<OperationalRequest>)query.getResultList();
	}
	
	@Override
	@SuppressWarnings("unchecked")
	public OperationalRequest findMostRecentAmendment(final int headId) {

		//for imported requests, the amendment requestId was occasionally getting out of order (A03 < A02)		
		//Query query = createQuery("from OperationalRequest where headId=:head order by id desc");
		//Query query = createQuery("from OperationalRequest where headId=:head order by trackingnumber desc");
		Query query = createQuery("from OperationalRequest where headId=:head order by createdOn desc");
		
		query.setParameter("head", headId);
		List<OperationalRequest> ll = (List<OperationalRequest>)query.getResultList();
		
		if (ll == null || ll.size() < 1) {
			return null;
		}
		
		return (OperationalRequest)ll.get(0);
	}

}
