/**
 * 
 */


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


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

import javax.annotation.Resource;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriInfo;

import org.apache.cxf.binding.xml.XMLFault;
import org.apache.cxf.feature.transform.XSLTOutInterceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.jaxrs.impl.UriInfoImpl;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.springframework.util.StringUtils;


/**
 * @author DNS   egberb
 *
 */
public class RoutingXsltOutInterceptor
    extends
        AbstractPhaseInterceptor<Message>
{

    private Map<String, XSLTOutInterceptor> outInterceptors = null;
    private static final String DEFAULT_RESPONSE_TYPE = "json";
    private static final String XML_REQUEST = "<clinicaldata:ClinicalData";
    private static final String XML_RESPONSE_TYPE = "xml";

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


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


    public RoutingXsltOutInterceptor( )
    {
        super( Phase.PRE_STREAM );
    }


    @Override
    public void handleMessage( Message message )
        throws Fault
    {

        Message inMessage = message.getExchange().getInMessage();
        UriInfo uriInfo = null;
        String pathInfo = null;
        String _type = null;
        String domainName = null;
        try
        {
            //is this an isAlive test
            pathInfo = ( String )inMessage.get( Message.PATH_INFO );
            if ( pathInfo != null && pathInfo.endsWith( "isAlive" ) )
            {
                return;
            }

            //is this a wadl check
            String queryValue = ( String )inMessage.get( Message.QUERY_STRING );
            if ( "_wadl".equals( queryValue ) )
            {
                return;
            }

            List msgContents = inMessage.getContent( List.class );
            String responseType = null;
            int uriInfoPosition = msgContents.size() - 1;

            if ( msgContents.get( uriInfoPosition ) instanceof UriInfoImpl )
            {
                uriInfo = ( UriInfo )msgContents.get( uriInfoPosition );
                MultivaluedMap<String, String> queryParameters = uriInfo.getQueryParameters();
                List<String> typeList = ( List<String> )queryParameters.get( "_type" );

                MultivaluedMap<String, String> pathParameters = uriInfo.getPathParameters();
                List<String> domainList = ( List<String> )pathParameters.get( "domain" );

                if ( domainList != null )
                {
                    domainName = ( String )domainList.get( 0 );
                }

                if ( typeList != null )
                {
                    responseType = ( String )typeList.get( 0 );
                }

                //response type not null
                if ( StringUtils.hasText( responseType ) )
                {
                    _type = responseType;

                    // If the response type is anything other than XML or JSOn then set the response type to default JSON
                    if ( !_type.equals( XML_RESPONSE_TYPE ) && !_type.equals( DEFAULT_RESPONSE_TYPE ) )
                    {
                        _type = DEFAULT_RESPONSE_TYPE;
                    }
                }

                //write and delete processing with null response type
                if ( !StringUtils.hasText( responseType ) )
                {
                    if ( pathInfo.contains( XML_REQUEST ) )
                    {
                        responseType = XML_RESPONSE_TYPE;
                    }
                    else if ( pathInfo.contains( "{" ) )
                    {
                        responseType = DEFAULT_RESPONSE_TYPE;
                    }
                    _type = responseType;
                }

                //read request processing with null response type//
                if ( !StringUtils.hasText( responseType ) && !StringUtils.hasText( _type ) )
                {
                    _type = DEFAULT_RESPONSE_TYPE;
                }

            }

        }
        catch ( Exception e )
        {
            throw new XMLFault( "UriInfo object is expected to be part of the in message content list." );
        }

        XSLTOutInterceptor outInterceptor = null;

        boolean processMessage = true;

        if ( StringUtils.hasText( domainName ) )
        {
            String mandatoryResponseType = null;
            if ( null != linkDomainToResponseTypeOfRPC )
            {
                mandatoryResponseType = linkDomainToResponseTypeOfRPC.get( domainName.toUpperCase() );
            }

            if ( mandatoryResponseType != null )
            {
                if ( mandatoryResponseType.equalsIgnoreCase( _type ) )
                {
                    processMessage = false;
                }
            }
        }

        // If the response is already in XML format then no need to process it again
        if ( !StringUtils.hasText( domainName ) || processMessage )
        {
            if ( ( outInterceptor = this.outInterceptors.get( _type ) ) != null )
            {
                outInterceptor.handleMessage( message );
            }
        }
    }


    public void setOutInterceptors( Map<String, String> outInterceptors )
    {
        this.outInterceptors = new HashMap<String, XSLTOutInterceptor>();

        for ( String key : outInterceptors.keySet() )
        {
            this.outInterceptors.put( key, new XSLTOutInterceptor( outInterceptors.get( key ) ) );
        }
    }


    protected void setOutInterceptorsInternal( Map<String, XSLTOutInterceptor> outInterceptors )
    {
        this.outInterceptors = outInterceptors;
    }

}
