

package gov.va.med.cds.ejb;


import gov.va.med.cds.audit.VhimRequestAuditLoggerInterface;
import gov.va.med.cds.client.ClinicalDataServiceInterface;
import gov.va.med.cds.clinicaldata.vhim400.ClinicalDataResponseInterface;
import gov.va.med.cds.config.BeanConstantsInterface;
import gov.va.med.cds.exception.ErrorCodeEnum;
import gov.va.med.cds.exception.RuntimeMDBOnMessageException;
import gov.va.med.cds.response.util.ResponseErrorSectionExtractor;

import java.nio.ByteBuffer;

import javax.annotation.PostConstruct;
import javax.jms.BytesMessage;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.NamingException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.jndi.JndiTemplate;
/**
 * 
 * parent abstract bean for clinical write operations - currently unused
 * @author DNS   talbom
 *
 */

public abstract class AbstractCdsVhimClinicalMdb implements MessageListener
{
   
    protected final Log logger = LogFactory.getLog(getClass());
    
    private static String TEMPLATE_ID = "TEMPLATE_ID";
    private static String REQUEST_ID = "REQUEST_ID";
    private static String NO_REQUEST_ID_PROVIDED = "NO_REQUEST_ID";

    
    private JndiTemplate jndiTemplate = new JndiTemplate();
    private Boolean persistOriginalMessage;
    protected ClinicalDataServiceInterface cdsService;
    private ResponseErrorSectionExtractor responseErrorSectionExtractor;
    private VhimRequestAuditLoggerInterface vhimRequestAuditLogger;
    private JmsTemplate responseJmsTemplate;
    private String cdsAppName;
    private ClinicalDataResponseInterface clinicalDataResponse;

    private BeanFactory beanFactory;

   @PostConstruct
    protected void onEjbCreate( )
    {
        try
        {
        	beanFactory = new ClassPathXmlApplicationContext("classpath:gov/va/med/cds/ejb/config/weblogicApplicationContext.xml");
        	persistOriginalMessage = ( Boolean )safeGetEnvironmentEntry( "java:comp/env/ejb/vhim400/defaultPersistOriginalMessage", Boolean.class, Boolean.TRUE );
            vhimRequestAuditLogger = ( VhimRequestAuditLoggerInterface )beanFactory.getBean( BeanConstantsInterface.VHIM_REQUEST_AUDIT_LOGGER );
            cdsService = ( ClinicalDataServiceInterface )beanFactory.getBean( BeanConstantsInterface.CLINICAL_DATA_SERVICE_SYNCHRONOUS_BEAN_ID );
            responseErrorSectionExtractor = ( ResponseErrorSectionExtractor )beanFactory.getBean( "responseErrorSectionExtractor" );
            responseJmsTemplate = (JmsTemplate)beanFactory.getBean(BeanConstantsInterface.VHIM_ASYNC_RESPONSE_JMS_TEMPLATE);
            clinicalDataResponse = (ClinicalDataResponseInterface)beanFactory.getBean("clinicalDataResponse");
        }
        catch ( Exception e )
        {
            
        }
    }
    
    @SuppressWarnings( "unchecked" )
    protected Object safeGetEnvironmentEntry(String name, @SuppressWarnings( "rawtypes" ) Class type, Object defaultValue)
    {
        Object environmentEntry = defaultValue;
        try {
            environmentEntry =  this.jndiTemplate.lookup( name, type );
        } catch (NamingException ne)
        {
            logger.warn( String.format( "Error initializing CDS VIM MDB. Error Reason: %s", ne.getMessage() ), ne );
        }
        
        return environmentEntry;
    }


    /* (non-Javadoc)
     * @see javax.jms.MessageListener#onMessage(javax.jms.Message)
     */
    public void onMessage( Message message )
    {
        String templateId = null;
        String requestId = null;
        String response = null;
        
        try
        {
            byte[] messageBytes = null;
            
            templateId = message.getStringProperty( TEMPLATE_ID );
            requestId = message.getStringProperty( REQUEST_ID );

            if ( message instanceof BytesMessage )
            {
                BytesMessage bytesMsg = ( BytesMessage )message;
                int msgLength = ( int )bytesMsg.getBodyLength();
                messageBytes = new byte[msgLength];
                bytesMsg.readBytes( messageBytes );
            }
            else if ( message instanceof TextMessage )
            {
                TextMessage textMsg = ( TextMessage )message;
                messageBytes = textMsg.getText().getBytes();
            }

            ByteBuffer messageBuffer = ByteBuffer.wrap( messageBytes );
            String vhimPayload = new String( messageBuffer.array() );

            if ( persistOriginalMessage )
            {
                this.vhimRequestAuditLogger.auditWriteRequest( templateId, vhimPayload, requestId );
            }

            response = doClinicalOperation( vhimPayload, templateId, requestId );

            responseErrorSectionExtractor.checkForErrorsInResponse( response );
        }
        catch ( Exception e )
        {
            String msg = "Exception occured while processing CDS write request message.";
            logger.error( gov.va.med.cds.util.LogMessageUtil.buildMessage( null, requestId, cdsAppName, msg ), e );
            
            if(response == null)
            {
                templateId = (templateId != null) ? templateId : "CdsResponse400";
                requestId = (requestId != null) ? requestId : NO_REQUEST_ID_PROVIDED;
                response = clinicalDataResponse.buildEmptyClinicalDocument( templateId, requestId ).asXML();
            }
            
            throw new RuntimeMDBOnMessageException( ErrorCodeEnum.MDB_ON_MESSAGE_JMS_EXCEPTION, e, msg );
        }
        finally {
            try {
                final String responseMessage = response;
                final String responseTemplateId = templateId;
                final String responseRequestId = requestId;
                
                // if there has been a 'Reply-To' queue associated with this request,
                // use it to supply the response.
                Destination destination = message.getJMSReplyTo();
                if( destination == null )
                {
                    // if no 'Reply-To' destination is supplied, use the default destination.
                    destination = responseJmsTemplate.getDefaultDestination();
                }
                
                if( responseMessage != null ) 
                {
                    responseJmsTemplate.send(destination,  new MessageCreator()
                    {
                        
                        @Override
                        public Message createMessage( Session session )
                            throws JMSException
                        {
                            Message message = session.createTextMessage( responseMessage );
                            message.setStringProperty( TEMPLATE_ID, responseTemplateId );
                            message.setStringProperty( REQUEST_ID, responseRequestId );
                            return message;
                        }
                    });
                }
            } catch (Exception ex2) {
                String errMsg = "Failed to publish response message to JMS destination.";
                logger.error( gov.va.med.cds.util.LogMessageUtil.buildMessage( null, requestId, cdsAppName, errMsg ), ex2 );
                
                throw new RuntimeMDBOnMessageException( ErrorCodeEnum.MDB_ON_MESSAGE_JMS_EXCEPTION, ex2, errMsg );
            }
        }
    }
    
    /**
     * Template method to override to invoke the appropriate CdS operation.
     * @param vhimPayload The VHIM template XML.
     * @param templateId The ID of the template.
     * @param requestId The request identifier.
     * @return The response XML template.
     */
    protected abstract String doClinicalOperation(String vhimPayload, String templateId, String requestId);
    
    public void setPersistOriginalMessage( Boolean persistOriginalMessage )
    {
        this.persistOriginalMessage = persistOriginalMessage;
    }


    public void setCdsService( ClinicalDataServiceInterface cdsService )
    {
        this.cdsService = cdsService;
    }


    public void setResponseErrorSectionExtractor( ResponseErrorSectionExtractor responseErrorSectionExtractor )
    {
        this.responseErrorSectionExtractor = responseErrorSectionExtractor;
    }

    public void setVhimRequestAuditLogger( VhimRequestAuditLoggerInterface vhimRequestAuditLogger )
    {
        this.vhimRequestAuditLogger = vhimRequestAuditLogger;
    }
    
    public void setClinicalDataResponse( ClinicalDataResponseInterface clinicalDataResponse )
    {
        this.clinicalDataResponse = clinicalDataResponse;
    }
    
    public void setResponseJmsTemplate( JmsTemplate responseJmsTemplate )
    {
        this.responseJmsTemplate = responseJmsTemplate;
    }
    
}


