/********************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ********************************************************************/
package gov.va.med.esr.common.persistent.history;

// Java Classes
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.io.Serializable;

import org.apache.commons.lang.Validate;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;

import gov.va.med.esr.common.model.ee.EnrollmentDetermination;
import gov.va.med.esr.common.model.financials.IncomeTest;
import gov.va.med.esr.common.model.lookup.EnrollmentStatus;
import gov.va.med.esr.service.impl.ChangeEvent;
import gov.va.med.esr.service.impl.FinancialsChangeEvent;
import gov.va.med.esr.service.impl.HistoricalInfo;
import gov.va.med.fw.model.EntityKey;
import gov.va.med.fw.persistent.DAOException;
import gov.va.med.fw.persistent.hibernate.AbstractDAOAction;

// Common Classes

/**
 * @author DNS   CHENJ2
 *
 */
public class FinancialsHistoryDAOImpl extends HistoryDAOImpl implements
		FinancialsHistoryDAO {

	private static final long serialVersionUID = -6539765663679727611L;

    // special filter for financial history
	public static final String FILTER_INCOME_YEAR = "incomeYearFilter";
	public static final String FILTER_PAR_INCOME_YEAR = "incomeYear";

	/**
	 * A default constructor
	 */
	public FinancialsHistoryDAOImpl() {
		super();
	}

	/*
	 * Retrieves the list of history change timestamps for a group of
	 * data, in reverse order.
	 *
	 * @param entityKey Key to the root object, e.g. person
	 * @param incomeYear IncomeYear input to be used as filter parameter value
	 * @see gov.va.med.esr.common.persistent.history.HistoryDAO#getHistoryChangeTimes(gov.va.med.fw.model.EntityKey)
	 */
	public Set getHistoryChangeTimes(EntityKey entityKey, Integer incomeYear) throws DAOException {

		Validate.notNull(incomeYear, "IncomeYear cannot be null");

		Map contextData = new HashMap();
		contextData.put("entityKey", entityKey);
		contextData.put("incomeYear", incomeYear);
		HibernateCallback callback = new AbstractDAOAction(contextData) {
			public Object execute(Session session) throws DAOException {
				session.enableFilter(FILTER_INCOME_YEAR)
				.setParameter(FILTER_PAR_INCOME_YEAR, getContextData().get("incomeYear"));

				return getHistoryChangeTimes((EntityKey) getContextData().get("entityKey"));
			}
		};
		Set ceList = (Set) this.getHibernateTemplate().execute(callback);

		Set financialsCeList = new TreeSet();
		FinancialsChangeEvent fce = null;
		ChangeEvent ce = null;

		for (Iterator i=ceList.iterator();i.hasNext();) {
			ce = (ChangeEvent)i.next();
			fce = new FinancialsChangeEvent(ce.getTimeStamp(), ce.getEntityKey(), incomeYear);
			financialsCeList.add(fce);
		}

		if (logger.isDebugEnabled())
            logger.debug("FinancialsHistoryDAO getchangeTimes: " + financialsCeList);

		return financialsCeList;
	}

	/* Retrieves the current and previous version of the entity
	 *
	 * @param changeEvent provides the key to the root object, and timestamp for history retrieval
	 * @param incomeYear IncomeYear input to be used as filter parameter value
	 * @see gov.va.med.esr.common.persistent.history.HistoryDAO#getHistoryByChangeTime(gov.va.med.esr.service.impl.ChangeEvent)
	 */
	public HistoricalInfo getHistoryByChangeTime(FinancialsChangeEvent fce) throws DAOException
	{
		if (fce != null) {
			Map contextData = new HashMap();
			contextData.put("fce", fce);
			HibernateCallback callback = new AbstractDAOAction(contextData) {
				public Object execute(Session session) throws DAOException {
					FinancialsChangeEvent targetChangeEvent = (FinancialsChangeEvent) getContextData().get("fce");
					session.enableFilter(FILTER_INCOME_YEAR).setParameter(FILTER_PAR_INCOME_YEAR, targetChangeEvent.getIncomeYear());

					return doGetHistoryByChangeTime(targetChangeEvent);
				}
			};
			return (HistoricalInfo) this.getHibernateTemplate().execute(callback);
		}
		return null;
	}

	public IncomeTest findConversionBaseTest(IncomeTest incomeTest) throws DAOException {
		if (incomeTest == null) return null;

		Map contextData = new HashMap();
		contextData.put("baseId", incomeTest.getEntityKey());
		HibernateCallback callback = new AbstractDAOAction(contextData) {
			public Object execute(Session session) {
				Query q = session.getNamedQuery("ivmReversalQuery_findConversionBase");
				q.setMaxResults(1);
				q.setParameter("baseId", ((EntityKey) getContextData().get("baseId")).getKeyValue());
				return q.list();
			}
		};

		Iterator iter = this.getHibernateTemplate().executeFind(callback).iterator();
		IncomeTest test = iter.hasNext() ? (IncomeTest) iter.next() : null;

		if (test != null && logger.isDebugEnabled())
            logger.debug("FinancialsHistoryDAO findconversionBaseTest: " + test);

		return test;
	}

	public List getIncomeTestStatusesForIVMReversal(final Serializable key) throws DAOException {
	   Validate.notNull(key, "Entity key cannot be null");

		Map contextData = new HashMap();
		contextData.put("baseHistoryId", key);
		HibernateCallback callback = new AbstractDAOAction(contextData) {
			public Object execute(Session session) {
				Query q = session.getNamedQuery("IncomeTestStatusQuery_GetHistoryByChangeTime");
				//q.setMaxResults(1);
				q.setParameter("baseHistoryId", key);
				return q.list();
			}
		};
		List statuses = (List) this.getHibernateTemplate().execute(callback);

		if (logger.isDebugEnabled())
            logger.debug("FinancialsHistoryDAO getITstatusForIVMReversal: " + statuses);

		return statuses;

	}

	protected HistoricalInfo doGetHistoryByChangeTime(FinancialsChangeEvent fce) throws DAOException {
		return super.getHistoryByChangeTime(fce);
	}
}