package gov.va.med.cds.filter;

import static org.junit.Assert.*;

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

import org.dom4j.Element;
import org.easymock.EasyMock;
import org.junit.Test;

public class Filter100QueryMetadataTest
{

    @Test
    public void testFilter100QueryMetadataAdditionalParametersExtractionString( )
    {
        List<Element> specialized = new ArrayList<Element>();
        List<Element> otherParams = new ArrayList<Element>();
        
        // mocks
        Element entryFilterMock = EasyMock.createMock( Element.class );
        Element domainEntryPointMock = EasyMock.createMock( Element.class );
        Element otherQueryParametersMock = EasyMock.createMock( Element.class );
        Element paramMock = EasyMock.createMock( Element.class );
        specialized.add( otherQueryParametersMock );
        otherParams.add( paramMock );
        
        EasyMock.expect( entryFilterMock.attributeValue( "queryName" ) ).andReturn("queryName");
        EasyMock.expect( entryFilterMock.attributeValue( "countOnly" ) ).andReturn("false");
        EasyMock.expect( entryFilterMock.attributeValue( "pageNumber" ) ).andReturn(null);
        EasyMock.expect( entryFilterMock.attributeValue( "pageSize" ) ).andReturn(null);
        EasyMock.expect( entryFilterMock.attributeValue( "isPatientCentric" ) ).andReturn("false").anyTimes();
        EasyMock.expect( entryFilterMock.attributeValue( "isSiteCentric" ) ).andReturn("false").anyTimes();
        EasyMock.expect( entryFilterMock.attributeValue( "facilityId" ) ).andReturn(null).anyTimes();
        EasyMock.expect( entryFilterMock.elements()).andReturn( specialized );
        EasyMock.expect( otherQueryParametersMock.getName()).andReturn( "otherQueryParameters" );
        EasyMock.expect( entryFilterMock.element( "queryTimeoutSeconds" ) ).andReturn(null);
        EasyMock.expect( entryFilterMock.element( "startDate" ) ).andReturn(null).anyTimes();
        EasyMock.expect( entryFilterMock.element( "endDate" ) ).andReturn(null).anyTimes();
        EasyMock.expect( entryFilterMock.elements( "recordIdentifiers" ) ).andReturn(null);
        
        EasyMock.expect( entryFilterMock.element( "otherQueryParameters" ) ).andReturn(otherQueryParametersMock);
        EasyMock.expect( otherQueryParametersMock.elements() ).andReturn( otherParams );
        EasyMock.expect( paramMock.attributeValue("name") ).andReturn("someName").anyTimes();
        EasyMock.expect( paramMock.attributeValue("type") ).andReturn("string").anyTimes();
        EasyMock.expect( paramMock.elementTextTrim( "value" ) ).andReturn( "stringValue" );
        
        EasyMock.expect( entryFilterMock.element( "xpathQuery" ) ).andReturn(null);
        EasyMock.expect( entryFilterMock.element( "jsonPathQuery" ) ).andReturn(null);
        EasyMock.expect( entryFilterMock.element( "xpathExtractor" ) ).andReturn(null);
        EasyMock.expect( entryFilterMock.element( "xpathFilter" ) ).andReturn(null);
        
        EasyMock.expect( entryFilterMock.elements() ).andReturn(new ArrayList<Element>()).anyTimes();
        EasyMock.expect( entryFilterMock.element( "domainEntryPoint" ) ).andReturn( domainEntryPointMock );
        EasyMock.expect( domainEntryPointMock.getTextTrim() ).andReturn("domainEntryPointText");
        
        EasyMock.replay( entryFilterMock, domainEntryPointMock, otherQueryParametersMock, paramMock);
        
        EntryFilterInterface entryFilter = new Filter100QueryMetadata( entryFilterMock, "TEMPLATE_ID", UUID.randomUUID().toString() );
        ParameterMapInterface parameterMap = entryFilter.getAdditionalParametersMap();
        QueryParameter queryParam = parameterMap.getParameterValue( "someName" );
        assertEquals( "string", queryParam.getType() );
        assertEquals( "stringValue", queryParam.getValue() );
        
        EasyMock.verify( entryFilterMock, domainEntryPointMock, otherQueryParametersMock, paramMock );
    }
    
    
    @Test
    public void testFilter100QueryMetadataAdditionalParametersExtractionList( )
    {
        List<Element> specialized = new ArrayList<Element>();
        List<Element> otherParams = new ArrayList<Element>();
        List<Element> listElements = new ArrayList<Element>();
              
        // mocks
        Element entryFilterMock = EasyMock.createMock( Element.class );
        Element domainEntryPointMock = EasyMock.createMock( Element.class );
        
        Element otherQueryParametersMock = EasyMock.createMock( Element.class );
        specialized.add( otherQueryParametersMock );
        
        Element paramMock = EasyMock.createMock( Element.class );
        otherParams.add( paramMock );
        
        Element listElement1 = EasyMock.createMock( Element.class );
        Element listElement2 = EasyMock.createMock( Element.class );
        Element listElement3 = EasyMock.createMock( Element.class );
        
        listElements.add(listElement1);
        listElements.add(listElement2);
        listElements.add(listElement3);
        
        EasyMock.expect( entryFilterMock.attributeValue( "queryName" ) ).andReturn("queryName");
        EasyMock.expect( entryFilterMock.attributeValue( "countOnly" ) ).andReturn("false");
        EasyMock.expect( entryFilterMock.attributeValue( "pageNumber" ) ).andReturn(null);
        EasyMock.expect( entryFilterMock.attributeValue( "pageSize" ) ).andReturn(null);
        EasyMock.expect( entryFilterMock.attributeValue( "isPatientCentric" ) ).andReturn("false").anyTimes();
        EasyMock.expect( entryFilterMock.attributeValue( "isSiteCentric" ) ).andReturn("false").anyTimes();
        EasyMock.expect( entryFilterMock.attributeValue( "facilityId" ) ).andReturn(null).anyTimes();
        EasyMock.expect( entryFilterMock.elements()).andReturn( specialized );
        EasyMock.expect( otherQueryParametersMock.getName()).andReturn( "otherQueryParameters" );
        EasyMock.expect( entryFilterMock.element( "queryTimeoutSeconds" ) ).andReturn(null);
        EasyMock.expect( entryFilterMock.element( "startDate" ) ).andReturn(null).anyTimes();
        EasyMock.expect( entryFilterMock.element( "endDate" ) ).andReturn(null).anyTimes();
        EasyMock.expect( entryFilterMock.elements( "recordIdentifiers" ) ).andReturn(null);
        
        EasyMock.expect( entryFilterMock.element( "otherQueryParameters" ) ).andReturn(otherQueryParametersMock);
        EasyMock.expect( otherQueryParametersMock.elements() ).andReturn( otherParams );
        EasyMock.expect( paramMock.attributeValue("name") ).andReturn("someName").anyTimes();
        EasyMock.expect( paramMock.attributeValue("type") ).andReturn("list").anyTimes();
        EasyMock.expect( paramMock.elements() ).andReturn( listElements );
        EasyMock.expect( listElement1.getTextTrim() ).andReturn( "ONE" );
        EasyMock.expect( listElement2.getTextTrim() ).andReturn( "TWO" );
        EasyMock.expect( listElement3.getTextTrim() ).andReturn( "THREE" );
        
        EasyMock.expect( entryFilterMock.element( "xpathQuery" ) ).andReturn(null);
        EasyMock.expect( entryFilterMock.element( "jsonPathQuery" ) ).andReturn(null);
        EasyMock.expect( entryFilterMock.element( "xpathExtractor" ) ).andReturn(null);
        EasyMock.expect( entryFilterMock.element( "xpathFilter" ) ).andReturn(null);
        
        EasyMock.expect( entryFilterMock.elements() ).andReturn(new ArrayList<Element>()).anyTimes();
        EasyMock.expect( entryFilterMock.element( "domainEntryPoint" ) ).andReturn( domainEntryPointMock );
        EasyMock.expect( domainEntryPointMock.getTextTrim() ).andReturn("domainEntryPointText");
        
        EasyMock.replay( entryFilterMock, domainEntryPointMock, otherQueryParametersMock, paramMock, listElement1, listElement2, listElement3);
        
        EntryFilterInterface entryFilter = new Filter100QueryMetadata( entryFilterMock, "TEMPLATE_ID", UUID.randomUUID().toString() );
        ParameterMapInterface parameterMap = entryFilter.getAdditionalParametersMap();
        QueryParameter queryParam = parameterMap.getParameterValue( "someName" );
        assertEquals( "list", queryParam.getType() );
        assertTrue( queryParam.getValue() instanceof List);
        
        List<QueryParameter<String>> params = (List<QueryParameter<String>>)queryParam.getValue();
        assertTrue( params.size() == 3 );
        assertTrue( "ONE".equals( params.get(0) ));
        assertTrue( "TWO".equals( params.get(1) ));
        assertTrue( "THREE".equals( params.get(2) ));
        
        EasyMock.verify( entryFilterMock, domainEntryPointMock, otherQueryParametersMock, paramMock, listElement1, listElement2, listElement3 );
    }
    
    
    @Test
    public void testFilter100QueryMetadataAdditionalParametersExtractionDateRanges( )
    {
        List<Element> specialized = new ArrayList<Element>();
        List<Element> otherParams = new ArrayList<Element>();
        List<Element> dateRange1Params = new ArrayList<Element>();
        List<Element> dateRange2Params = new ArrayList<Element>();
              
        // mocks
        Element entryFilterMock = EasyMock.createMock( Element.class );
        Element domainEntryPointMock = EasyMock.createMock( Element.class );
        
        Element otherQueryParametersMock = EasyMock.createMock( Element.class );
        specialized.add( otherQueryParametersMock );
        
        Element dateRange1 = EasyMock.createMock( Element.class );
        Element dr1Begin = EasyMock.createMock( Element.class );
        Element dr1End = EasyMock.createMock( Element.class );
        Element dateRange2 = EasyMock.createMock( Element.class );
        Element dr2Begin = EasyMock.createMock( Element.class );
        Element dr2End = EasyMock.createMock( Element.class );
        
        otherParams.add(dateRange1);
        otherParams.add(dateRange2);
        dateRange1Params.add(dr1Begin);
        dateRange1Params.add( dr1End );
        dateRange2Params.add(dr2Begin);
        dateRange2Params.add( dr2End );
        
        EasyMock.expect( entryFilterMock.attributeValue( "queryName" ) ).andReturn("queryName");
        EasyMock.expect( entryFilterMock.attributeValue( "countOnly" ) ).andReturn("false");
        EasyMock.expect( entryFilterMock.attributeValue( "pageNumber" ) ).andReturn(null);
        EasyMock.expect( entryFilterMock.attributeValue( "pageSize" ) ).andReturn(null);
        EasyMock.expect( entryFilterMock.attributeValue( "isPatientCentric" ) ).andReturn("false").anyTimes();
        EasyMock.expect( entryFilterMock.attributeValue( "isSiteCentric" ) ).andReturn("false").anyTimes();
        EasyMock.expect( entryFilterMock.attributeValue( "facilityId" ) ).andReturn(null).anyTimes();
        EasyMock.expect( entryFilterMock.elements()).andReturn( specialized );
        EasyMock.expect( otherQueryParametersMock.getName()).andReturn( "otherQueryParameters" );
        EasyMock.expect( entryFilterMock.element( "queryTimeoutSeconds" ) ).andReturn(null);
        EasyMock.expect( entryFilterMock.element( "startDate" ) ).andReturn(null).anyTimes();
        EasyMock.expect( entryFilterMock.element( "endDate" ) ).andReturn(null).anyTimes();
        EasyMock.expect( entryFilterMock.elements( "recordIdentifiers" ) ).andReturn(null);
        
        EasyMock.expect( entryFilterMock.element( "otherQueryParameters" ) ).andReturn(otherQueryParametersMock);
        EasyMock.expect( otherQueryParametersMock.elements() ).andReturn( otherParams );
        
        EasyMock.expect( dateRange1.elements() ).andReturn( dateRange1Params );
        EasyMock.expect( dateRange1.attributeValue("name") ).andReturn("createDate").anyTimes();
        EasyMock.expect( dateRange1.attributeValue("type") ).andReturn("dateRange").anyTimes();
        EasyMock.expect( dr1Begin.getTextTrim() ).andReturn( "2010-01-01" );
        EasyMock.expect( dr1End.getTextTrim() ).andReturn( "2010-12-31" );
        
        EasyMock.expect( dateRange2.elements() ).andReturn( dateRange2Params );
        EasyMock.expect( dateRange2.attributeValue("name") ).andReturn("anotherDate").anyTimes();
        EasyMock.expect( dateRange2.attributeValue("type") ).andReturn("dateRange").anyTimes();
        EasyMock.expect( dr2Begin.getTextTrim() ).andReturn( "2010-02-02" );
        EasyMock.expect( dr2End.getTextTrim() ).andReturn( "2010-12-30" );
        
        EasyMock.expect( entryFilterMock.element( "xpathQuery" ) ).andReturn(null);
        EasyMock.expect( entryFilterMock.element( "jsonPathQuery" ) ).andReturn(null);
        EasyMock.expect( entryFilterMock.element( "xpathExtractor" ) ).andReturn(null);
        EasyMock.expect( entryFilterMock.element( "xpathFilter" ) ).andReturn(null);
        
        EasyMock.expect( entryFilterMock.elements() ).andReturn(new ArrayList<Element>()).anyTimes();
        EasyMock.expect( entryFilterMock.element( "domainEntryPoint" ) ).andReturn( domainEntryPointMock );
        EasyMock.expect( domainEntryPointMock.getTextTrim() ).andReturn("domainEntryPointText");
        
        EasyMock.replay( entryFilterMock, domainEntryPointMock, otherQueryParametersMock, dateRange1, dr1Begin, dr1End, dateRange2, dr2Begin, dr2End);
        
        EntryFilterInterface entryFilter = new Filter100QueryMetadata( entryFilterMock, "TEMPLATE_ID", UUID.randomUUID().toString() );
        ParameterMapInterface parameterMap = entryFilter.getAdditionalParametersMap();
        QueryParameter dateParam1 = parameterMap.getParameterValue( "createDate" );
        QueryParameter dateParam2 = parameterMap.getParameterValue( "anotherDate" );
        
        assertEquals( "dateRange", dateParam1.getType() );
        assertEquals( "dateRange", dateParam2.getType() );
        
        
        
//        assertTrue( queryParam.getValue() instanceof Map<K, V>);
//        
//        List<QueryParameter<String>> params = (List<QueryParameter<String>>)queryParam.getValue();
//        assertTrue( params.size() == 3 );
//        assertTrue( "ONE".equals( params.get(0) ));
//        assertTrue( "TWO".equals( params.get(1) ));
//        assertTrue( "THREE".equals( params.get(2) ));
        
        EasyMock.verify( entryFilterMock, domainEntryPointMock, otherQueryParametersMock, dateRange1, dr1Begin, dr1End, dateRange2, dr2Begin, dr2End );
    }

}
