/**
 * 
 */


package gov.va.med.repositories.fpds.filter;


import java.util.Date;
import java.util.List;

import javax.ws.rs.core.MultivaluedMap;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.util.StringUtils;


/**
 * @author vhaislegberb
 *
 * This class uses an XSLT style-sheet to generate the filter from the incoming request.
 */
public class HmpReadRequestXsltFilterBuilder
    extends
        AbstractBaseFilterBuilder
{
    private static final String jsonPathStartParam = "$..[?(";
    private static final String jsonPathEndParam = ")]";


    Document buildRequestParamsDocument( String filter, String domain, String patient, MultivaluedMap<String, String> additionalParams )
    {
        Document filterDocument = DocumentHelper.createDocument( DocumentHelper.createElement( "requestData" ) );
        filterDocument.getRootElement().add( DocumentHelper.createElement( "filterId" ).addText( filter ) );

        String icn = StringUtils.trimTrailingWhitespace( additionalParams.getFirst( ICN ) );
        if ( StringUtils.hasLength( icn ) )
        {
            filterDocument.getRootElement().add( DocumentHelper.createElement( "patientId" ).addText( icn ) );
        }

        filterDocument.getRootElement().add( DocumentHelper.createElement( "additionalParams" ) );
        filterDocument.getRootElement().element( "additionalParams" )
                        .add( DocumentHelper.createElement( "entry" ).addAttribute( "key", "domain" ).addAttribute( "value", domain ) );

        String[] content = null;
        List<String> excludeIds = additionalParams.get( EX_AI );
        List<String> dfnList = additionalParams.get( RS_ID );
        StringBuffer jsonParms = new StringBuffer();
        StringBuffer jsnPath = new StringBuffer();
        ;
        for ( String key : additionalParams.keySet() )
        {
            if ( StringUtils.hasLength( additionalParams.getFirst( key ) ) )
            {
                if ( !key.startsWith( "_" ) && !key.equals( "filterId" ) && !key.equals( "templateId" ) && !key.equals( "nationalId" ) )
                {
                    if ( STANDARD_FILTER_PARAMS.contains( key ) || key.startsWith( "@." ) )
                    {
                        if ( key.equals( "clientRequestInitiationTime" ) )
                        {
                            String clientInitiationTime = ( String )additionalParams.getFirst( key );
                            if ( !StringUtils.hasText( clientInitiationTime ) )
                            {
                                filterDocument.getRootElement().add(
                                                DocumentHelper.createElement( "clientRequestInitiationTime" ).addText(
                                                                DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) ) );
                            }
                            else
                            {
                                filterDocument.getRootElement().add(
                                                DocumentHelper.createElement( "clientRequestInitiationTime" ).addText( clientInitiationTime ) );
                            }
                        }
                        else if ( key.equals( EX_AI ) && StringUtils.hasLength( icn ) )
                        {

                            for ( String excludeId : excludeIds )
                            {

                                content = excludeId.split( SEPARATOR );
                                Element excludedId = DocumentHelper.createElement( "excludedId" );
                                if ( content != null && content.length > 0 )
                                {
                                    if ( content[0] != null && content[0].length() > 0 )
                                    {
                                        excludedId.add( DocumentHelper.createElement( "excludedIdentifier" ).addText( content[0] ) );
                                    }
                                    if ( content[1] != null && content[1].length() > 0 )
                                    {
                                        excludedId.add( DocumentHelper.createElement( "excludedAssigningFacility" ).addText( content[1] ) );
                                    }
                                    if ( content[2] != null && content[2].length() > 0 )
                                    {
                                        excludedId.add( DocumentHelper.createElement( "excludedAssigningAuthority" ).addText( content[2] ) );
                                    }

                                    filterDocument.getRootElement().add( excludedId );
                                }

                            }

                        }
                        else if ( key.equals( RS_ID ) && !StringUtils.hasLength( icn ) )
                        {

                            for ( String dfn : dfnList )
                            {

                                content = dfn.split( SEPARATOR );
                                Element el = DocumentHelper.createElement( "resolvedIdentifier" );
                                if ( content != null && content.length > 0 )
                                {
                                    if ( content[0] != null || content[0].length() > 0 )
                                    {
                                        el.add( DocumentHelper.createElement( "identifier" ).addText( content[0] ) );

                                        if ( content.length > 1 )
                                        {
                                            el.add( DocumentHelper.createElement( "assigningFacility" ).addText( content[1] ) );
                                        }
                                        if ( content.length > 2 )
                                        {
                                            el.add( DocumentHelper.createElement( "assigningAuthority" ).addText( content[2] ) );
                                        }
                                    }

                                }
                                filterDocument.getRootElement().add( el );
                            }

                        }
                        else if ( key.startsWith( "@." ) )
                        {
                            String value = additionalParams.getFirst( key ).trim();

                            if ( StringUtils.hasLength( value ) && value.length() > 1 )
                            {
                                if ( !value.startsWith( "'" ) )
                                {
                                    StringBuffer sb = new StringBuffer();
                                    value = sb.append( "'" ).append( value ).append( "'" ).toString();
                                }

                                jsonParms.append( key ).append( "==" ).append( value );

                                if ( jsonParms.length() > 0 )
                                {
                                    jsonParms.append( " && " );
                                }
                            }
                        }
                        else
                        {
                            filterDocument.getRootElement().add( DocumentHelper.createElement( key ).addText( additionalParams.getFirst( key ) ) );
                        }
                    }
                    else
                    {

                        filterDocument.getRootElement()
                                        .element( "additionalParams" )
                                        .add( DocumentHelper.createElement( "entry" ).addAttribute( "key", key )
                                                        .addAttribute( "value", additionalParams.getFirst( key ) ) );

                    }

                }
            }
        }

        if ( jsonParms.length() > 0 )
        {
            String jsonPrms = jsonParms.toString().trim();
            String path = null;
            if ( jsonPrms.endsWith( "&&" ) )
            {
                path = jsonPrms.substring( 0, jsonPrms.lastIndexOf( " &&" ) );
            }

            if ( StringUtils.hasLength( path ) )
            {
                jsnPath.append( jsonPathStartParam ).append( path.trim() ).append( this.jsonPathEndParam );

                Element jsonPathQuery = DocumentHelper.createElement( "jsonPathQuery" );
                Element jsonPath = DocumentHelper.createElement( "jsonPath" ).addText( jsnPath.toString() );
                jsonPathQuery.add( jsonPath );
                filterDocument.getRootElement().add( jsonPathQuery );
            }

        }

        return filterDocument;
    }
}
