

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.HADietJournalBuilder;
import gov.va.med.cds.testharness.vhim400.builders.HAPatientJournalEntryDietJournalBuilderFactory;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
//import org.hibernate.sql.ordering.antlr.Node;
import org.junit.Test;
import org.junit.runner.RunWith;


@RunWith( SuiteAwareSpringRunner.class )
public class EndToEndPatientEnteredDietJournalEntryTest
    extends
        AbstractHealthAdapterEndToEndTest
{

    @SuppressWarnings( "unchecked" )
    @Test
    @Suite( groups = { "deprecatedtest" } )
    public void testDietJournalDetailsCRUD()
        throws Exception
    {
    	String patientId = uniquePatientIdentity;
    	
        doDelete( patientId );
       
        patientId = uniquePatientIdentity + "_" + (int)(Math.random()*10000000);
    	
        
        /// CREATE
        String createRequestXml = createHaCreateXml( patientId, "PatientEnteredDietJournalEntry", TemplateIdHelper.HEALTH_ADAPTER_CREATE1_TEMPLATE_ID, null, "calories", 1, null );
        Document createRequest = DocumentHelper.parseText(createRequestXml);
      
        String hexBinaryAttachmentName = createRequest.selectSingleNode("//hexBinaryAttachment").getParent().elementText("name");
        String base64BinaryAttachmentName = createRequest.selectSingleNode("//base64BinaryAttachment").getParent().elementText("name");

        Document createResponse = createAndAssertDomainData( TemplateIdHelper.HEALTH_ADAPTER_CREATE1_TEMPLATE_ID, createRequestXml );
        List<Element> recordIdentifierList = createResponse.selectNodes( RECORD_IDENTIFIER_IDENTITY_XPATH );
        assertTrue( recordIdentifierList.size() == 1 );
        String recordIdentifier = ( ( Element )recordIdentifierList.get( 0 ) ).getText();
        createRequest=null;
        createResponse=null;        
        
        /// DETAIL READ for hexBinaryAttachmentName
        Map<String,String> otherQueryParameters = new HashMap<String,String>();
        otherQueryParameters.put("attachmentName", hexBinaryAttachmentName);
        Map<String, String> assigningAuthorityAndFacilityMap = new HashMap<String, String>();
        String detailFilterXml = FilterBuilder.buildHealthAdapterJournalDetailsFilter("PatientEnteredDietJournalEntry", recordIdentifier, otherQueryParameters);
        Document readDetailsWithHexName = readAndAssertDomainData( assigningAuthorityAndFacilityMap,
                        TemplateIdHelper.HEALTH_ADAPTER_JOURNAL_DETAIL_READ1_TEMPLATE_ID, detailFilterXml, TemplateIdHelper.HEALTH_ADAPTER_JOURNAL_DETAIL_FILTER,
                        "//genericJournalEntryDetails/patient", 1 );
        List<Element> dataList = readDetailsWithHexName.selectNodes( "//patients/patient/patientJournalEntries" );
        assertTrue( dataList.size() > 0 );
        List<Element> hexNodes = readDetailsWithHexName.selectNodes("//hexBinaryAttachment");
        assertTrue( hexNodes.size()==1);
        

        /// DETAIL READ for base64BinaryAttachmentName
        otherQueryParameters.put("attachmentName", base64BinaryAttachmentName);
        detailFilterXml = FilterBuilder.buildHealthAdapterJournalDetailsFilter("PatientEnteredDietJournalEntry", recordIdentifier, otherQueryParameters);
        Document readDetailsWithBase64Name = readAndAssertDomainData( assigningAuthorityAndFacilityMap,
                        TemplateIdHelper.HEALTH_ADAPTER_JOURNAL_DETAIL_READ1_TEMPLATE_ID, detailFilterXml, TemplateIdHelper.HEALTH_ADAPTER_JOURNAL_DETAIL_FILTER,
                        "//genericJournalEntryDetails/patient", 1 );
        dataList = readDetailsWithBase64Name.selectNodes( "//patients/patient/patientJournalEntries" );
        assertTrue( dataList.size() > 0 );
        List<Element> base64Nodes = readDetailsWithBase64Name.selectNodes("//base64BinaryAttachment");
        assertTrue( base64Nodes.size()==1);
        
        /// READ
        Map<String, String> entryPointFilterMap = new HashMap<String, String>();
        entryPointFilterMap.put( "ID_1", "PatientEnteredDietJournalEntry" );
        String filterXml = createHAFilter( patientId, ASSIGNINGAUTHORITY_HDR, ASSIGNING_FACILITY_HDR, "PatientEnteredDietJournalEntry",
                        TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER, null, null );
        readAndAssertDomainData( assigningAuthorityAndFacilityMap, TemplateIdHelper.HEALTH_ADAPTER_READ1_TEMPLATE_ID, filterXml, TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER,
                        getPatientEnteredDietJournalEntriesEntryPointXpath(), 1 );
        
        // Update journal entry
        String updateRequestXml = createHaCreateXml( patientId, "PatientEnteredDietJournalEntry", TemplateIdHelper.HEALTH_ADAPTER_UPDATE1_TEMPLATE_ID, recordIdentifier, "calories", 1, null );
        Document updateRequest = DocumentHelper.parseText(updateRequestXml);
        String attachmentName2 = updateRequest.selectSingleNode("//binaryAttachments/binaryAttachment/name").getText();
        otherQueryParameters.put("attachmentName", attachmentName2);
        Document updateResponse = updateAndAssertDomainData( TemplateIdHelper.HEALTH_ADAPTER_UPDATE1_TEMPLATE_ID, updateRequestXml, "DIET_JOURNAL", "DIET_JOURNAL_ID" );
        assertNotNull( updateResponse );
        updateRequest=null;
        updateResponse = null;

        // 2nd update of journal entry with attachment having a randomized attachment name
        String secondUpdateRequestXml = createHaCreateXml( patientId, "PatientEnteredDietJournalEntry", TemplateIdHelper.HEALTH_ADAPTER_UPDATE1_TEMPLATE_ID, recordIdentifier, "calories", 1, null );
        Document secondUpdateResponse = updateAndAssertDomainData( TemplateIdHelper.HEALTH_ADAPTER_UPDATE1_TEMPLATE_ID, secondUpdateRequestXml, "DIET_JOURNAL", "DIET_JOURNAL_ID" );
        assertNotNull( secondUpdateResponse );
        secondUpdateResponse = null;
        
        /// DETAIL READ AFTER UPDATE - no attachment name 
        String detailFilterXmlAfterUpdateNoName = FilterBuilder.buildHealthAdapterJournalDetailsFilter("PatientEnteredDietJournalEntry", recordIdentifier, null);
        Document readResponseWithoutOtherQueryParameters = readAndAssertDomainData( assigningAuthorityAndFacilityMap,
                        TemplateIdHelper.HEALTH_ADAPTER_JOURNAL_DETAIL_READ1_TEMPLATE_ID, detailFilterXmlAfterUpdateNoName, TemplateIdHelper.HEALTH_ADAPTER_JOURNAL_DETAIL_FILTER,
                        "//genericJournalEntryDetails/patient", 1 );
        dataList = readResponseWithoutOtherQueryParameters.selectNodes( "//patients/patient/patientJournalEntries" );
        assertTrue( dataList.size() > 0 );
        /*List<Node> attachments = readResponseWithoutOtherQueryParameters.selectNodes("//binaryAttachment");
        assertTrue( attachments.size()==6);        

        /// DETAIL READ AFTER UPDATE - with attachment name 
        String detailFilterXmlAfterUpdateWithName = FilterBuilder.buildHealthAdapterJournalDetailsFilter("PatientEnteredDietJournalEntry", recordIdentifier, otherQueryParameters);
        Document readResponseAfterUpdateWithName = readAndAssertDomainData( assigningAuthorityAndFacilityMap,
                        TemplateIdHelper.HEALTH_ADAPTER_JOURNAL_DETAIL_READ1_TEMPLATE_ID, detailFilterXmlAfterUpdateWithName, TemplateIdHelper.HEALTH_ADAPTER_JOURNAL_DETAIL_FILTER,
                        "//genericJournalEntryDetails/patient", 1 );
        dataList = readResponseAfterUpdateWithName.selectNodes( "//patients/patient/patientJournalEntries" );
        assertTrue( dataList.size() > 0 );
        attachments = readResponseAfterUpdateWithName.selectNodes("//binaryAttachment");
        assertTrue( attachments.size()==3);
        
        // Logically Delete Dietjournal entry

        String logicalDeleteXml = createHADeleteXml( "PatientEnteredDietJournalEntry", TemplateIdHelper.HEALTH_ADAPTER_DELETE1_TEMPLATE_ID, recordIdentifier, LOGICAL_DELETE_RECORD_STATUS );
        deleteAndAssertDomainData( TemplateIdHelper.HEALTH_ADAPTER_DELETE1_TEMPLATE_ID, logicalDeleteXml, "DIET_JOURNAL", "DIET_JOURNAL_ID", true );

        // Physically Delete Diet journal entry
        String physicalDeleteXml = createHADeleteXml( "PatientEnteredDietJournalEntry", TemplateIdHelper.HEALTH_ADAPTER_DELETE1_TEMPLATE_ID, recordIdentifier, DELETE_RECORD_STATUS );
        deleteAndAssertDomainData( TemplateIdHelper.HEALTH_ADAPTER_DELETE1_TEMPLATE_ID, physicalDeleteXml, "DIET_JOURNAL", "DIET_JOURNAL_ID", false );*/
    }

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

        doDelete( uniquePatientIdentity );
        // Create journal entry
        String createRequestXml = createHaCreateXml( uniquePatientIdentity, "PatientEnteredDietJournalEntry", TemplateIdHelper.HEALTH_ADAPTER_CREATE1_TEMPLATE_ID, null, "calories", 1, null );
        Document clinicalDataDocument = createAndAssertDomainData( TemplateIdHelper.HEALTH_ADAPTER_CREATE1_TEMPLATE_ID, createRequestXml );

        List<Element> recordIdentifierList = clinicalDataDocument.selectNodes( RECORD_IDENTIFIER_IDENTITY_XPATH );
        assertTrue( recordIdentifierList.size() == 1 );
        String recordIdentifier = ( ( Element )recordIdentifierList.get( 0 ) ).getText();

        //Read journal entry
        Map<String, String> assigningAuthorityAndFacilityMap = new HashMap<String, String>();
        Map<String, String> entryPointFilterMap = new HashMap<String, String>();
        entryPointFilterMap.put( "ID_1", "PatientEnteredDietJournalEntry" );

        String filterXml = createHAFilter( uniquePatientIdentity, ASSIGNINGAUTHORITY_HDR, ASSIGNING_FACILITY_HDR, "PatientEnteredDietJournalEntry",
                        TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER, null, null );

        readAndAssertDomainData( assigningAuthorityAndFacilityMap, TemplateIdHelper.HEALTH_ADAPTER_READ1_TEMPLATE_ID, filterXml, TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER,
                        getPatientEnteredDietJournalEntriesEntryPointXpath(), 1 );

        //Read Diet Journal with start and end dates

        filterXml = createHAFilter( uniquePatientIdentity, ASSIGNINGAUTHORITY_HDR, ASSIGNING_FACILITY_HDR, "PatientEnteredDietJournalEntry",
                        TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER, START_DATE, getEndDateToday() );
        //List<Element> dataList = clinicalDataDocument.selectNodes( PATIENT_ENTEREDJOURNAL_DOMAINENTRYPOINT_XPATH );
        //assertTrue( dataList.size() > 0 );

        readAndAssertDomainData( assigningAuthorityAndFacilityMap, TemplateIdHelper.HEALTH_ADAPTER_READ1_TEMPLATE_ID, filterXml, TemplateIdHelper.HEALTH_ADAPTER_SINGLE_PATIENT_ALL_DATA_FILTER,
                        getPatientEnteredDietJournalEntriesEntryPointXpath(), 1 );

        // Update journal entry
        String updateRequestXml = createHaCreateXml( uniquePatientIdentity, "PatientEnteredDietJournalEntry", TemplateIdHelper.HEALTH_ADAPTER_UPDATE1_TEMPLATE_ID, recordIdentifier, "calories", 1, null );
        Document clinicalDataDocumentUpdate = updateAndAssertDomainData( TemplateIdHelper.HEALTH_ADAPTER_UPDATE1_TEMPLATE_ID, updateRequestXml, "DIET_JOURNAL", "DIET_JOURNAL_ID" );
        assertNotNull( clinicalDataDocumentUpdate );

        // Logically Delete Dietjournal entry

        String logicalDeleteXml = createHADeleteXml( "PatientEnteredDietJournalEntry", TemplateIdHelper.HEALTH_ADAPTER_DELETE1_TEMPLATE_ID, recordIdentifier, LOGICAL_DELETE_RECORD_STATUS );
        deleteAndAssertDomainData( TemplateIdHelper.HEALTH_ADAPTER_DELETE1_TEMPLATE_ID, logicalDeleteXml, "DIET_JOURNAL", "DIET_JOURNAL_ID", true );

        // Physically Delete Diet journal entry
        String physicalDeleteXml = createHADeleteXml( "PatientEnteredDietJournalEntry", TemplateIdHelper.HEALTH_ADAPTER_DELETE1_TEMPLATE_ID, recordIdentifier, DELETE_RECORD_STATUS );
        deleteAndAssertDomainData( TemplateIdHelper.HEALTH_ADAPTER_DELETE1_TEMPLATE_ID, physicalDeleteXml, "DIET_JOURNAL", "DIET_JOURNAL_ID", false );
    }


    private void doDelete( String patientId )
    {
        hdrJdbcTemplate.update( "DELETE FROM DIET_JOURNAL WHERE PATIENT_IDENTITY = '" + patientId + "'" );
    }


    protected String createHaCreateXml( String patientIdentifier, String entryPoint, String templateId, String recordIdentifier, String calories, int count, String attachmentName )
    {
        Map<String, DomainEntryPoint> domainEntryPointsMap = new HashMap<String, DomainEntryPoint>();
        domainEntryPointsMap.put( templateId, DomainEntryPoint.PatientEnteredDietJournalEntry );
        ClinicalDataBuilder clinicalDataBuilder = new ClinicalDataBuilder();
        clinicalDataBuilder.setDomainEntryPointsMap( domainEntryPointsMap );

        Map<String, ClinicalDomainBuilderFactoryInterface> domainEntryPointsWrappersMap = new HashMap<String, ClinicalDomainBuilderFactoryInterface>();
        HAPatientJournalEntryDietJournalBuilderFactory factory = new HAPatientJournalEntryDietJournalBuilderFactory();
        factory.setDietJournalBuilder( new HADietJournalBuilder( recordIdentifier, calories, attachmentName ) );
        domainEntryPointsWrappersMap.put( "PatientEnteredDietJournalEntry", factory );
        clinicalDataBuilder.setDomainEntryPointsWrappersMap( domainEntryPointsWrappersMap );

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

        Document vdmClinicalDataInsert = clinicalDataBuilder.createClinicalData( templateId, count, patient );

        return vdmClinicalDataInsert.asXML();

    }


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

        Map<String, ClinicalDomainBuilderFactoryInterface> domainEntryPointsWrappersMap = new HashMap<String, ClinicalDomainBuilderFactoryInterface>();
        HAPatientJournalEntryDietJournalBuilderFactory factory = new HAPatientJournalEntryDietJournalBuilderFactory();
        factory.setDietJournalBuilder( new HADietJournalBuilder() );

        domainEntryPointsWrappersMap.put( "PatientEnteredDietJournalEntry", 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();
    }


    private String getEndDateToday( )
    {
        Date today = new Date();
        SimpleDateFormat format = new SimpleDateFormat( "yyyy-MM-dd" );
        String parsed = null;

        try
        {
            parsed = format.format( today );
        }
        catch ( Exception e )
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return parsed.toString();
    }


    protected String getPatientEnteredDietJournalEntriesEntryPointXpath( )
    {
        return "//patientJournalEntries";
    }
}
