

package gov.va.med.cds.response.vhim400;


import gov.va.med.cds.clinicaldata.vhim400.ClinicalDataResponseInterface;
import gov.va.med.cds.clinicaldata.vhim400.ConfigurableClinicalDataResponse;
import gov.va.med.cds.junit.runners.Suite;
import gov.va.med.cds.junit.runners.SuiteAwareRunner;
import gov.va.med.cds.response.AggregatorNodeSpecification;
import gov.va.med.cds.response.ParameterizedResponseAggregator;
import gov.va.med.cds.response.ResponseAggregatorException;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

//import junit.framework.Assert;
import org.junit.Assert;

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


@RunWith( SuiteAwareRunner.class )
public class ParameterizedResponseAggregatorTest
{

    @Test
    @Suite( groups = { "brokentest" } )
    public void testGetAggregatedResult_OneDocument( )
    {
        List<Document> aggregatedReadResponseList = new ArrayList<Document>();
        Document documentMock = EasyMock.createMock( Document.class );
        aggregatedReadResponseList.add( documentMock );
        
        ClinicalDataResponseInterface clinicalDataResponse = new ConfigurableClinicalDataResponse("pateints/patient", "patients/patient", "CdsResponse400");
        Map<String, List<AggregatorNodeSpecification>> aggregatedChildNodeSpecMap = new Hashtable<String, List<AggregatorNodeSpecification>>();
        ParameterizedResponseAggregator aggregator = new ParameterizedResponseAggregator(clinicalDataResponse, aggregatedChildNodeSpecMap);
        
        Assert.assertNotNull( aggregator.aggregateResponses( aggregatedReadResponseList ) );
    }


    @Test( expected = ResponseAggregatorException.class )
    @Suite( groups = { "checkintest" } )
    public void testGetAggregatedResult_ThrowsException( )
    {
        List<Document> aggregatedReadResponseList = new ArrayList<Document>();
        ConfigurableClinicalDataResponse clinicalDataResponse = new ConfigurableClinicalDataResponse("pateints/patient", "patients/patient", "CdsResponse400");
        Map<String, List<AggregatorNodeSpecification>> aggregatedChildNodeSpecMap = new Hashtable<String, List<AggregatorNodeSpecification>>();
        ParameterizedResponseAggregator aggregator = new ParameterizedResponseAggregator(clinicalDataResponse, aggregatedChildNodeSpecMap);
        
        aggregator.aggregateResponses( aggregatedReadResponseList );
    }

    @Test
    @Suite( groups = { "checkintest" } )
    public void testGetAggregatedResult_DocumentList( )
    {
        // create some clinical documents to play with.
        ClinicalDataResponseInterface clinicalDataResponse = new ConfigurableClinicalDataResponse("patients/patient", "patients/patient/clinicalDocumentEvents", "CdsResponse400");
        Document responseDocument1 = clinicalDataResponse.buildEmptyClinicalDocument( "TiuDocumentListRead2", "requestId1" );
        Document responseDocument2 = clinicalDataResponse.buildEmptyClinicalDocument( "TiuDocumentListRead2", "requestId1" );
        clinicalDataResponse.addRequestedNationalId( responseDocument1, "nationalId1" );
        clinicalDataResponse.addRequestedNationalId( responseDocument2, "nationalId1" );
        
        Element resolvedId1 = DocumentHelper.createElement( "requestedResolvedIdentifiers" );
        resolvedId1.add( DocumentHelper.createElement( "requestedResolvedIdentifier" ) );
        clinicalDataResponse.getPatientElement( responseDocument1 ).add( resolvedId1 );
        
        Element resolvedId2 = DocumentHelper.createElement( "requestedResolvedIdentifiers" );
        resolvedId2.add( DocumentHelper.createElement( "requestedResolvedIdentifier" ) );
        clinicalDataResponse.getPatientElement( responseDocument2 ).add( resolvedId2 );
        
        Element clinicalRoot1 = clinicalDataResponse.getClinicalRoot( responseDocument1 );
        clinicalRoot1.add( DocumentHelper.createElement( "clinicalDocumentEvent" ) );
        clinicalRoot1.add( DocumentHelper.createElement( "clinicalDocumentEvent" ) );
        
        Element clinicalRoot2 = clinicalDataResponse.getClinicalRoot( responseDocument2 );
        clinicalRoot2.add( DocumentHelper.createElement( "clinicalDocumentEvent" ) );
        clinicalRoot2.add( DocumentHelper.createElement( "clinicalDocumentEvent" ) );
        
        List<Document> aggregatedReadResponseList = new ArrayList<Document>();
        aggregatedReadResponseList.add( responseDocument1 );
        aggregatedReadResponseList.add( responseDocument2 );
        
        Map<String, List<AggregatorNodeSpecification>> aggregatedChildNodeSpecMap = new Hashtable<String, List<AggregatorNodeSpecification>>();
        List<AggregatorNodeSpecification> nodeSpecsClinical = new ArrayList<AggregatorNodeSpecification>();
        nodeSpecsClinical.add( new AggregatorNodeSpecification( "requestedResolvedIdentifiers", true ) );
        nodeSpecsClinical.add( new AggregatorNodeSpecification( "clinicalDocumentEvents", true ) );
        aggregatedChildNodeSpecMap.put( "patients/patient", nodeSpecsClinical );
        List<AggregatorNodeSpecification> nodeSpecsErrors = new ArrayList<AggregatorNodeSpecification>();
        nodeSpecsErrors.add( new AggregatorNodeSpecification( "errors", true ) );
        nodeSpecsErrors.add( new AggregatorNodeSpecification( "fatalErrors", true ) );
        nodeSpecsErrors.add( new AggregatorNodeSpecification( "warnings", true ) );
        aggregatedChildNodeSpecMap.put( "errorSection", nodeSpecsErrors );
        
        ParameterizedResponseAggregator aggregator = new ParameterizedResponseAggregator(clinicalDataResponse, aggregatedChildNodeSpecMap);
        Document clinicalData =  aggregator.aggregateResponses( aggregatedReadResponseList ) ;
        
        Assert.assertNotNull( clinicalData.getRootElement() );
        Assert.assertEquals("TiuDocumentListRead2", clinicalData.getRootElement().element("templateId").getText() );
        Assert.assertEquals("requestId1", clinicalData.getRootElement().element("requestId").getText() );
        Assert.assertNotNull(clinicalData.getRootElement().element("patients").element("patient"));
        Assert.assertNotNull(clinicalData.getRootElement().element("patients").element("patient").element("requestedNationalId"));
        Assert.assertNotNull(clinicalData.getRootElement().element("patients").element("patient").element("requestedResolvedIdentifiers"));
        Assert.assertNotNull(clinicalData.getRootElement().element("patients").element("patient").element("clinicalDocumentEvents"));
        Assert.assertEquals( 4, clinicalData.getRootElement().element("patients").element("patient").element("clinicalDocumentEvents").elements("clinicalDocumentEvent").size() );
    }
    
    
    @Test
    @Suite( groups = { "checkintest" } )
    public void testGetAggregatedResultWithErrors_DocumentList( )
    {
        // create some clinical documents to play with.
        ClinicalDataResponseInterface clinicalDataResponse = new ConfigurableClinicalDataResponse("patients/patient", "patients/patient/clinicalDocumentEvents", "CdsResponse400");
        Document responseDocument1 = clinicalDataResponse.buildEmptyClinicalDocument( clinicalDataResponse.getErrorResponseTemplateId(), "requestId1" );
        Document responseDocument2 = clinicalDataResponse.buildEmptyClinicalDocument( "TiuDocumentListRead2", "requestId1" );
        clinicalDataResponse.addRequestedNationalId( responseDocument1, "nationalId1" );
        clinicalDataResponse.addRequestedNationalId( responseDocument2, "nationalId1" );
        
        Element resolvedId1 = DocumentHelper.createElement( "requestedResolvedIdentifiers" );
        resolvedId1.add( DocumentHelper.createElement( "requestedResolvedIdentifier" ) );
        clinicalDataResponse.getPatientElement( responseDocument1 ).add( resolvedId1 );
        
        Element resolvedId2 = DocumentHelper.createElement( "requestedResolvedIdentifiers" );
        resolvedId2.add( DocumentHelper.createElement( "requestedResolvedIdentifier" ) );
        clinicalDataResponse.getPatientElement( responseDocument2 ).add( resolvedId2 );
        
        Element errorSection1 = DocumentHelper.createElement( "errorSection" );
        responseDocument1.getRootElement().add(errorSection1);
        Element errors1 = DocumentHelper.createElement("errors");
        errors1.add( DocumentHelper.createElement("error"));
        errors1.add( DocumentHelper.createElement("error"));
        errors1.add( DocumentHelper.createElement("error"));
        errorSection1.add(errors1);
        
        Element clinicalRoot2 = clinicalDataResponse.getClinicalRoot( responseDocument2 );
        clinicalRoot2.add( DocumentHelper.createElement( "clinicalDocumentEvent" ) );
        clinicalRoot2.add( DocumentHelper.createElement( "clinicalDocumentEvent" ) );
        
        List<Document> aggregatedReadResponseList = new ArrayList<Document>();
        aggregatedReadResponseList.add( responseDocument1 );
        aggregatedReadResponseList.add( responseDocument2 );
        
        Map<String, List<AggregatorNodeSpecification>> aggregatedChildNodeSpecMap = new Hashtable<String, List<AggregatorNodeSpecification>>();
        List<AggregatorNodeSpecification> nodeSpecsClinical = new ArrayList<AggregatorNodeSpecification>();
        nodeSpecsClinical.add( new AggregatorNodeSpecification( "clinicalDocumentEvents", true ) );
        nodeSpecsClinical.add( new AggregatorNodeSpecification( "requestedResolvedIdentifiers", true ) );
        aggregatedChildNodeSpecMap.put( "patients/patient", nodeSpecsClinical );
        List<AggregatorNodeSpecification> nodeSpecsErrors = new ArrayList<AggregatorNodeSpecification>();
        nodeSpecsErrors.add( new AggregatorNodeSpecification( "errors", true ) );
        nodeSpecsErrors.add( new AggregatorNodeSpecification( "fatalErrors", true ) );
        nodeSpecsErrors.add( new AggregatorNodeSpecification( "warnings", true ) );
        aggregatedChildNodeSpecMap.put( "errorSection", nodeSpecsErrors );
        
        ParameterizedResponseAggregator aggregator = new ParameterizedResponseAggregator(clinicalDataResponse, aggregatedChildNodeSpecMap);
        Document clinicalData =  aggregator.aggregateResponses( aggregatedReadResponseList ) ;
        
        Assert.assertNotNull( clinicalData.getRootElement() );
        Assert.assertEquals("TiuDocumentListRead2", clinicalData.getRootElement().element("templateId").getText() );
        Assert.assertEquals("requestId1", clinicalData.getRootElement().element("requestId").getText() );
        Assert.assertNotNull(clinicalData.getRootElement().element("patients").element("patient"));
        Assert.assertNotNull(clinicalData.getRootElement().element("patients").element("patient").element("requestedNationalId"));
        Assert.assertNotNull(clinicalData.getRootElement().element("patients").element("patient").element("requestedResolvedIdentifiers"));
        Assert.assertNotNull(clinicalData.getRootElement().element("patients").element("patient").element("clinicalDocumentEvents"));
        Assert.assertEquals( 2, clinicalData.getRootElement().element("patients").element("patient").element("clinicalDocumentEvents").elements("clinicalDocumentEvent").size() );
        Assert.assertNotNull( clinicalData.getRootElement().element("errorSection") );
        Assert.assertNotNull( clinicalData.getRootElement().element("errorSection").element("errors") );
        Assert.assertEquals( 3,  clinicalData.getRootElement().element("errorSection").element("errors").elements("error").size() );
    }
    
    
    @Test(expected = ResponseAggregatorException.class)
    @Suite( groups = { "checkintest" } )
    public void testGetAggregatedResult_DocumentList_ThrowsRuntimeException( )
    {
        List<Document> aggregatedReadResponseList = new ArrayList<Document>();
        Document document1 = DocumentHelper.createDocument();
        Document document2 = DocumentHelper.createDocument();
        aggregatedReadResponseList.add( document1 );
        aggregatedReadResponseList.add( document2 );
        
        Map<String, List<AggregatorNodeSpecification>> aggregatedChildNodeSpecMap = new Hashtable<String, List<AggregatorNodeSpecification>>();
        List<AggregatorNodeSpecification> nodeSpecsClinical = new ArrayList<AggregatorNodeSpecification>();
        nodeSpecsClinical.add( new AggregatorNodeSpecification( "clinicalDocumentEvents", true ) );
        nodeSpecsClinical.add( new AggregatorNodeSpecification( "requestedResolvedIdentifiers", true ) );
        aggregatedChildNodeSpecMap.put( "patients/patient", nodeSpecsClinical );
        List<AggregatorNodeSpecification> nodeSpecsErrors = new ArrayList<AggregatorNodeSpecification>();
        nodeSpecsErrors.add( new AggregatorNodeSpecification( "errors", true ) );
        nodeSpecsErrors.add( new AggregatorNodeSpecification( "fatalErrors", true ) );
        nodeSpecsErrors.add( new AggregatorNodeSpecification( "warnings", true ) );
        aggregatedChildNodeSpecMap.put( "errorSection", nodeSpecsErrors );

        ConfigurableClinicalDataResponse clinicalDataResponse = new ConfigurableClinicalDataResponse("pateints/patient", "patients/patient", "CdsResponse400");
        ParameterizedResponseAggregator aggregator = new ParameterizedResponseAggregator(clinicalDataResponse, aggregatedChildNodeSpecMap);

        // first document throws Exception
        aggregator.aggregateResponses( aggregatedReadResponseList ) ;
        
        
    }
}
