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

import java.util.LinkedHashMap;
import java.util.Map;

import gov.va.med.cds.exception.ErrorCodeEnum;
import gov.va.med.cds.filter.EntryFilterInterface;
import gov.va.med.cds.filter.ParameterMapInterface;
import gov.va.med.cds.filter.QueryParameter;
import gov.va.med.cds.persistence.PersistenceException;

/**
 * @author vhaislegberb
 *
 * Extracts parameter names and values from the filter in accordance with Legacy CDS 2.x - 3.3 expectations.
 * 
 */
public class LegacyFilterParameterExtractor
    implements
        FilterParameterExtractorInterface
{
    
    /*
     * (non-Javadoc)
     * @see gov.va.med.cds.persistence.hibernate.FilterParameterExtractorInterface#extractNamedParameters(java.util.Map, gov.va.med.cds.filter.EntryFilterInterface)
     */
    @Override
    public Map<String, Object> extractNamedParameters( Map<String, QueryParameterTransformerInterface> parameterTransformerMap, EntryFilterInterface entryFilter )
    {
        Map<String, Object> params = new LinkedHashMap<String, Object>();
        
        if ( entryFilter.hasRecordIdentifiers() ) // record identifiers query
        {
            QueryParameterTransformerInterface parameterTransformer = parameterTransformerMap.get( PN_RECORD_IDENTIFIERS );
            if(parameterTransformer != null)
            {
                parameterTransformer.transformAndSetParameter( PN_RECORD_IDENTIFIERS, entryFilter.getRecordIdentifiers(), params );
            }
            else
            {
                params.put( PN_RECORD_IDENTIFIERS, entryFilter.getRecordIdentifiers() );
            }
        }
        else if ( entryFilter.useDates() ) // person ids and date query.
        {
            // dates require a parameter transformer to facilitate querying. transformer must be present
            QueryParameterTransformerInterface startParamTransformer = parameterTransformerMap.get(PN_START_DATE);
            if( startParamTransformer != null )
            {
                startParamTransformer.transformAndSetParameter( PN_START_DATE, entryFilter.getStartDate(), params );
            }
            else
            {
                throw new PersistenceException( ErrorCodeEnum.PARAMETER_TRANSFORMER_EXPECTED_ERROR, PN_START_DATE );
            }
            
            QueryParameterTransformerInterface endParamTransformer = parameterTransformerMap.get(PN_END_DATE);
            if( endParamTransformer != null )
            {
                endParamTransformer.transformAndSetParameter( PN_END_DATE, entryFilter.getEndDate(), params );
            }
            else
            {
                throw new PersistenceException( ErrorCodeEnum.PARAMETER_TRANSFORMER_EXPECTED_ERROR, PN_END_DATE );
            }
            
        }
        
        ParameterMapInterface parameterMap = entryFilter.getAdditionalParametersMap();
        if ( parameterMap != null )
        {
            for ( String filterParameterName : parameterMap.getFilterParameterNames() )
            {
                QueryParameter<?> queryParameter = parameterMap.getParameterValue( filterParameterName );
                if ( queryParameter == null )
                {
                    throw new PersistenceException( ErrorCodeEnum.INVALID_OR_UNEXPECTED_QUERY_PARAM, filterParameterName );
                }

                Object parameterValue = queryParameter.getValue();
                
                if(parameterValue instanceof Map)
                {
                    @SuppressWarnings( "unchecked" )
                    Map<String, Object> map = (Map<String, Object>)parameterValue;
                    for(String key : map.keySet())
                    {
                        params.put( key, map.get( key ) );
                    }
                }
                else
                {
                    params.put( filterParameterName, parameterValue );
                }
            }
        }
        
        if ( entryFilter.containsXpathFilterExpression() )
        {
            params.put( PN_XPATH_FILTER_EXPRESSION, entryFilter.getXpathFilterExpression() );
            params.put( PN_XPATH_FILTER_EXPRESSION_NAMESPACE, entryFilter.getXpathFilterExpressionNamespace());
        }

        return params;
    }

}
