

package gov.va.med.cds.audit;


import gov.va.med.cds.audit.persistence.AuditLogPersistenceManagerInterface;
import gov.va.med.cds.audit.persistence.CdsAuditClobStore;
import gov.va.med.cds.audit.persistence.CdsAuditClobStoreInterface;
import gov.va.med.cds.exception.AuditClobStoreException;
import gov.va.med.cds.exception.CdsAuditLogException;
import gov.va.med.cds.exception.ErrorCodeEnum;
import gov.va.med.cds.junit.runners.Suite;
import gov.va.med.cds.junit.runners.SuiteAwareRunner;
import junit.framework.Assert;

import org.easymock.EasyMock;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;


@RunWith( SuiteAwareRunner.class )
public class VhimRequestAuditLoggerTest
{
    private static final String VHIM_IC_CREATE_REQUEST = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><clinicaldata:ClinicalData xmlns:clinicaldata=\"Clinicaldata\"><templateId>IntoleranceConditionCreate40020</templateId><clientName>CHDR</clientName><clientRequestInitiationTime>2011-06-06T12:01:01Z</clientRequestInitiationTime><patient><intoleranceConditions><recordIdentifier><identity>ID_127145081172210000</identity><namespaceId>DefaultAssigningFacility</namespaceId><universalId>UID_127145081172210000</universalId><universalIdType>aUniversalIdType</universalIdType></recordIdentifier><patient><identifier><identity>intoleranceConditionTest</identity><assigningFacility>intoleranceConditionTest</assigningFacility><assigningAuthority>USVHA</assigningAuthority></identifier><name><prefix>Prefix</prefix><given>Given</given><middle>MiddleName</middle><family>FamilyName</family><suffix>Suffix</suffix><title>Title</title></name></patient><observationTime><literal>19691231170000</literal></observationTime><agent><code>Sulfa</code><displayText>AgentDisplayTextLite</displayText><codingSystem>AgentCodingSystemLite</codingSystem></agent><allergyType><code>Drug</code><displayText>AllergyTypeDisplayTextLite</displayText><codingSystem>AllergyTypeCodingSystemLite</codingSystem></allergyType><gmrAllergyAgent><code>Sulfa</code><displayText>AgentDisplayText</displayText><codingSystem>AgentCodingSystem</codingSystem><alternateCode>Agenttest_altcode_3002</alternateCode><alternateDisplayText>AgentAltDisplayTextLite</alternateDisplayText><alternateCodingSystem>AgentAltCodingSystem</alternateCodingSystem></gmrAllergyAgent><informationSourceCategory><code>test_code_2004</code><displayText>ISC DisplayTextLite</displayText><codingSystem>ISC CodingSystemLite</codingSystem></informationSourceCategory><mechanism><code>test_code_2002</code><displayText>Mechanism DisplayTextLite</displayText><codingSystem>Mechanism CodingSystemLite</codingSystem></mechanism><status>Status</status><verified>true</verified><reaction><observationTime><literal>19691231170000</literal></observationTime><reaction><code>test_code_2003</code><displayText>Reaction DisplayTextLite</displayText><codingSystem>Reaction CodingSystemLite</codingSystem></reaction><author><comment>Comment</comment><time><literal>20100416144651</literal></time><practitioner><identifier><identity>test_eid_1003</identity><assigningFacility>DefaultAssigningFacility</assigningFacility><assigningAuthority>USVHA</assigningAuthority></identifier><idSourceTable>IdSourceTable</idSourceTable><name><prefix>Prefix</prefix><given>Given</given><middle>MiddleName</middle><family>FamilyName</family><suffix>Suffix</suffix><title>Title</title></name></practitioner></author></reaction><reaction><observationTime><literal>19691231170000</literal></observationTime><reaction><code>test_code_2001</code><displayText>Reaction DisplayTextLite</displayText><codingSystem>Reaction CodingSystemLite</codingSystem></reaction><author><comment>Comment</comment><time><literal>20100416144651</literal></time><practitioner><identifier><identity>test_eid_1001</identity><assigningFacility>DefaultAssigningFacility</assigningFacility><assigningAuthority>USVHA</assigningAuthority></identifier><idSourceTable>IdSourceTable</idSourceTable><name><prefix>Prefix</prefix><given>Given</given><middle>MiddleName</middle><family>FamilyName</family><suffix>Suffix</suffix><title>Title</title></name></practitioner></author></reaction><verifier><comment>Verifier Comment</comment><time><literal>20100416144651</literal></time><practitioner><identifier><identity>test_VERIFIERID_2002</identity><assigningFacility>DefaultAssigningFacility</assigningFacility><assigningAuthority>USVHA</assigningAuthority></identifier><idSourceTable>IdSourceTable</idSourceTable><name><prefix>Prefix</prefix><given>Given</given><middle>MiddleName</middle><family>FamilyName</family><suffix>Suffix</suffix><title>Title</title></name></practitioner></verifier><author><comment>Author Comment</comment><time><literal>20100416144651</literal></time><practitioner><identifier><identity>test_AUTHORID_1001</identity><assigningFacility>DefaultAssigningFacility</assigningFacility><assigningAuthority>USVHA</assigningAuthority></identifier><idSourceTable>IdSourceTable</idSourceTable><name><prefix>Prefix</prefix><given>Given</given><middle>MiddleName</middle><family>FamilyName</family><suffix>Suffix</suffix><title>Title</title></name></practitioner></author><errorEnterer><comment>ErrorEnterer Comment</comment><time><literal>20100416144651</literal></time><practitioner><identifier><identity>test_ERRORENTERERID_5005</identity><assigningFacility>DefaultAssigningFacility</assigningFacility><assigningAuthority>USVHA</assigningAuthority></identifier><idSourceTable>IdSourceTable</idSourceTable><name><prefix>Prefix</prefix><given>Given</given><middle>MiddleName</middle><family>FamilyName</family><suffix>Suffix</suffix><title>Title</title></name></practitioner></errorEnterer><idBandMarker><comment>ID Band Marker 1 Comment</comment><time><literal>20100416144651</literal></time><practitioner><identifier><identity>test_IDBANDUPDATERID_3003</identity><assigningFacility>DefaultAssigningFacility</assigningFacility><assigningAuthority>USVHA</assigningAuthority></identifier><idSourceTable>IdSourceTable</idSourceTable><name><prefix>Prefix</prefix><given>Given</given><middle>MiddleName</middle><family>FamilyName</family><suffix>Suffix</suffix><title>Title</title></name></practitioner></idBandMarker><idBandMarker><comment>ID Band Marker 2 Comment</comment><time><literal>20100416144651</literal></time><practitioner><identifier><identity>test_IDBANDUPDATERID_3005</identity><assigningFacility>DefaultAssigningFacility</assigningFacility><assigningAuthority>USVHA</assigningAuthority></identifier><idSourceTable>IdSourceTable</idSourceTable><name><prefix>Prefix</prefix><given>Given</given><middle>MiddleName</middle><family>FamilyName</family><suffix>Suffix</suffix><title>Title</title></name></practitioner></idBandMarker><chartMarker><comment>Chart Marker 1 Comment</comment><time><literal>20100416144651</literal></time><practitioner><identifier><identity>test_CHARTMARKERID_4002</identity><assigningFacility>DefaultAssigningFacility</assigningFacility><assigningAuthority>USVHA</assigningAuthority></identifier><idSourceTable>IdSourceTable</idSourceTable><name><prefix>Prefix</prefix><given>Given</given><middle>MiddleName</middle><family>FamilyName</family><suffix>Suffix</suffix><title>Title</title></name></practitioner></chartMarker><chartMarker><comment>Chart Marker 2 Comment</comment><time><literal>20100416144651</literal></time><practitioner><identifier><identity>test_CHARTMARKERID_4003</identity><assigningFacility>DefaultAssigningFacility</assigningFacility><assigningAuthority>USVHA</assigningAuthority></identifier><idSourceTable>IdSourceTable</idSourceTable><name><prefix>Prefix</prefix><given>Given</given><middle>MiddleName</middle><family>FamilyName</family><suffix>Suffix</suffix><title>Title</title></name></practitioner></chartMarker><commentEvents><date><literal>20100416144651</literal></date><author><identifier><identity>test_AUTHORID_1003</identity><assigningFacility>DefaultAssigningFacility</assigningFacility><assigningAuthority>USVHA</assigningAuthority></identifier><idSourceTable>IdSourceTable</idSourceTable><name><prefix>Prefix</prefix><given>Given</given><middle>MiddleName</middle><family>FamilyName</family><suffix>Suffix</suffix><title>Title</title></name></author><commentType><code>aCommentType</code><displayText>commentEventDisplayTextLite</displayText><codingSystem>commentEventCodingSystemLite</codingSystem></commentType><comments>theFirstComment</comments><comments>theSecondComment</comments></commentEvents><commentEvents><date><literal>20100416144651</literal></date><author><identifier><identity>test_AUTHORID_1003</identity><assigningFacility>DefaultAssigningFacility</assigningFacility><assigningAuthority>USVHA</assigningAuthority></identifier><idSourceTable>IdSourceTable</idSourceTable><name><prefix>Prefix</prefix><given>Given</given><middle>MiddleName</middle><family>FamilyName</family><suffix>Suffix</suffix><title>Title</title></name></author><commentType><code>aCommentType</code><displayText>commentEventDisplayTextLite</displayText><codingSystem>commentEventCodingSystemLite</codingSystem></commentType><comments>theFirstComment</comments><comments>theSecondComment</comments></commentEvents><drugClass><code><code>Class2</code><displayText>Drug Class 1DisplayText</displayText><codingSystem>Drug Class 1CodingSystem</codingSystem><alternateCode>Drug Class 1test_altcode_3001</alternateCode><alternateDisplayText>Drug Class 1AltDisplayTextLite</alternateDisplayText><alternateCodingSystem>Drug Class 1AltCodingSystem</alternateCodingSystem></code></drugClass><drugClass><code><code>Class4</code><displayText>Drug Class 2DisplayText</displayText><codingSystem>Drug Class 2CodingSystem</codingSystem><alternateCode>Drug Class 2test_altcode_3005</alternateCode><alternateDisplayText>Drug Class 2AltDisplayTextLite</alternateDisplayText><alternateCodingSystem>Drug Class 2AltCodingSystem</alternateCodingSystem></code></drugClass><drugIngredient><code><code>Ingredient2</code><displayText>Drug Ing. 1DisplayTextLite</displayText><codingSystem>Drug Ing. 1CodingSystemLite</codingSystem></code></drugIngredient><drugIngredient><code><code>Ingredient6</code><displayText>Drug Ing. 2DisplayTextLite</displayText><codingSystem>Drug Ing. 2CodingSystemLite</codingSystem></code></drugIngredient><facilityIdentifier><identity>OrganizationId</identity><name>OrganizationName</name><assigningAuthority>AssigningAuthNamespaceId</assigningAuthority></facilityIdentifier><recordSource><namespaceId>200CH</namespaceId><universalId>1271450811722100000</universalId><universalIdType>aUniversalIdType</universalIdType></recordSource><recordVersion>10000</recordVersion><recordUpdateTime><literal>20100416144651</literal></recordUpdateTime></intoleranceConditions></patient></clinicaldata:ClinicalData>";
    private static final String VHIM_RX_READ_FILTER = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><filter:filter vhimVersion=\"Vhim_4_00\" xmlns:filter=\"Filter\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><filterId>RX_SINGLE_PATIENT_ALL_DATA_FILTER</filterId><patients><resolvedIdentifiers><assigningAuthority>VW_FnTest_Rx_AssigningAuthority</assigningAuthority><assigningFacility>VW_FnTest_Rx_AssigningFacility</assigningFacility><identity>VW_FnTest_Rx_Patient_135</identity></resolvedIdentifiers></patients><entryPointFilter queryName=\"OPP-Standardized\"><domainEntryPoint>OutpatientMedicationPromise</domainEntryPoint></entryPointFilter></filter:filter>";
    private static final String VHIM_IC_DELETE_REQUEST = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><clinicaldata:ClinicalData xmlns:clinicaldata=\"Clinicaldata\"><templateId>IntoleranceConditionDelete40030</templateId><patient><intoleranceConditions><recordIdentifier><identity>ID_127187754578910000</identity><namespaceId>DefaultAssigningFacility</namespaceId><universalId>UID_127187754578910000</universalId><universalIdType>aUniversalIdType</universalIdType></recordIdentifier><recordVersion>10000</recordVersion></intoleranceConditions></patient></clinicaldata:ClinicalData>";
    private static final String IC_CREATE_TEMPLATE_ID = "IntoleranceConditionCreate40020";
    private static final String IC_DELETE_TEMPLATE_ID = "IntoleranceConditionDelete40030";
    private static final String HA_CREATE_TEMPLATE_ID = "HealthAdapterCreate1";
    private static final String HA_DELETE_TEMPLATE_ID = "HealthAdapterDelete1";
    private static final String RX_TEMPLATE_ID = "VWPharmacyRead40010";
    private static final String RX_FILER_ID = "RX_SINGLE_PATIENT_ALL_DATA_FILTER";
    private static final String UNIQUE_REQUEST_ID = "E851B78E-0807-1A28-E86C-E1B362624068";
    private static final String SENDING_FACILITY_START_ELEMENT = "<recordSource><namespaceId>";
    private static final String SENDING_FACILITY_END_ELEMENT = "</namespaceId>";
    private static final String MESSAGE_DATETIME_START_ELEMENT = "<recordUpdateTime><literal>";
    private static final String MESSAGE_DATETIME_END_ELEMENT = "</literal></recordUpdateTime>";
    private static final String DEFAULT_REQUEST_ID = "<<requestId>>";

    private VhimRequestAuditLoggerInterface vhimRequestAuditLogger;
    private JdbcTemplate loggerJdbcTemplate;
    private JdbcTemplate monitorJdbcTemplate;


    public VhimRequestAuditLoggerTest( )
    {
        // load up the application context and set the members because we can't
        // use the test harness Abstract test classes because of a circular
        // dependency issue
        ConfigurableApplicationContext appCtxt = new ClassPathXmlApplicationContext(
                        new String[] { "gov/va/med/cds/audit/vhimRequestAuditLoggerTestContext.xml" } );
        appCtxt.getBeanFactory().autowireBeanProperties( this, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true );

        clearAuditClobStrTable();
        clearHaAuditClobStrTable();
    }


    @SuppressWarnings("deprecation")
	@Test
    @Suite( groups = "checkintest" )
    public void testAuditWriteRequest( )
    {
        clearAuditClobStrTable( UNIQUE_REQUEST_ID );
        vhimRequestAuditLogger.auditWriteRequest( IC_CREATE_TEMPLATE_ID, VHIM_IC_CREATE_REQUEST, UNIQUE_REQUEST_ID );
        Assert.assertEquals( 1, getAuditClobStrCount( UNIQUE_REQUEST_ID ) );

        clearAuditClobStrTable( UNIQUE_REQUEST_ID );
        vhimRequestAuditLogger.auditWriteRequest( IC_DELETE_TEMPLATE_ID, VHIM_IC_DELETE_REQUEST, UNIQUE_REQUEST_ID );
        Assert.assertEquals( 1, getAuditClobStrCount( UNIQUE_REQUEST_ID ) );
    }


    /*@Test
    @Suite( groups = "checkintest" )
    public void testHaAuditWriteRequestWithNullParams( )
    {
        clearHaAuditClobStrTable( DEFAULT_REQUEST_ID );
        vhimRequestAuditLogger.auditWriteRequest( HA_CREATE_TEMPLATE_ID, VHIM_IC_CREATE_REQUEST, "" );
        Assert.assertEquals( 1, getHaAuditClobStrCount( DEFAULT_REQUEST_ID ) );

        clearHaAuditClobStrTable( DEFAULT_REQUEST_ID );
        vhimRequestAuditLogger.auditWriteRequest( HA_DELETE_TEMPLATE_ID, VHIM_IC_DELETE_REQUEST, DEFAULT_REQUEST_ID );
        Assert.assertEquals( 1, getHaAuditClobStrCount( DEFAULT_REQUEST_ID ) );
    }*/


    @Test
    @Suite( groups = "checkintest" )
    public void testAuditWriteRequestWithNullParams( )
    {
        clearAuditClobStrTable( DEFAULT_REQUEST_ID );
        vhimRequestAuditLogger.auditWriteRequest( "", "", "" );
        Assert.assertEquals( 1, getAuditClobStrCount( DEFAULT_REQUEST_ID ) );

        clearAuditClobStrTable( DEFAULT_REQUEST_ID );
        vhimRequestAuditLogger.auditWriteRequest( "", VHIM_IC_DELETE_REQUEST, "" );
        Assert.assertEquals( 1, getAuditClobStrCount( DEFAULT_REQUEST_ID ) );
    }


    /*@Test
    @Suite( groups = "checkintest" )
    public void testHaAuditWriteRequest( )
    {
        clearHaAuditClobStrTable( UNIQUE_REQUEST_ID );
        vhimRequestAuditLogger.auditWriteRequest( HA_CREATE_TEMPLATE_ID, VHIM_IC_CREATE_REQUEST, UNIQUE_REQUEST_ID );
        Assert.assertEquals( 1, getHaAuditClobStrCount( UNIQUE_REQUEST_ID ) );

        clearHaAuditClobStrTable( UNIQUE_REQUEST_ID );
        vhimRequestAuditLogger.auditWriteRequest( HA_DELETE_TEMPLATE_ID, VHIM_IC_DELETE_REQUEST, UNIQUE_REQUEST_ID );
        Assert.assertEquals( 1, getHaAuditClobStrCount( UNIQUE_REQUEST_ID ) );
    }*/


    @Test( expected = AuditClobStoreException.class )
    @Suite( groups = "checkintest" )
    public void testAuditWriteRequestWithException( )
    {
        VhimRequestAuditLogger vhimRequestAuditLogger = new VhimRequestAuditLogger();

        CdsAuditClobStoreInterface CdsAuditClobStoreMock = EasyMock.createNiceMock( CdsAuditClobStoreInterface.class );
        CdsAuditClobStoreMock.persistCdsAuditClob( EasyMock.isA( CdsAuditClobStore.class ) );
        EasyMock.expectLastCall().andThrow( new AuditClobStoreException( ErrorCodeEnum.CDS_AUDIT_CLOB_STORE_ERROR ) );
        EasyMock.replay( CdsAuditClobStoreMock );

        vhimRequestAuditLogger.setCdsAuditClobStore( CdsAuditClobStoreMock );
        vhimRequestAuditLogger.setSendingFacilityStartElement( SENDING_FACILITY_START_ELEMENT );
        vhimRequestAuditLogger.setSendingFacilityEndElement( SENDING_FACILITY_END_ELEMENT );
        vhimRequestAuditLogger.setMessageDateTimeStartElement( MESSAGE_DATETIME_START_ELEMENT );
        vhimRequestAuditLogger.setMessageDateTimeEndElement( MESSAGE_DATETIME_END_ELEMENT );

        vhimRequestAuditLogger.auditWriteRequest( IC_CREATE_TEMPLATE_ID, VHIM_IC_CREATE_REQUEST, UNIQUE_REQUEST_ID );
    }


    @Test
    @Suite( groups = "checkintest" )
    public void testAuditReadRequest( )
    {
        vhimRequestAuditLogger.auditReadRequest( RX_TEMPLATE_ID, VHIM_RX_READ_FILTER, RX_FILER_ID, UNIQUE_REQUEST_ID, System.currentTimeMillis(),
                        "<<READ_RESPONSE>>" );

        Assert.assertTrue( true );
    }


    @Test
    @Suite( groups = "checkintest" )
    public void testAuditReadRequestWithException( )
    {
        //VhimRequestAuditLogger vhimRequestAuditLogger = new VhimRequestAuditLogger();

        AuditLogPersistenceManagerInterface auditLogPersistenceManagerMock = EasyMock.createNiceMock( AuditLogPersistenceManagerInterface.class );
        auditLogPersistenceManagerMock.storeAuditLog( EasyMock.isA( AbstractAuditLog.class ) );
        EasyMock.expectLastCall().andThrow( new CdsAuditLogException( ErrorCodeEnum.CDS_AUDIT_LOG_ERROR ) );
        EasyMock.replay( auditLogPersistenceManagerMock );

        ((VhimRequestAuditLogger)vhimRequestAuditLogger).setAuditLogPersistenceManager( auditLogPersistenceManagerMock );

        vhimRequestAuditLogger.auditReadRequest( RX_TEMPLATE_ID, VHIM_RX_READ_FILTER, RX_FILER_ID, UNIQUE_REQUEST_ID, System.currentTimeMillis(),
                        "<<READ_RESPONSE>>" );
    }


    private void clearAuditClobStrTable( )
    {
        monitorJdbcTemplate.update( "truncate table audit_clob_str" );
    }


    private void clearHaAuditClobStrTable( )
    {
        monitorJdbcTemplate.update( "truncate table ha_audit_clob_str" );
    }


    private void clearAuditClobStrTable( String queryRequestId )
    {
        loggerJdbcTemplate.update( "delete from audit_clob_str where request_id = ?", new Object[] { queryRequestId } );
    }


    private void clearHaAuditClobStrTable( String queryRequestId )
    {
        loggerJdbcTemplate.update( "delete from ha_audit_clob_str where request_id = ?", new Object[] { queryRequestId } );
    }


    private int getAuditClobStrCount( String queryRequestId )
    {
        //return loggerJdbcTemplate.queryForInt( "select count(*) from audit_clob_str where REQUEST_ID = ?", new Object[] { queryRequestId } );
        Number number = loggerJdbcTemplate.queryForObject( "select count(*) from audit_clob_str where REQUEST_ID = ?", new Object[] { queryRequestId }, Integer.class );
        return (number != null ? number.intValue() : 0);
    }


    /*private int getHaAuditClobStrCount( String queryRequestId )
    {
        return loggerJdbcTemplate.queryForInt( "select count(*) from ha_audit_clob_str where REQUEST_ID = ?", new Object[] { queryRequestId } );
    }*/


    public void setLoggerJdbcTemplate( JdbcTemplate loggerJdbcTemplate )
    {
        this.loggerJdbcTemplate = loggerJdbcTemplate;
    }


    public void setMonitorJdbcTemplate( JdbcTemplate monitorJdbcTemplate )
    {
        this.monitorJdbcTemplate = monitorJdbcTemplate;
    }


    public void setVhimRequestAuditLogger( VhimRequestAuditLoggerInterface vhimRequestAuditLogger )
    {
        this.vhimRequestAuditLogger = vhimRequestAuditLogger;
    }
}
