package org.eclipse.osbp.jpa.services.history;

import org.eclipse.osbp.runtime.common.annotations.HistReference;
import org.eclipse.osbp.runtime.common.util.BeanUtils;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.internal.identitymaps.CacheId;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.EmptyRecord;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.QueryRedirector;
import org.eclipse.persistence.queries.ReadObjectQuery;
import org.eclipse.persistence.sessions.Record;
import org.eclipse.persistence.sessions.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Manages references to historized and timedependent entities.
 */
@SuppressWarnings("serial")
public class HistorizedReferenceQueryRedirector implements QueryRedirector {
	protected static Logger logger = LoggerFactory.getLogger(HistorizedReferenceQueryRedirector.class);

	@Override
	public Object invokeQuery(DatabaseQuery query, Record arguments, Session session) {
		if (query instanceof ReadObjectQuery) {
			ReadObjectQuery readQuery = (ReadObjectQuery) query;
			DatabaseMapping mapping = readQuery.getSourceMapping();
			if (mapping != null) {
				ClassDescriptor descriptor = mapping.getDescriptor();
				String att = mapping.getAttributeName();
				Class<?> targetEntity = descriptor.getJavaClass();
				if (!BeanUtils.isAnnotationPresent(targetEntity, att, HistReference.class)) {
					return getCurrentManaged(readQuery, (AbstractRecord) arguments, mapping.getReferenceDescriptor(),
							(AbstractSession) session);
				}
			}
		}
		query.setDoNotRedirect(true);
		return query.execute((AbstractSession) session, (AbstractRecord) arguments);

	}

	private Object getCurrentManaged(ReadObjectQuery readQuery, AbstractRecord arguments,
			ClassDescriptor targetDescriptor, AbstractSession session) {

		HistorizedObjectWrapper wrapper = new HistorizedObjectWrapper(targetDescriptor, null);
		Object objId = null;
		CacheId id = (CacheId) readQuery.getSelectionId();
		if (id != null) {
			Object[] pk = id.getPrimaryKey();
			objId = pk[0];
		} else {
			ClassDescriptor sourceDescriptor = readQuery.getSourceMapping().getDescriptor();
			String refAttName = readQuery.getSourceMapping().getAttributeAccessor().getAttributeName();
			DatabaseMapping id_idMapping = sourceDescriptor.getMappingForAttributeName(refAttName);
			objId = arguments.get(id_idMapping.getFields().get(0));
		}

		ReadObjectQuery rq = new ReadObjectQuery(targetDescriptor.getJavaClass());
		rq.conformResultsInUnitOfWork();

		ExpressionBuilder eb = rq.getExpressionBuilder();
		Expression exp = eb.get(wrapper.getIdAttName()).get(wrapper.getId_IdAttName()).equal(objId)
				.and(eb.get(wrapper.getCurrentHistAttName()).equal(true));
		rq.setSelectionCriteria(exp);
		rq.setDoNotRedirect(true);
		return rq.execute(session, EmptyRecord.getEmptyRecord());
	}
}
