/**
 * 
 */


package gov.va.med.cds.request;


import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.junit.Assert.fail;
import gov.va.med.cds.clinicaldata.vhim400.ClinicalDataResponseInterface;
import gov.va.med.cds.exception.AbstractCdsBaseException;
import gov.va.med.cds.exception.ErrorCodeEnum;
import gov.va.med.cds.exceptionframework.ExceptionHandler;
import gov.va.med.cds.exceptionframework.ExceptionInfo;
import gov.va.med.cds.exceptionframework.ExceptionLoggerInterface;
import gov.va.med.cds.filter.FilterValidatorInterface;
import gov.va.med.cds.internal.ClinicalDataServiceSynchronousInternalInterface;
import gov.va.med.cds.junit.runners.Suite;
import gov.va.med.cds.junit.runners.SuiteAwareRunner;
import gov.va.med.cds.persistence.PersistenceException;
import gov.va.med.cds.response.ResponseAggregatorInterface;
import gov.va.med.cds.response.sequencer.ResponseSequencerInterface;
import gov.va.med.cds.template.TemplateHelperInterface;

import java.util.ArrayList;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;


/**
 * @author vhaislegberb
 *
 */
@RunWith( SuiteAwareRunner.class )
public class TemplateRequestProcessorTest
{
    private static String FILTER_ID = "filterId";
    private static String REQUEST_ID = "requestId";
    private static String TEMPLATE_ID = "templateId";
    private static String FILTER_XML_REQUEST = "filterXmlRequest";
    private static String CDS_APP_NAME = "CDS 3.6";

    private static Document WRITE_RESPONSE_DOCUMENT = DocumentHelper.createDocument();

    private FilterValidatorInterface filterManager;
    private ClinicalDataServiceSynchronousInternalInterface delegatingClinicalDataServiceSynchronousInternal;
    private TemplateHelperInterface templateHelper;

    private ResponseAggregatorInterface responseAggregator;
    private ResponseSequencerInterface responseSequencer;

    private ExceptionLoggerInterface guaranteedLogger;
    private ErrorSectionHelperInterface errorSectionHelper;
    private ClinicalDataResponseInterface clinicalDataResponse;


    @Before
    @Suite( groups = { "checkintest" } )
    public void beforeTemplateRequestProcessorTestClassSetUp( )
    {
        filterManager = createNiceMock( FilterValidatorInterface.class );
        delegatingClinicalDataServiceSynchronousInternal = createNiceMock( ClinicalDataServiceSynchronousInternalInterface.class );
        templateHelper = createNiceMock( TemplateHelperInterface.class );

        responseAggregator = createNiceMock( ResponseAggregatorInterface.class );
        responseSequencer = createNiceMock( ResponseSequencerInterface.class );

        guaranteedLogger = createNiceMock( ExceptionLoggerInterface.class );
        errorSectionHelper = createNiceMock( ErrorSectionHelperInterface.class );
        clinicalDataResponse = createNiceMock( ClinicalDataResponseInterface.class );
        ExceptionHandler.setGuaranteedLogger( guaranteedLogger );
        ExceptionHandler.setTemplateHelper( templateHelper );
        ExceptionHandler.setClinicalDataResponse( clinicalDataResponse );
    }


    @Test
    @Suite( groups = { "checkintest" } )
    public void tesReadClinicalData( )
    {
        try
        {
            List<Document> responses = new ArrayList<Document>();
            expect( delegatingClinicalDataServiceSynchronousInternal.readClinicalData( FILTER_XML_REQUEST, FILTER_ID, TEMPLATE_ID, REQUEST_ID ) )
                            .andReturn( responses );

            Document document = DocumentHelper.createDocument();
            expect( responseAggregator.aggregateResponses( responses ) ).andReturn( document );
            expect( responseSequencer.sequence( TEMPLATE_ID, document, false ) ).andReturn( document );

            expect( templateHelper.getResponseAggregator( TEMPLATE_ID ) ).andReturn( responseAggregator );
            expect( templateHelper.getResponseSequencer( TEMPLATE_ID ) ).andReturn( responseSequencer );

            replay( filterManager, delegatingClinicalDataServiceSynchronousInternal, responseAggregator, responseSequencer, templateHelper );

            TemplateRequestProcessor requestProcessor = new TemplateRequestProcessor();
            requestProcessor.setFilterManager( filterManager );
            requestProcessor.setDelegatingClinicalDataServiceSynchronousInternal( delegatingClinicalDataServiceSynchronousInternal );
            requestProcessor.setTemplateHelper( templateHelper );

            requestProcessor.readClinicalData( TEMPLATE_ID, FILTER_XML_REQUEST, FILTER_ID, REQUEST_ID );
        }
        catch ( Exception e )
        {
            fail();
        }
    }


    @Test
    @Suite( groups = { "checkintest" } )
    public void testReadClinicalDataRuntimeException( )
    {
        try
        {
            RuntimeException runtimeException = new IllegalArgumentException( "My bogus runtime exception." );
            TemplateRequestProcessor requestProcessor = new TemplateRequestProcessor();

            expect( delegatingClinicalDataServiceSynchronousInternal.readClinicalData( FILTER_XML_REQUEST, FILTER_ID, TEMPLATE_ID, REQUEST_ID ) )
                            .andThrow( runtimeException );
            expect( templateHelper.getApplicationName(TEMPLATE_ID)).andReturn("CDS 1.0");
            expect( templateHelper.getErrorSectionHelper( TEMPLATE_ID ) ).andReturn( errorSectionHelper );
            expect(errorSectionHelper.buildErrorSection( EasyMock.isA( Document.class ), EasyMock.isA( ExceptionInfo.class ),
                                            EasyMock.eq( REQUEST_ID ) ) ).andReturn( DocumentHelper.createDocument() );
            expect( clinicalDataResponse.buildEmptyClinicalDocument( TEMPLATE_ID, REQUEST_ID ) ).andReturn( DocumentHelper.createDocument() );

            replay( delegatingClinicalDataServiceSynchronousInternal, templateHelper, errorSectionHelper, guaranteedLogger, clinicalDataResponse );

            requestProcessor.setDelegatingClinicalDataServiceSynchronousInternal( delegatingClinicalDataServiceSynchronousInternal );
            requestProcessor.setTemplateHelper(templateHelper);

            requestProcessor.readClinicalData( TEMPLATE_ID, FILTER_XML_REQUEST, FILTER_ID, REQUEST_ID );
        }
        catch ( RuntimeException re )
        {
            fail();
        }
    }


    @Test
    @Suite( groups = { "checkintest" } )
    public void testReadClinicalDataCdsBaseExceptionFatal( )
    {
        try
        {
            AbstractCdsBaseException cdsBaseException = new PersistenceException( ErrorCodeEnum.READ_REQUEST_ALL_DATASOURCES_FAILED );
            TemplateRequestProcessor requestProcessor = new TemplateRequestProcessor();

            expect( delegatingClinicalDataServiceSynchronousInternal.readClinicalData( FILTER_XML_REQUEST, FILTER_ID, TEMPLATE_ID, REQUEST_ID ) )
                            .andThrow( cdsBaseException );
            expect( templateHelper.getApplicationName(TEMPLATE_ID)).andReturn("CDS 1.0");
            expect( templateHelper.getErrorSectionHelper( TEMPLATE_ID ) ).andReturn( errorSectionHelper );
            expect(
                            errorSectionHelper.buildErrorSection( EasyMock.isA( Document.class ), EasyMock.isA( ExceptionInfo.class ),
                                            EasyMock.eq( REQUEST_ID ) ) ).andReturn( DocumentHelper.createDocument() );
            expect( clinicalDataResponse.buildEmptyClinicalDocument( TEMPLATE_ID, REQUEST_ID ) ).andReturn( DocumentHelper.createDocument() );

            replay( delegatingClinicalDataServiceSynchronousInternal, templateHelper, errorSectionHelper, guaranteedLogger, clinicalDataResponse );

            requestProcessor.setDelegatingClinicalDataServiceSynchronousInternal( delegatingClinicalDataServiceSynchronousInternal );
            requestProcessor.setTemplateHelper(templateHelper);
            requestProcessor.readClinicalData( TEMPLATE_ID, FILTER_XML_REQUEST, FILTER_ID, REQUEST_ID );
        }
        catch ( RuntimeException re )
        {
            fail();
        }
    }


    @Test
    @Suite( groups = { "checkintest" } )
    public void testCreateClinicalData( )
    {
        try
        {
            String request = "createRequest";
            expect( delegatingClinicalDataServiceSynchronousInternal.createClinicalData( request, TEMPLATE_ID, REQUEST_ID ) ).andReturn(
                            WRITE_RESPONSE_DOCUMENT );
            expect( templateHelper.getApplicationName(TEMPLATE_ID)).andReturn("CDS 1.0");
            replay( delegatingClinicalDataServiceSynchronousInternal, templateHelper );

            TemplateRequestProcessor requestProcessor = new TemplateRequestProcessor();
            requestProcessor.setTemplateHelper(templateHelper);
            requestProcessor.createClinicalData( request, TEMPLATE_ID, REQUEST_ID );
        }
        catch ( Exception e )
        {
            fail();
        }
    }


    @Test
    @Suite( groups = { "checkintest" } )
    public void testCreateOrUpdateClinicalData( )
    {
        try
        {
            String request = "createOrUpdateRequest";
            expect( delegatingClinicalDataServiceSynchronousInternal.createClinicalData( request, TEMPLATE_ID, REQUEST_ID ) ).andReturn(
                            WRITE_RESPONSE_DOCUMENT );
            expect( templateHelper.getApplicationName(TEMPLATE_ID)).andReturn("CDS 1.0");
            replay( delegatingClinicalDataServiceSynchronousInternal, templateHelper );

            TemplateRequestProcessor requestProcessor = new TemplateRequestProcessor();
            requestProcessor.setTemplateHelper(templateHelper);
            requestProcessor.createOrUpdateClinicalData( request, TEMPLATE_ID, REQUEST_ID );
        }
        catch ( Exception e )
        {
            fail();
        }
    }


    @Test
    @Suite( groups = { "checkintest" } )
    public void testUpdateClinicalData( )
    {
        try
        {
            String request = "updateRequest";
            expect( delegatingClinicalDataServiceSynchronousInternal.updateClinicalData( request, TEMPLATE_ID, REQUEST_ID ) ).andReturn(
                            WRITE_RESPONSE_DOCUMENT );
            expect( templateHelper.getApplicationName(TEMPLATE_ID)).andReturn("CDS 1.0");
            replay( delegatingClinicalDataServiceSynchronousInternal, templateHelper );

            TemplateRequestProcessor requestProcessor = new TemplateRequestProcessor();
            requestProcessor.setTemplateHelper(templateHelper);
            requestProcessor.updateClinicalData( request, TEMPLATE_ID, REQUEST_ID );
        }
        catch ( Exception e )
        {
            fail();
        }
    }


    @Test
    @Suite( groups = { "checkintest" } )
    public void testAppendClinicalData( )
    {
        try
        {
            String request = "appendRequest";
            expect( delegatingClinicalDataServiceSynchronousInternal.appendClinicalData( request, TEMPLATE_ID, REQUEST_ID ) ).andReturn(
                            WRITE_RESPONSE_DOCUMENT );
            expect( templateHelper.getApplicationName(TEMPLATE_ID)).andReturn("CDS 1.0");
            replay( delegatingClinicalDataServiceSynchronousInternal, templateHelper );

            TemplateRequestProcessor requestProcessor = new TemplateRequestProcessor();
            requestProcessor.setTemplateHelper(templateHelper);
            requestProcessor.appendClinicalData( request, TEMPLATE_ID, REQUEST_ID );
        }
        catch ( Exception e )
        {
            fail();
        }
    }


    @Test
    @Suite( groups = { "checkintest" } )
    public void testDeleteClinicalData( )
    {
        try
        {
            String request = "deleteRequest";
            expect( delegatingClinicalDataServiceSynchronousInternal.deleteClinicalData( request, TEMPLATE_ID, REQUEST_ID ) ).andReturn(
                            WRITE_RESPONSE_DOCUMENT );
            expect( templateHelper.getApplicationName(TEMPLATE_ID)).andReturn("CDS 1.0");
            replay( delegatingClinicalDataServiceSynchronousInternal, templateHelper );

            TemplateRequestProcessor requestProcessor = new TemplateRequestProcessor();
            requestProcessor.setTemplateHelper(templateHelper);
            requestProcessor.deleteClinicalData( request, TEMPLATE_ID, REQUEST_ID );
        }
        catch ( Exception e )
        {
            fail();
        }
    }
}
