

package gov.va.med.cds.integration.vim.ha;


import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import gov.va.med.cds.clinicaldata.DomainEntryPoint;
import gov.va.med.cds.junit.runners.Suite;
import gov.va.med.cds.junit.runners.SuiteAwareSpringRunner;
import gov.va.med.cds.testharness.vhim400.TemplateIdHelper;
import gov.va.med.cds.testharness.vhim400.builders.BaseDatatypesBuilder;
import gov.va.med.cds.testharness.vhim400.builders.ClinicalDataBuilder;
import gov.va.med.cds.testharness.vhim400.builders.ClinicalDomainBuilderFactoryInterface;
import gov.va.med.cds.testharness.vhim400.builders.FilterBuilder;
import gov.va.med.cds.testharness.vhim400.builders.HAPatientEnteredVitalSignBuilderFactory;
import gov.va.med.cds.testharness.vhim400.builders.HAVitalsBuilder;
import gov.va.med.cds.uniqueidentifier.UniqueIdentifier;


import org.apache.commons.lang3.time.DateFormatUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.junit.Test;
import org.junit.runner.RunWith;

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


@RunWith( SuiteAwareSpringRunner.class )
public class EndToEndPatientEnteredVitalSignTest
    extends
        AbstractHealthAdapterEndToEndTest
{
    private static String READ_TEST_DOMAINENTRYPOINT_XPATH = "//patientEnteredVitalSigns/patientEnteredVitalSign";


    @SuppressWarnings( "deprecatedtest" )
    @Test
    @Suite( groups = { "checkintest" } )
    public void testCreateUpdateDeletePatientEnteredVitalSign( )
        throws Exception
    {

        String createRequestXml = createHaCreateXml( TEST_CUD_PATIENTIDENTITY_HDR, "PatientEnteredVitalSigns", TemplateIdHelper.HEALTH_ADAPTER_CREATE1_TEMPLATE_ID );

        // Create Vital Sign
        Document clinicalDataDocument = createAndAssertDomainData( TemplateIdHelper.HEALTH_ADAPTER_CREATE1_TEMPLATE_ID, createRequestXml );
        
        // Update Vital Sign
        String updateRequestXml = createHaUpdateXml( TEST_CUD_PATIENTIDENTITY_HDR, "PatientEnteredVitalSigns", TemplateIdHelper.HEALTH_ADAPTER_UPDATE1_TEMPLATE_ID, recordIdentifier );
        updateAndAssertDomainData( TemplateIdHelper.HEALTH_ADAPTER_UPDATE1_TEMPLATE_ID, updateRequestXml,"VITAL_SIGN", "VITAL_SIGN_ID" );

        // Logically Delete vital sign
        String logicalDeleteXml = createHAVitalsignsDeleteXml( "PatientEnteredVitalSigns", TemplateIdHelper.HEALTH_ADAPTER_DELETE1_TEMPLATE_ID, recordIdentifier, LOGICAL_DELETE_RECORD_STATUS );
        deleteAndAssertDomainData( TemplateIdHelper.HEALTH_ADAPTER_DELETE1_TEMPLATE_ID, logicalDeleteXml, "VITAL_SIGN", "VITAL_SIGN_ID", true );
    
        //Delete vital sign
        String deleteXml = createHAVitalsignsDeleteXml( "PatientEnteredVitalSigns", TemplateIdHelper.HEALTH_ADAPTER_DELETE1_TEMPLATE_ID, recordIdentifier, DELETE_RECORD_STATUS );
        deleteAndAssertDomainData( TemplateIdHelper.HEALTH_ADAPTER_DELETE1_TEMPLATE_ID, deleteXml, "VITAL_SIGN", "VITAL_SIGN_ID", false );
    }


    protected String createHaCreateXml( String patientIdentifier, String entryPoint, String templateId )
    {
        return createHaXml( patientIdentifier, entryPoint, templateId, null );

    }


    protected String createHaUpdateXml( String patientIdentifier, String entryPoint, String templateId, String recordIdentifier )
    {
        return createHaXml( patientIdentifier, entryPoint, templateId, recordIdentifier );

    }


    protected String createHaXml( String patientIdentifier, String entryPoint, String templateId, String recordIdentifier )
    {
        Map<String, DomainEntryPoint> domainEntryPointsMap = new HashMap<String, DomainEntryPoint>();
        domainEntryPointsMap.put( templateId, DomainEntryPoint.PatientEnteredVitalSign );
        ClinicalDataBuilder clinicalDataBuilder = new ClinicalDataBuilder();
        clinicalDataBuilder.setDomainEntryPointsMap( domainEntryPointsMap );

        Map<String, ClinicalDomainBuilderFactoryInterface> domainEntryPointsWrappersMap = new HashMap<String, ClinicalDomainBuilderFactoryInterface>();
        HAPatientEnteredVitalSignBuilderFactory factory = new HAPatientEnteredVitalSignBuilderFactory();

        HAVitalsBuilder haVitalBuilder;
        if ( recordIdentifier != null )
        {
            haVitalBuilder = new HAVitalsBuilder( recordIdentifier );
        }
        else
        {
            haVitalBuilder = new HAVitalsBuilder();
        }
        factory.setVitalSignObservationEventBuilder( haVitalBuilder );

        domainEntryPointsWrappersMap.put( "PatientEnteredVitalSign", factory );
        clinicalDataBuilder.setDomainEntryPointsWrappersMap( domainEntryPointsWrappersMap );

        Element patient = null;
        if ( patientIdentifier == null )
        {
            patient = BaseDatatypesBuilder.createHL72PersonIdentifier( "HealthAdapterTest", "200DOD", "USDOD" );
        }
        else
        {
            patient = BaseDatatypesBuilder.createHL72PersonIdentifier( "HealthAdapterTest", patientIdentifier, "200DOD", "USDOD" );
        }

        Document clinicalDataInsert = clinicalDataBuilder.createClinicalData( templateId, 1, patient );

        return clinicalDataInsert.asXML();
    }


    protected String createHAVitalsignsDeleteXml( String entryPoint, String templateId, String recordIdentifierIdentity, String recordStatus )
    {
        Map<String, DomainEntryPoint> domainEntryPointsMap = new HashMap<String, DomainEntryPoint>();
        domainEntryPointsMap.put( templateId, DomainEntryPoint.PatientEnteredVitalSign );
        ClinicalDataBuilder clinicalDataBuilder = new ClinicalDataBuilder();
        clinicalDataBuilder.setDomainEntryPointsMap( domainEntryPointsMap );

        Map<String, ClinicalDomainBuilderFactoryInterface> domainEntryPointsWrappersMap = new HashMap<String, ClinicalDomainBuilderFactoryInterface>();
        HAPatientEnteredVitalSignBuilderFactory factory = new HAPatientEnteredVitalSignBuilderFactory();
        factory.setVitalSignObservationEventBuilder( new HAVitalsBuilder() );
        domainEntryPointsWrappersMap.put( "PatientEnteredVitalSign", factory );
        clinicalDataBuilder.setDomainEntryPointsWrappersMap( domainEntryPointsWrappersMap );

        Element patient = BaseDatatypesBuilder.createHL72PersonIdentifier( "HealthAdapterTest", "200DOD", "USDOD" );
        Document clinicalDataInsert = clinicalDataBuilder.deleteClinicalData( domainEntryPointsMap.get( templateId ), templateId, patient, recordIdentifierIdentity, recordStatus );

        return clinicalDataInsert.asXML();
    }


    @Test
    @Suite( groups = { "checkintest" } )
    public void testPatientEnteredVitalSignsReadNoDates( )
        throws Exception
    {
        String[] hdrPatient1 = { ASSIGNINGAUTHORITY_HDR, ASSIGNING_FACILITY_HDR, TEST_READ_PATIENTIDENTITY_HDR };
        String[][] patientIdentifiers = { hdrPatient1 };
        List<Map<String, String>> patients = getResolvedPatients( patientIdentifiers );

        Map<String, String> entryPointFilter = new HashMap<String, String>();
        entryPointFilter.put( FilterBuilder.DOMAIN_ENTRYPOINT_KEY, "PatientEnteredVitalSign" );
        entryPointFilter.put( FilterBuilder.QUERY_NAME_KEY, "queryName" );

        List<Map<String, String>> entryPointFilterMaps = new ArrayList<Map<String, String>>();
        entryPointFilterMaps.add( entryPointFilter );

        String filterXml = FilterBuilder.buildFilterWithEdiPi( FILTER_ID, entryPointFilterMaps, patients, DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) );

        readAndAssertDomainData( filterXml );
    }


    @Test
    @Suite( groups = { "checkintest" } )
    public void testPatientEnteredVitalSignsReadWithDates( )
        throws Exception
    {
        String[] hdrPatient1 = { ASSIGNINGAUTHORITY_HDR, ASSIGNING_FACILITY_HDR, TEST_READ_PATIENTIDENTITY_HDR };
        String[][] patientIdentifiers = { hdrPatient1 };
        List<Map<String, String>> patients = getResolvedPatients( patientIdentifiers );

        Map<String, String> entryPointFilter = new HashMap<String, String>();
        entryPointFilter.put( FilterBuilder.DOMAIN_ENTRYPOINT_KEY, "PatientEnteredVitalSign" );
        entryPointFilter.put( FilterBuilder.QUERY_NAME_KEY, "queryName" );

        entryPointFilter.put( FilterBuilder.START_DATE_KEY, "2012-03-16" );
        entryPointFilter.put( FilterBuilder.END_DATE_KEY, "2012-03-16" );

        List<Map<String, String>> entryPointFilterMaps = new ArrayList<Map<String, String>>();
        entryPointFilterMaps.add( entryPointFilter );

        String filterXml = FilterBuilder.buildFilterWithEdiPi( FILTER_ID, entryPointFilterMaps, patients, DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) );

        readAndAssertDomainData( filterXml );
    }


    @SuppressWarnings( "deprecatedtest" )
    protected Document readAndAssertDomainData( String filter )
        throws Exception
    {
        Document clinicalDataDocument = super.readAndAssertDomainData( filter );
          
        // Check for domain entry point elements
        List<Element> domainElements = clinicalDataDocument.selectNodes( READ_TEST_DOMAINENTRYPOINT_XPATH );
        assertTrue( domainElements.size() > 0 );

        return clinicalDataDocument;
    }


    protected String getPatientEnteredVitalSignsEntryPointXpath( )
    {
        return "//PatientEnteredVitalSigns";
    }

}
