/**
 * 
 */
package gov.va.med.cds.persistence.hibernate;

import gov.va.med.cds.persistence.hibernate.common.AbstractPointInTimeUserType;
import gov.va.med.cds.persistence.hibernate.common.PointInTime;

import java.util.Collection;
import java.util.Map;
import java.util.Properties;

import org.hibernate.Query;
import org.hibernate.TypeHelper;
import org.hibernate.internal.TypeLocatorImpl;
import org.hibernate.type.TypeResolver;

/**
 * @author DNS   egberb
 *
 */
public class DefaultQueryParameterBinder
    implements
        QueryParameterBinderInterface
{
    
    /* (non-Javadoc)
     * @see gov.va.med.cds.persistence.hibernate.QueryParameterBinderInterface#bindQueryParameters(org.hibernate.Query, java.util.Map)
     */
    @Override
    public Query bindQueryParameters( Query query, Map<String, Object> queryParametersMap, Class<?> pointInTimeUserType )
    {
        for ( String parameterName : queryParametersMap.keySet() )
        {
            Object parameterValue = queryParametersMap.get( parameterName );
            if ( parameterValue instanceof PointInTime || parameterValue instanceof gov.va.med.cds.template.generated.basedatatypes.PointInTime)
            {
                Properties userTypeProperties = new Properties();
                userTypeProperties.setProperty( AbstractPointInTimeUserType.SET_VALUES, AbstractPointInTimeUserType.SV_NUMERIC_ONLY );
                TypeHelper typeHelper = new TypeLocatorImpl(new TypeResolver());
                //query.setParameter( parameterName, parameterValue, Hibernate.custom( pointInTimeUserType, userTypeProperties ) );
                query.setParameter( parameterName, parameterValue, typeHelper.custom( pointInTimeUserType, userTypeProperties ) );
            }
            else if ( parameterValue instanceof Map<?, ?>) //added support for complex type optional parameters
            {   
                @SuppressWarnings("unchecked")
				Map<String, Object> complexParam = ( Map<String, Object> )parameterValue;
                bindQueryParameters( query, complexParam, pointInTimeUserType );
            }
            else if ( parameterValue instanceof Collection )
            {
                query.setParameterList( parameterName, ( Collection<?> )parameterValue );
            }
            else
            {
                query.setParameter( parameterName, parameterValue );
            }
        }
        
        return query;
    }
    
}
