/**
 * 
 */


package gov.va.med.cds.response.strategy;


import gov.va.med.cds.filter.EntryFilterInterface;
import gov.va.med.cds.filter.ParameterMapInterface;
import gov.va.med.cds.filter.QueryParameter;

import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.util.StringUtils;


/**
 * @author DNS   egberb
 * 
 * <p>In some cases, the VistA Generic Stored Procedure responds with multiple records that
 * constitutes a single result from the VistAa system. The result is split between multiple
 * records due to limitation that Cache / MUMPS systems have with regard to string lengths.
 * 
 * <p>This response strategy object assumes that all of the records passed into the format
 * response method are a single record and concatenates the response prior to sending it on. 
 *
 */
public class VistaGenericStoredProcedureSingleResponseStrategy
    implements
        VistaGenericStoredProcedureSingleResponseStrategyInterface
{
    private static final String RESULTS = "results";

    private static final String GENERIC_OBSERVATION = "genericObservation";

    private static final String PATIENT = "patient";

    private static final String IDENTIFIER = "identifier";

    private static final String IDENTITY = "identity";

    private static final String ASSIGNING_FACILITY = "assigningFacility";

    private static final String OBSERVATION_VALUE = "observationValue";

    private static final String DOMAIN = "domain";

    private static final String COMMAND = "command";

    private static final String JSON_TYPE = "json";

    private VistaGenericStoredProcedureJsonResponseStrategy jsonFilterStrategy;

    private VistaGenericStoredProcedureXmlResponseStrategy xmlToJsonStrategy;

    @Resource( name = "linkDomainToResponseTypeOfRPC" )
    private Map<String, String> linkDomainToResponseTypeOfRPC;


    public void setLinkDomainToResponseTypeOfRPC( Map<String, String> linkDomainToResponseTypeOfRPC )
    {
        this.linkDomainToResponseTypeOfRPC = linkDomainToResponseTypeOfRPC;
    }


    /* (non-Javadoc)
     * @see gov.va.med.cds.response.strategy.VistaGenericStoredProcedureResponseStrategyInterface#formatResponse(java.util.List, java.lang.String, java.lang.String)
     */
    @Override
    //Need this in future for cache date conversion requirements
    public Element formatResponse( List<String> records, String patientId, EntryFilterInterface entryFilter, String siteId )
        throws Exception
    {
        StringBuffer sbValue = new StringBuffer();
        for ( String value : records )
        {
            sbValue.append( value );
        }
        String filteredResponse = null;

        ParameterMapInterface parameterMap = entryFilter.getAdditionalParametersMap();
        QueryParameter<?> commandParam = parameterMap.getParameterValue( COMMAND );
        String requestType = ( String )commandParam.getValue();

        QueryParameter<?> domainParam = parameterMap.getParameterValue( "domain" );
        String domain = null;
        String mandatoryResponseTypeForThisDomain = null;
        if ( domainParam != null )
        {
            domain = ( String )domainParam.getValue();

            mandatoryResponseTypeForThisDomain = linkDomainToResponseTypeOfRPC.get( domain.toUpperCase() );
        }

        if ( requestType.equals( JSON_TYPE ) && StringUtils.hasText( entryFilter.getJsonPathQuery() ) )
        {
            filteredResponse = jsonFilterStrategy.processJsonFilter( sbValue.toString(), entryFilter );
        }
        else if ( StringUtils.hasText( domain ) && ( mandatoryResponseTypeForThisDomain != null )
                        && mandatoryResponseTypeForThisDomain.equals( "xml" ) )
        {
            QueryParameter<?> toJsonParam = parameterMap.getParameterValue( "toJson" );

            String convertToJson = ( String )toJsonParam.getValue();

            if ( convertToJson.equals( "true" ) )
            {
                filteredResponse = xmlToJsonStrategy.convertToJson( sbValue.toString() );
            }

        }

        Element results = DocumentHelper.createElement( RESULTS );
        results.addElement( GENERIC_OBSERVATION );
        results.element( GENERIC_OBSERVATION ).addElement( PATIENT ).addElement( IDENTIFIER ).addElement( IDENTITY ).addText( patientId );
        if ( StringUtils.hasLength( siteId ) )
        {
            results.element( GENERIC_OBSERVATION ).element( PATIENT ).element( IDENTIFIER ).addElement( ASSIGNING_FACILITY ).addText( siteId );
        }

        results.element( GENERIC_OBSERVATION ).addElement( OBSERVATION_VALUE )
                        .addText( StringUtils.hasText( filteredResponse ) ? filteredResponse : sbValue.toString() );

        return results;
    }


    @Override
    public Element formatResponse( List<String> records, String patientId, String siteId )
        throws Exception
    {
        return null;
    }


    public void setJsonFilterStrategy( VistaGenericStoredProcedureJsonResponseStrategy jsonFilterStrategy )
    {
        this.jsonFilterStrategy = jsonFilterStrategy;
    }


    public void setXmlToJsonStrategy( VistaGenericStoredProcedureXmlResponseStrategy xmlToJsonStrategy )
    {
        this.xmlToJsonStrategy = xmlToJsonStrategy;
    }
}
