/**
 * 
 */


package gov.va.med.cds.filter;


import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.dom4j.Element;

import gov.va.med.cds.common.person.correlation.PersonIdentifierInterface;


/**
 * @author DNS   egberb
 *
 */
public class Filter100QueryMetadata
    extends
        FilterQueryMetadata implements ParameterMapInterface
{

    private Map<String, QueryParameter<?>> queryParameterMap;


    protected Filter100QueryMetadata( Element entryFilter, String templateId, String requestId )
    {
        super( entryFilter, templateId, requestId );
    }
    
    @Override 
    public ParameterMapInterface getAdditionalParametersMap( )
    {
        return this;
    }

    @SuppressWarnings( "unchecked" )
    @Override
    protected void extractAdditionalParameters( Element entryFilter )
    {
        Element additionalParametersElement = entryFilter.element( "otherQueryParameters" );
        if ( additionalParametersElement != null )
        {
            this.queryParameterMap = new HashMap<String, QueryParameter<?>>();
            QueryParameter<?> queryParameter = null;
            List<Element> additionalParametersList = ( List<Element> )additionalParametersElement.elements();
            for ( Element additionalParameter : additionalParametersList )
            {
                String paramName = ( additionalParameter.attributeValue( "name" ) != null ) ? additionalParameter.attributeValue( "name" )
                                : additionalParameter.getName();
                String paramType = ( additionalParameter.attributeValue( "type" ) != null ) ? additionalParameter.attributeValue( "type" ) : "string";

                if ( "dateRange".equals( paramType ) )
                {
                    queryParameter = extractDateRangeParameter( additionalParameter );
                }
                else if ( "list".equals( paramType ) )
                {
                    queryParameter = extractListTypeParameter( additionalParameter.elements() );
                    queryParameter.setName( paramName );
                    queryParameter.setType( paramType );
                }
                else
                {
                	
                    queryParameter = new QueryParameter<String>();
                    queryParameter.setName( paramName );
                    String paramValue = additionalParameter.elementTextTrim( "value" );
                    ( ( QueryParameter<String> )queryParameter ).setValue( paramValue );
                }
                queryParameter.setType( paramType );
                queryParameterMap.put( paramName, queryParameter );
            }
        }
    }


    private QueryParameter<Map<String, Calendar>> extractDateRangeParameter( Element additionalParameter )
    {
        QueryParameter<Map<String, Calendar>> queryParameter = null;
        @SuppressWarnings( "unchecked" )
        List<Element> elements = ( List<Element> )additionalParameter.elements();

        if ( elements != null && elements.size() > 0 && elements.size() < 3 )
        {
            Element beginDateElement = elements.get( 0 );
            Element endDateElement = elements.get( 1 );
            Map<String, Calendar> valueMap = new HashMap<String, Calendar>();
            queryParameter = new QueryParameter<Map<String, Calendar>>();
            queryParameter.setName( additionalParameter.attributeValue( "name" ) );
            queryParameter.setValue( valueMap );

            Calendar c = null;

            if ( beginDateElement != null )
            {
                c = extractCalendar( beginDateElement, -1 );
                valueMap.put( "begin", c );
            }

            if ( endDateElement != null )
            {
                c = extractCalendar( endDateElement, 1 );
                valueMap.put( "end", c );
            }
        }

        return queryParameter;
    }


    private Calendar extractCalendar( Element dateElement, int dayOffset )
    {
        DateFormat xmlDateFormat = new SimpleDateFormat( XS_DATE_FORMAT_PATTERN );
        Calendar c = null;

        if ( dateElement != null )
        {
            String dateString = dateElement.getTextTrim();

            c = extractDate( dateString, xmlDateFormat );
            c.set( Calendar.HOUR_OF_DAY, 0 );
            c.set( Calendar.MINUTE, 0 );
            c.set( Calendar.SECOND, 0 );
            c.add( Calendar.DATE, dayOffset );
        }

        return c;
    }


    private QueryParameter<List<String>> extractListTypeParameter( List<Element> valueElements )
    {
        List<String> values = new ArrayList<String>();
        QueryParameter<List<String>> queryParameter = new QueryParameter<List<String>>();
        queryParameter.setValue( values );

        for ( Element valueElement : valueElements )
        {
            values.add( valueElement.getTextTrim() );
        }
        return queryParameter;
    }


    @Override
    public Set<String> getFilterParameterNames( )
    {
        Set<String> parameterNames = new HashSet<String>();
        if(queryParameterMap != null && queryParameterMap.size() > 0)
        {
            parameterNames.addAll(queryParameterMap.keySet());
        }
        return parameterNames;
    }


    @Override
    public QueryParameter<?> getParameterValue( String parameterName )
    {
        return this.queryParameterMap.get( parameterName );
    }
}
