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

public class DartRequestDAOImpl extends HibernateDAO implements DartRequestDAO {
	
	@Override
	public DartRequest findById(final int requestId) throws ObjectNotFoundException {
//		return (DartRequest)findById(DartRequest.class, requestId);
		Query q = createQuery("from DartRequest where id=:rid");
		q.setParameter("rid", requestId);
		try {
			DartRequest result = (DartRequest)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<DartRequest> listByActivityId(final int activityId) {
		Query query = createQuery("from DartRequest where activity.id=:aid");
		query.setParameter("aid", activityId);
		return (List<DartRequest>)query.getResultList();
	}
	
	@Override
	@SuppressWarnings("unchecked")
	public List<DartRequest> listByRequestor(final int requestorId) {
		Query query = createQuery("from DartRequest where requestor.id=:rid");
		query.setParameter("rid", requestorId);
		return (List<DartRequest>)query.getResultList();
	}

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

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

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

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

		//for imported requests, the request IDs were out of order (A03 < A02).  Fixed the createdOn dirty data (imported from the old SharePoint application).  Fixed the trackingNumber dirty data (imported from the old SharePoint application).
		//Query query = createQuery("from DartRequest where headId=:head order by id desc");
		//Query query = createQuery("from DartRequest where headId=:head order by trackingnumber desc");
		Query query = createQuery("from DartRequest where headId=:head order by createdOn desc");

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

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

	@Override
	public void save(final DartRequest request) {

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