/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  The ASF licenses this file to You
 * under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.  For additional information regarding
 * copyright in this work, please see the NOTICE file in the top level
 * directory of this distribution.
 */
package org.apache.usergrid.persistence.index.impl;


import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicLong;

import com.google.common.base.Optional;
import org.apache.usergrid.persistence.core.CassandraFig;
import org.apache.usergrid.persistence.index.*;
import org.apache.usergrid.persistence.model.field.*;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.commons.lang3.time.StopWatch;

import org.apache.usergrid.persistence.core.scope.ApplicationScopeImpl;
import org.apache.usergrid.persistence.core.test.UseModules;
import org.apache.usergrid.persistence.core.util.Health;
import org.apache.usergrid.persistence.index.guice.TestIndexModule;
import org.apache.usergrid.persistence.index.utils.UUIDUtils;
import org.apache.usergrid.persistence.model.entity.Entity;
import org.apache.usergrid.persistence.model.entity.Id;
import org.apache.usergrid.persistence.model.entity.SimpleId;
import org.apache.usergrid.persistence.model.util.EntityUtils;
import org.apache.usergrid.persistence.model.util.UUIDGenerator;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;
import com.google.inject.Inject;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;


@RunWith( EsRunner.class )
@UseModules( { TestIndexModule.class } )
public class EntityIndexTest extends BaseIT {

    private static final Logger logger = LoggerFactory.getLogger(EntityIndexTest.class);

    @Inject
    public EntityIndexFactory eif;


    @Inject
    public IndexFig fig;

    @Inject
    public IndexProducer indexProducer;

    @Inject
    public CassandraFig cassandraFig;

    @Inject
    @Rule
    public ElasticSearchRule elasticSearchRule;
    private EntityIndex entityIndex;
    private SimpleId appId;

    @Before
    public void setup(){
        appId = new SimpleId(UUID.randomUUID(), "application" );

        IndexLocationStrategy strategy =  new TestIndexIdentifier(cassandraFig,fig,new ApplicationScopeImpl(appId));

        entityIndex = eif.createEntityIndex( strategy );
    }

    @Test
    public void testIndex() throws IOException, InterruptedException {



        final String entityType = "thing";
        IndexEdge searchEdge = new IndexEdgeImpl( appId, "things", SearchEdge.NodeType.SOURCE, 1 );
        final SearchTypes searchTypes = SearchTypes.fromTypes( entityType );

        insertJsonBlob( entityType, searchEdge, "/sample-large.json", 101, 0 );


        testQueries( searchEdge, searchTypes  );
    }


    /**
     * Tests that when types conflict, but should match queries they work
     */
    @Test
    public void testIndexVariations() throws IOException {
        Id appId = new SimpleId( "application" );
        final String entityType = "thing";
        IndexEdge indexEdge = new IndexEdgeImpl( appId, "things", SearchEdge.NodeType.SOURCE, 1 );
        final SearchTypes searchTypes = SearchTypes.fromTypes( entityType );
        EntityIndexBatch batch = entityIndex.createBatch();


        UUID uuid = UUID.randomUUID();
        Entity entity1 = new Entity( entityType );
        EntityUtils.setVersion(entity1, UUIDGenerator.newTimeUUID());
        entity1.setField(new UUIDField(IndexingUtils.ENTITY_ID_FIELDNAME, UUID.randomUUID()));
        entity1.setField( new StringField( "testfield", "test" ) );
        entity1.setField(new IntegerField("ordinal", 0));
        entity1.setField(new UUIDField("testuuid", uuid));
        entity1.setField( new NullField("nullfield"));


        batch.index( indexEdge, entity1 );
        indexProducer.put(batch.build()).subscribe();


        Entity entity2 = new Entity( entityType );
        EntityUtils.setVersion(entity2, UUIDGenerator.newTimeUUID());


        List<String> list = new ArrayList<>();
        list.add("test");
        entity2.setField(new ArrayField<>("testfield", list));
        entity2.setField(new IntegerField("ordinal", 1));


        batch.index( indexEdge, entity2 );
        indexProducer.put(batch.build()).subscribe();;

        entityIndex.refreshAsync().toBlocking().first();


        StopWatch timer = new StopWatch();
        timer.start();
        CandidateResults candidateResults =
            entityIndex.search( indexEdge, searchTypes, "select * where testfield = 'test' order by ordinal", 100, 0, false );

        timer.stop();

        assertEquals( 2, candidateResults.size() );
        logger.debug( "Query time {}ms", timer.getTime() );

        final CandidateResult candidate1 = candidateResults.get(0);

        //check the id and version
        assertEquals( entity1.getId(), candidate1.getId() );
        assertEquals(entity1.getVersion(), candidate1.getVersion());


        final CandidateResult candidate2 = candidateResults.get(1);

        //check the id and version
        assertEquals( entity2.getId(), candidate2.getId() );
        assertEquals( entity2.getVersion(), candidate2.getVersion() );

        //make sure we can query uuids out as strings and not wrapped
        candidateResults =
            entityIndex.search( indexEdge, searchTypes, "select * where testuuid = '"+uuid+"'", 100, 0, false );
        assertEquals(entity1.getId(),candidateResults.get(0).getId());

        candidateResults =
            entityIndex.search( indexEdge, searchTypes, "select * where testuuid = "+uuid, 100, 0, false);
        assertEquals(entity1.getId(),candidateResults.get(0).getId());
    }


    @Test
    public void testIndexThreads() throws IOException {


        long now = System.currentTimeMillis();
        final int threads = 20;
        final int size = 30;

        final String entityType = "thing";

        final CountDownLatch latch = new CountDownLatch( threads );
        final AtomicLong failTime = new AtomicLong( 0 );
        InputStream is = this.getClass().getResourceAsStream("/sample-large.json");
        ObjectMapper mapper = new ObjectMapper();
        final List<Object> sampleJson = mapper.readValue( is, new TypeReference<List<Object>>() {} );
        for ( int i = 0; i < threads; i++ ) {

            final IndexEdge indexEdge = new IndexEdgeImpl( appId, "things", SearchEdge.NodeType.SOURCE, i );

            Thread thread = new Thread( () -> {
                try {


                    EntityIndexBatch batch = entityIndex.createBatch();
                    insertJsonBlob( sampleJson, batch, entityType, indexEdge, size, 0 );
                    indexProducer.put(batch.build()).subscribe();;
                }
                catch ( Exception e ) {
                    synchronized ( failTime ) {
                        if ( failTime.get() == 0 ) {
                            failTime.set( System.currentTimeMillis() );
                        }
                    }
                    System.out.println( e.toString() );
                    fail( "threw exception" );
                }
                finally {
                    latch.countDown();
                }
            } );
            thread.start();
        }
        try {
            latch.await();
        }
        catch ( InterruptedException ie ) {
            throw new RuntimeException( ie );
        }
        assertTrue( "system must have failed at " + ( failTime.get() - now ), failTime.get() == 0 );
    }




    @Test
    public void testAddMultipleIndexes() throws IOException {


        final String entityType = "thing";
        IndexEdge searchEdge = new IndexEdgeImpl( appId, "things", SearchEdge.NodeType.SOURCE, 10 );
        final SearchTypes searchTypes = SearchTypes.fromTypes(entityType);

        insertJsonBlob( entityType, searchEdge, "/sample-large.json", 101, 0);


        testQueries(searchEdge, searchTypes);

        entityIndex.addIndex(UUID.randomUUID()+"_v2", 1, 0, "one");

        insertJsonBlob( entityType, searchEdge, "/sample-large.json", 101, 100);

        //Hilda Youn
        testQuery( searchEdge, searchTypes,  "name = 'Hilda Young'", 1 );

        testQuery( searchEdge, searchTypes,  "name = 'Lowe Kelley'", 1 );

        logger.info("hi");
    }


    @Test
    public void testDeleteWithAlias() throws IOException {


        final String entityType = "thing";
        IndexEdge searchEdge = new IndexEdgeImpl( appId, "things", SearchEdge.NodeType.SOURCE, 1 );
        final SearchTypes searchTypes = SearchTypes.fromTypes( entityType );

        insertJsonBlob(  entityType, searchEdge, "/sample-large.json", 1, 0 );


        entityIndex.addIndex(UUID.randomUUID() + "v2", 1, 0, "one");
        entityIndex.refreshAsync().toBlocking().first();

        insertJsonBlob(  entityType, searchEdge, "/sample-large.json", 1, 1 );

        CandidateResults crs = testQuery( searchEdge, searchTypes, "name = 'Bowers Oneil'", 1 );

        EntityIndexBatch entityIndexBatch = entityIndex.createBatch();
        entityIndexBatch.deindex(searchEdge, crs.get(0));
        indexProducer.put(entityIndexBatch.build()).subscribe();
        entityIndex.refreshAsync().toBlocking().first();

        //Hilda Youn
        testQuery(searchEdge, searchTypes, "name = 'Bowers Oneil'", 0);
    }


    private void insertJsonBlob( String entityType, IndexEdge indexEdge,
                                 String filePath, final int max, final int startIndex ) throws IOException {
        InputStream is = this.getClass().getResourceAsStream( filePath );
        ObjectMapper mapper = new ObjectMapper();
        List<Object> sampleJson = mapper.readValue(is, new TypeReference<List<Object>>() {
        });
        EntityIndexBatch batch = entityIndex.createBatch();
        insertJsonBlob(sampleJson, batch, entityType, indexEdge, max, startIndex);
        indexProducer.put(batch.build()).subscribe();;
        EntityIndex.IndexRefreshCommandInfo info =  entityIndex.refreshAsync().toBlocking().first();
        long time = info.getExecutionTime();
        logger.info("refresh took ms:" + time);
    }


    private void insertJsonBlob( List<Object> sampleJson, EntityIndexBatch batch, String entityType,
                                 IndexEdge indexEdge, final int max, final int startIndex ) throws IOException {
        int count = 0;
        StopWatch timer = new StopWatch();
        timer.start();


        if ( startIndex > 0 ) {
            for ( int i = 0; i < startIndex; i++ ) {
                sampleJson.remove( 0 );
            }
        }

        for ( Object o : sampleJson ) {

            Map<String, Object> item = ( Map<String, Object> ) o;

            Entity entity = new Entity( entityType );
            entity = EntityIndexMapUtils.fromMap( entity, item );
            EntityUtils.setVersion( entity, UUIDGenerator.newTimeUUID() );
            entity.setField( new UUIDField( IndexingUtils.ENTITY_ID_FIELDNAME, UUID.randomUUID() ) );
            batch.index( indexEdge, entity );

            if ( ++count > max ) {
                break;
            }
        }

        timer.stop();
        logger.info( "Total time to index {} entries {}ms, average {}ms/entry",
            new Object[] { count, timer.getTime(), timer.getTime() / count } );
    }


    @Test
    public void testDeindex() {

       IndexEdge searchEdge = new IndexEdgeImpl( appId, "fastcars", SearchEdge.NodeType.SOURCE, 1 );

        Map entityMap = new HashMap() {{
            put( "name", "Ferrari 212 Inter" );
            put( "introduced", 1952 );
            put( "topspeed", 215 );
        }};


        Entity entity = EntityIndexMapUtils.fromMap( entityMap );
        EntityUtils.setId(entity, new SimpleId( "fastcar" ) );
        EntityUtils.setVersion(entity, UUIDGenerator.newTimeUUID() );
        entity.setField(new UUIDField(IndexingUtils.ENTITY_ID_FIELDNAME, UUID.randomUUID() ) );

        indexProducer.put(entityIndex.createBatch().index( searchEdge, entity ).build()).subscribe();
        entityIndex.refreshAsync().toBlocking().first();

        CandidateResults candidateResults = entityIndex
            .search( searchEdge, SearchTypes.fromTypes( entity.getId().getType() ), "name contains 'Ferrari*'", 10, 0, false );
        assertEquals( 1, candidateResults.size() );

        EntityIndexBatch batch = entityIndex.createBatch();
        batch.deindex( searchEdge, entity );
        indexProducer.put(batch.build()).subscribe();;
        entityIndex.refreshAsync().toBlocking().first();

        candidateResults = entityIndex
            .search(searchEdge, SearchTypes.fromTypes( entity.getId().getType() ), "name contains 'Ferrari*'", 10, 0, false );
        assertEquals(0, candidateResults.size());
    }



    private CandidateResults testQuery( final SearchEdge scope, final SearchTypes searchTypes,
                                      final String queryString,
                                        final int num ) {

        StopWatch timer = new StopWatch();
        timer.start();
        CandidateResults candidateResults  = entityIndex.search( scope, searchTypes, queryString, 1000, 0, false );

        timer.stop();

        assertEquals(num, candidateResults.size());
        logger.debug("Query time {}ms", timer.getTime());
        return candidateResults;
    }


    private void testQueries( final SearchEdge scope, SearchTypes searchTypes) {

        testQuery( scope, searchTypes, "age > 35", 29 );

        testQuery( scope, searchTypes, "age <= 35", 73 );

        testQuery( scope, searchTypes, "age <= 35 or age > 35", 102 );

        // TODO: uncomment this test when you are ready to fix USERGRID-1314
        // (https://issues.apache.org/jira/browse/USERGRID-1314)
        // testQuery( scope, searchTypes, "name = 'astro*' or age > 35", 29 );

        testQuery( scope, searchTypes, "name = 'Morgan Pierce'", 1 );

        testQuery( scope, searchTypes, "name = 'morgan pierce'", 1 );

        testQuery( scope, searchTypes, "name = 'Morgan'", 0 );

        testQuery( scope, searchTypes, "name contains 'Morgan'", 1 );

        testQuery( scope, searchTypes, "company > 'GeoLogix'", 64 );

        testQuery( scope, searchTypes, "gender = 'female'", 45 );

        testQuery( scope, searchTypes, "name = 'Minerva Harrell' and age > 39", 1 );

        testQuery( scope, searchTypes, "name = 'Minerva Harrell' and age > 39 and age < 41", 1 );

        testQuery( scope, searchTypes, "name = 'Minerva Harrell' and age > 40", 0 );

        testQuery( scope, searchTypes, "name = 'Minerva Harrell' and age >= 40", 1 );

        testQuery( scope, searchTypes, "name = 'Minerva Harrell' and age <= 40", 1 );

        testQuery( scope, searchTypes, "name = 'Morgan* '", 1 );

        testQuery( scope, searchTypes, "name = 'Morgan*'", 1 );


        // test a couple of array sub-property queries

        int totalUsers = 102;

        // nobody has a friend named Jack the Ripper
        testQuery( scope, searchTypes, "friends.name = 'Jack the Ripper'", 0 );

        // everybody doesn't have a friend named Jack the Ripper
        testQuery( scope, searchTypes, "not (friends.name = 'Jack the Ripper')", totalUsers );

        // one person has a friend named Shari Hahn
        testQuery( scope, searchTypes, "friends.name = 'Wendy Moody'", 1 );

        // everybody but 1 doesn't have a friend named Shari Hahh
        testQuery( scope, searchTypes, "not (friends.name = 'Shari Hahn')", totalUsers - 1 );
    }


    /**
     * Tests that Entity-to-map and Map-to-entity round trip works.
     */
    @Test
    public void testEntityIndexMapUtils() throws IOException {

        InputStream is = this.getClass().getResourceAsStream( "/sample-small.json" );
        ObjectMapper mapper = new ObjectMapper();
        List<Object> contacts = mapper.readValue( is, new TypeReference<List<Object>>() {} );

        for ( Object o : contacts ) {

            Map<String, Object> map1 = ( Map<String, Object> ) o;

            // convert map to entity
            Entity entity1 = EntityIndexMapUtils.fromMap( map1 );

            // convert entity back to map
            Map map2 = EntityIndexMapUtils.toMap( entity1 );

            // the two maps should be the same
            Map diff = Maps.difference( map1, map2 ).entriesDiffering();
            assertEquals( 0, diff.size() );
        }
    }



    @Test
    public void deleteVerification() throws Throwable {


        Id ownerId = new SimpleId( "owner" );



        IndexEdge indexSCope = new IndexEdgeImpl( ownerId, "user", SearchEdge.NodeType.SOURCE, 10 );




        final String middleName = "middleName" + UUIDUtils.newTimeUUID();

        Map entityMap = new HashMap() {{
            put( "username", "edanuff" );
            put( "email", "ed@anuff.com" );
            put( "middlename", middleName );
        }};

        Entity user = EntityIndexMapUtils.fromMap( entityMap );
        EntityUtils.setId( user, new SimpleId( "edanuff" ) );
        EntityUtils.setVersion( user, UUIDGenerator.newTimeUUID() );


        EntityIndexBatch batch = entityIndex.createBatch();

        batch.index( indexSCope, user );
        indexProducer.put(batch.build()).subscribe();;
        entityIndex.refreshAsync().toBlocking().first();

        final String query = "where username = 'edanuff'";

        CandidateResults r = entityIndex.search( indexSCope, SearchTypes.fromTypes( "edanuff" ), query, 10, 0, false);
        assertEquals( user.getId(), r.get( 0 ).getId());

        batch.deindex( indexSCope, user.getId(), user.getVersion() );
        indexProducer.put(batch.build()).subscribe();;
        entityIndex.refreshAsync().toBlocking().first();

        // EntityRef


        r = entityIndex.search( indexSCope, SearchTypes.fromTypes( "edanuff" ), query, 10, 0, false );

        assertFalse( r.iterator().hasNext() );
    }


    @Test
    public void multiValuedTypes() {

        Id appId = new SimpleId( "entityindextest" );
        Id ownerId = new SimpleId( "multivaluedtype" );


        IndexEdge indexScope = new IndexEdgeImpl( ownerId, "user", SearchEdge.NodeType.SOURCE, 10 );



        entityIndex.createBatch();

        // Bill has favorites as string, age as string and retirement goal as number
        Map billMap = new HashMap() {{
            put( "username", "bill" );
            put( "email", "bill@example.com" );
            put( "age", "thirtysomething" );
            put( "favorites", "scallops, croquet, wine" );
            put( "retirementGoal", 100000 );
        }};
        Entity bill = EntityIndexMapUtils.fromMap( billMap );
        EntityUtils.setId( bill, new SimpleId( UUIDGenerator.newTimeUUID(), "user" ) );
        EntityUtils.setVersion( bill, UUIDGenerator.newTimeUUID() );

        EntityIndexBatch batch = entityIndex.createBatch();

        batch.index( indexScope, bill );

        // Fred has age as int, favorites as object and retirement goal as object
        Map fredMap = new HashMap() {{
            put( "username", "fred" );
            put( "email", "fred@example.com" );
            put( "age", 41 );
            put( "favorites", new HashMap<String, Object>() {{
                put( "food", "cheezewiz" );
                put( "sport", "nascar" );
                put( "beer", "budwizer" );
            }} );
            put( "retirementGoal", new HashMap<String, Object>() {{
                put( "car", "Firebird" );
                put( "home", "Mobile" );
            }} );
        }};
        Entity fred = EntityIndexMapUtils.fromMap( fredMap );
        EntityUtils.setId( fred, new SimpleId( UUIDGenerator.newTimeUUID(), "user" ) );
        EntityUtils.setVersion( fred, UUIDGenerator.newTimeUUID() );
        batch.index( indexScope, fred);

        indexProducer.put(batch.build()).subscribe();;
        entityIndex.refreshAsync().toBlocking().first();

        final SearchTypes searchTypes = SearchTypes.fromTypes( "user" );


        CandidateResults r = entityIndex.search( indexScope, searchTypes, "where username = 'bill'", 10, 0, false);
        assertEquals( bill.getId(), r.get( 0 ).getId() );

        r = entityIndex.search( indexScope, searchTypes, "where username = 'fred'", 10, 0, false);
        assertEquals(fred.getId(), r.get(0).getId());

        r = entityIndex.search( indexScope, searchTypes, "where age = 41", 10, 0, false);
        assertEquals(fred.getId(), r.get(0).getId());

        r = entityIndex.search( indexScope, searchTypes, "where age = 'thirtysomething'", 10, 0, false);
        assertEquals(bill.getId(), r.get(0).getId());
    }


    @Test
    public void healthTest() {
        Id appId = new SimpleId( "entityindextest" );
        assertNotEquals( "cluster should be ok", Health.RED, entityIndex.getClusterHealth() );
        assertEquals( "index should be ready", Health.GREEN, entityIndex.getIndexHealth() );
        entityIndex.refreshAsync().toBlocking().first();
        assertNotEquals( "cluster should be fine", Health.RED, entityIndex.getIndexHealth() );
        assertNotEquals( "cluster should be ready now", Health.RED, entityIndex.getClusterHealth() );
    }


    @Test
    public void testCursorFormat() throws Exception {

        String myType = UUID.randomUUID().toString();
        Id ownerId = new SimpleId( UUID.randomUUID(),"owner" );



        IndexEdge indexEdge = new IndexEdgeImpl( ownerId, "users", SearchEdge.NodeType.SOURCE, 10 );


        final EntityIndexBatch batch = entityIndex.createBatch();


        final int size = 100;

        final List<Id> entityIds = new ArrayList<>( size );


        for ( int i = 0; i < size; i++ ) {

            final String middleName = "middleName" + UUIDUtils.newTimeUUID();

            final int ordinal = i;

            Map entityMap = new HashMap() {{
                put( "username", "edanuff" );
                put( "email", "ed@anuff.com" );
                put( "middlename", middleName );
                put( "ordinal", ordinal );
                put( "mytype", myType);
            }};

            final Id userId = new SimpleId( "user" );

            Entity user = EntityIndexMapUtils.fromMap( entityMap );
            EntityUtils.setId( user, userId );
            EntityUtils.setVersion( user, UUIDGenerator.newTimeUUID() );

            entityIds.add(userId );


            batch.index( indexEdge, user );
        }


        indexProducer.put(batch.build()).subscribe();;

        entityIndex.refreshAsync().toBlocking().first();


        final int limit = 5;


        final int expectedPages = size / limit;


        Optional<Integer> offset = Optional.absent();
        UUID lastId = null;
        final String query = "select * where mytype='"+myType+"' order by ordinal asc";
        int i ;
        for ( i=0; i < expectedPages; i++ ) {
            final CandidateResults results = !offset.isPresent()
                ? entityIndex.search( indexEdge, SearchTypes.allTypes(), query, limit, 0, false )
                : entityIndex.search(indexEdge, SearchTypes.allTypes(), query, limit, i * limit, false);

            assertEquals(limit, results.size());

            int ordinal = 0;//i == 0 ? 0 : 1;
            assertNotEquals("Scroll matches last item from previous page",lastId, results.get(ordinal).getId().getUuid());
            lastId = results.get(limit -1).getId().getUuid();
            offset = results.getOffset();
            assertEquals("Failed on page "+i, results.get( ordinal ).getId(), entityIds.get( i*limit ) );
        }

        //get our next page, we shouldn't get a cursor
        final CandidateResults results = entityIndex.search(indexEdge, SearchTypes.allTypes(), query, limit, i * limit, false);

        assertEquals( 0, results.size() );
        assertFalse(results.hasOffset());
    }


    @Test
    public void queryByUUID() throws Throwable {

        Id appId = new SimpleId( "application" );
        Id ownerId = new SimpleId( "owner" );



        IndexEdge indexSCope = new IndexEdgeImpl( ownerId, "user", SearchEdge.NodeType.SOURCE, 10 );




        final UUID searchUUID = UUIDGenerator.newTimeUUID();

        Map entityMap = new HashMap() {{
            put( "searchUUID", searchUUID );
        }};

        Entity user = EntityIndexMapUtils.fromMap( entityMap );

        final Id entityId = new SimpleId( "entitytype" );

        EntityUtils.setId( user, entityId );
        EntityUtils.setVersion( user, UUIDGenerator.newTimeUUID() );


        EntityIndexBatch batch = entityIndex.createBatch();

        batch.index( indexSCope, user );
        indexProducer.put(batch.build()).subscribe();;
        entityIndex.refreshAsync().toBlocking().first();

        final String query = "where searchUUID = " + searchUUID;

        final CandidateResults r =
            entityIndex.search( indexSCope, SearchTypes.fromTypes(entityId.getType()), query, 10, 0, false);
        assertEquals(user.getId(), r.get(0).getId());
    }


    @Test
    public void queryByStringWildCardSpaces() throws Throwable {

        Id appId = new SimpleId( "application" );
        Id ownerId = new SimpleId( "owner" );



        IndexEdge indexSCope = new IndexEdgeImpl( ownerId, "user", SearchEdge.NodeType.SOURCE, 10 );




        Map entityMap = new HashMap() {{
            put( "string", "I am a search string" );
        }};

        Entity user = EntityIndexMapUtils.fromMap( entityMap );

        final Id entityId = new SimpleId( "entitytype" );

        EntityUtils.setId( user, entityId );
        EntityUtils.setVersion( user, UUIDGenerator.newTimeUUID() );


        EntityIndexBatch batch = entityIndex.createBatch();

        batch.index(indexSCope, user);
        indexProducer.put(batch.build()).subscribe();;
        entityIndex.refreshAsync().toBlocking().first();

        final String query = "where string = 'I am*'";

        final CandidateResults r =
            entityIndex.search( indexSCope, SearchTypes.fromTypes( entityId.getType() ), query, 10, 0, false);

        assertEquals(user.getId(), r.get(0).getId());

        //shouldn't match
        final String queryNoWildCard = "where string = 'I am'";

        final CandidateResults noWildCardResults =
            entityIndex.search( indexSCope, SearchTypes.fromTypes( entityId.getType() ), queryNoWildCard, 10, 0, false );

        assertEquals( 0, noWildCardResults.size() );
    }


    @Test
    public void sortyByString() throws Throwable {

        Id appId = new SimpleId( "application" );
        Id ownerId = new SimpleId( "owner" );



        IndexEdge indexSCope = new IndexEdgeImpl( ownerId, "user", SearchEdge.NodeType.SOURCE, 10 );




        /**
         * Ensures sort ordering is correct when more than 1 token is present.  Should order by the unanalyzed field,
         * not the analyzed field
         */

        final Entity first = new Entity( "search" );

        first.setField( new StringField( "string", "alpha long string" ) );


        EntityUtils.setVersion( first, UUIDGenerator.newTimeUUID() );


        final Entity second = new Entity( "search" );

        second.setField(new StringField("string", "bravo long string"));


        EntityUtils.setVersion( second, UUIDGenerator.newTimeUUID() );


        EntityIndexBatch batch = entityIndex.createBatch();
        batch.index(indexSCope, first );
        batch.index( indexSCope, second );
        indexProducer.put(batch.build()).subscribe();;
        entityIndex.refreshAsync().toBlocking().first();


        final String ascQuery = "order by string";

        final CandidateResults ascResults =
            entityIndex.search(indexSCope, SearchTypes.fromTypes( first.getId().getType() ), ascQuery, 10 , 0, false);


        assertEquals( first.getId(), ascResults.get( 0).getId() );
        assertEquals( second.getId(), ascResults.get( 1 ).getId() );


        //search in reversed
        final String descQuery = "order by string desc";

        final CandidateResults descResults =
            entityIndex.search(indexSCope, SearchTypes.fromTypes( first.getId().getType() ), descQuery, 10 , 0, false);


        assertEquals( second.getId(), descResults.get( 0).getId() );
        assertEquals( first.getId(), descResults.get( 1 ).getId() );
    }


    @Test
    public void unionString() throws Throwable {

        Id appId = new SimpleId( "application" );
        Id ownerId = new SimpleId( "owner" );






        final Entity first = new Entity( "search" );

        first.setField( new StringField( "string", "alpha long string" ) );


        EntityUtils.setVersion( first, UUIDGenerator.newTimeUUID() );


        final Entity second = new Entity( "search" );

        second.setField( new StringField( "string", "bravo long string" ) );


        EntityUtils.setVersion( second, UUIDGenerator.newTimeUUID() );


        EntityIndexBatch batch = entityIndex.createBatch();


        //get ordering, so 2 is before 1 when both match
        IndexEdge indexScope1 = new IndexEdgeImpl( ownerId, "searches", SearchEdge.NodeType.SOURCE, 10 );
        batch.index(indexScope1, first);


        IndexEdge indexScope2 = new IndexEdgeImpl( ownerId, "searches", SearchEdge.NodeType.SOURCE, 11 );
        batch.index(indexScope2, second);


        indexProducer.put(batch.build()).subscribe();;
        entityIndex.refreshAsync().toBlocking().first();


        final String singleMatchQuery = "string contains 'alpha' OR string contains 'foo'";

        final CandidateResults singleResults =
            entityIndex.search(indexScope1, SearchTypes.fromTypes( first.getId().getType() ), singleMatchQuery, 10, 0, false );


        assertEquals(1, singleResults.size());
        assertEquals(first.getId(), singleResults.get(0).getId());


        //search in reversed
        final String bothKeywordsMatch = "string contains 'alpha' OR string contains 'bravo'";

        final CandidateResults singleKeywordUnion =
            entityIndex.search(indexScope1, SearchTypes.fromTypes( first.getId().getType() ), bothKeywordsMatch, 10 , 0, false);


        assertEquals( 2, singleKeywordUnion.size() );
        assertEquals( second.getId(), singleKeywordUnion.get( 0).getId() );
        assertEquals( first.getId(), singleKeywordUnion.get( 1 ).getId() );


        final String twoKeywordMatches = "string contains 'alpha' OR string contains 'long'";

        final CandidateResults towMatchResults =
            entityIndex.search(indexScope1, SearchTypes.fromTypes( first.getId().getType() ), twoKeywordMatches, 10, 0, false );


        assertEquals( 2, towMatchResults.size() );
        assertEquals(second.getId(), towMatchResults.get( 0).getId() );
        assertEquals(first.getId(), towMatchResults.get( 1 ).getId() );
    }


    /**
     * Tests that when NOT is the only query term, it functions correctly
     */
    @Test
    public void notRootOperandFilter() throws Throwable {

        Id appId = new SimpleId( "application" );
        Id ownerId = new SimpleId( "owner" );







        final Entity first = new Entity( "search" );

        first.setField( new IntegerField( "int", 1 ) );


        EntityUtils.setVersion( first, UUIDGenerator.newTimeUUID() );


        final Entity second = new Entity( "search" );

        second.setField( new IntegerField( "int", 2 ) );


        EntityUtils.setVersion( second, UUIDGenerator.newTimeUUID() );


        EntityIndexBatch batch = entityIndex.createBatch();


        //get ordering, so 2 is before 1 when both match
        IndexEdge indexScope1 = new IndexEdgeImpl( ownerId, "searches", SearchEdge.NodeType.SOURCE, 10 );
        batch.index( indexScope1, first );


        IndexEdge indexScope2 = new IndexEdgeImpl( ownerId, "searches", SearchEdge.NodeType.SOURCE, 11 );
        batch.index( indexScope2, second);


        indexProducer.put(batch.build()).subscribe();;
        entityIndex.refreshAsync().toBlocking().first();


        final String notFirst = "NOT int = 1";

        final CandidateResults notFirstResults =
            entityIndex.search(indexScope1, SearchTypes.fromTypes( first.getId().getType() ), notFirst, 10, 0, false );


        assertEquals( 1, notFirstResults.size() );
        assertEquals(second.getId(), notFirstResults.get( 0 ).getId() );


        //search in reversed
        final String notSecond = "NOT int = 2";

        final CandidateResults notSecondUnion =
            entityIndex.search(indexScope1, SearchTypes.fromTypes( first.getId().getType() ), notSecond, 10, 0, false );


        assertEquals( 1, notSecondUnion.size() );
        assertEquals( first.getId(), notSecondUnion.get( 0 ).getId() );


        final String notBothReturn = "NOT int = 3";

        final CandidateResults notBothReturnResults =
            entityIndex.search(indexScope1, SearchTypes.fromTypes( first.getId().getType() ), notBothReturn, 10, 0, false );


        assertEquals( 2, notBothReturnResults.size() );
        assertEquals( second.getId(), notBothReturnResults.get( 0).getId() );
        assertEquals( first.getId(), notBothReturnResults.get( 1 ).getId() );


        final String notFilterBoth = "(NOT int = 1) AND (NOT int = 2) ";

        final CandidateResults filterBoth =
            entityIndex.search(indexScope1, SearchTypes.fromTypes( first.getId().getType() ), notFilterBoth, 10, 0, false );


        assertEquals( 0, filterBoth.size() );

        final String noMatchesAnd = "(NOT int = 3) AND (NOT int = 4)";

        final CandidateResults noMatchesAndResults =
            entityIndex.search(indexScope1, SearchTypes.fromTypes( first.getId().getType() ), noMatchesAnd, 10, 0, false );


        assertEquals( 2, noMatchesAndResults.size() );
        assertEquals( second.getId(), noMatchesAndResults.get( 0).getId() );
        assertEquals( first.getId(), noMatchesAndResults.get( 1 ).getId() );


        final String noMatchesOr = "(NOT int = 3) AND (NOT int = 4)";

        final CandidateResults noMatchesOrResults =
            entityIndex.search(indexScope1, SearchTypes.fromTypes( first.getId().getType() ), noMatchesOr, 10, 0, false );


        assertEquals( 2, noMatchesOrResults.size() );
        assertEquals( second.getId(), noMatchesOrResults.get( 0).getId() );
        assertEquals( first.getId(), noMatchesOrResults.get( 1 ).getId() );
    }


    /**
     * Tests that when NOT is the only query term, it functions correctly
     */
    @Test
    public void notRootOperandQuery() throws Throwable {

        Id appId = new SimpleId( "application" );
        Id ownerId = new SimpleId( "owner" );







        final Entity first = new Entity( "search" );

        first.setField( new StringField( "string", "I ate a sammich" ) );


        EntityUtils.setVersion( first, UUIDGenerator.newTimeUUID() );


        final Entity second = new Entity( "search" );

        second.setField( new StringField( "string", "I drank a beer" ) );


        EntityUtils.setVersion( second, UUIDGenerator.newTimeUUID() );


        EntityIndexBatch batch = entityIndex.createBatch();


        //get ordering, so 2 is before 1 when both match
        IndexEdge indexScope1 = new IndexEdgeImpl( ownerId, "searches", SearchEdge.NodeType.SOURCE, 10 );
        batch.index( indexScope1, first );


        IndexEdge indexScope2 = new IndexEdgeImpl( ownerId, "searches", SearchEdge.NodeType.SOURCE, 11 );
        batch.index( indexScope2, second);


        indexProducer.put(batch.build()).subscribe();;
        entityIndex.refreshAsync().toBlocking().first();


        final String notFirst = "NOT string = 'I ate a sammich'";

        final CandidateResults notFirstResults =
            entityIndex.search(indexScope1, SearchTypes.fromTypes( first.getId().getType() ), notFirst, 10, 0, false );


        assertEquals( 1, notFirstResults.size() );
        assertEquals(second.getId(), notFirstResults.get( 0 ).getId() );


        final String notFirstWildCard = "NOT string = 'I ate*'";

        final CandidateResults notFirstWildCardResults =
            entityIndex.search(indexScope1, SearchTypes.fromTypes( first.getId().getType() ), notFirstWildCard, 10, 0, false );


        assertEquals( 1, notFirstWildCardResults.size() );
        assertEquals(second.getId(), notFirstWildCardResults.get( 0 ).getId() );


        final String notFirstContains = "NOT string contains 'sammich'";

        final CandidateResults notFirstContainsResults =
            entityIndex.search(indexScope1, SearchTypes.fromTypes( first.getId().getType() ), notFirstContains, 10 , 0, false);


        assertEquals( 1, notFirstContainsResults.size() );
        assertEquals(second.getId(), notFirstContainsResults.get( 0 ).getId() );


        //search in reversed
        final String notSecond = "NOT string = 'I drank a beer'";

        final CandidateResults notSecondUnion =
            entityIndex.search(indexScope1, SearchTypes.fromTypes( first.getId().getType() ), notSecond, 10, 0, false );


        assertEquals( 1, notSecondUnion.size() );
        assertEquals( first.getId(), notSecondUnion.get( 0 ).getId() );


        final String notSecondWildcard = "NOT string = 'I drank*'";

        final CandidateResults notSecondWildcardUnion =
            entityIndex.search(indexScope1, SearchTypes.fromTypes( first.getId().getType() ), notSecondWildcard, 10, 0, false );


        assertEquals( 1, notSecondWildcardUnion.size() );
        assertEquals( first.getId(), notSecondWildcardUnion.get( 0 ).getId() );


        final String notSecondContains = "NOT string contains 'beer'";

        final CandidateResults notSecondContainsUnion =
            entityIndex.search(indexScope1, SearchTypes.fromTypes( first.getId().getType() ), notSecondContains, 10, 0, false );


        assertEquals( 1, notSecondContainsUnion.size() );
        assertEquals( first.getId(), notSecondContainsUnion.get( 0 ).getId() );


        final String notBothReturn = "NOT string = 'I'm a foodie'";

        final CandidateResults notBothReturnResults =
            entityIndex.search(indexScope1, SearchTypes.fromTypes( first.getId().getType() ), notBothReturn, 10, 0, false );


        assertEquals( 2, notBothReturnResults.size() );
        assertEquals( second.getId(), notBothReturnResults.get( 0).getId() );
        assertEquals( first.getId(), notBothReturnResults.get( 1 ).getId() );


        final String notFilterBoth = "(NOT string = 'I ate a sammich') AND (NOT string = 'I drank a beer') ";

        final CandidateResults filterBoth =
            entityIndex.search(indexScope1, SearchTypes.fromTypes( first.getId().getType() ), notFilterBoth, 10, 0, false );


        assertEquals( 0, filterBoth.size() );

        final String noMatchesAnd = "(NOT string = 'I ate*') AND (NOT string = 'I drank*')";

        final CandidateResults noMatchesAndResults =
            entityIndex.search(indexScope1, SearchTypes.fromTypes( first.getId().getType() ), noMatchesAnd, 10, 0, false );


        assertEquals( 0, noMatchesAndResults.size() );

        final String noMatchesContainsAnd = "(NOT string contains 'ate') AND (NOT string contains 'drank')";

        final CandidateResults noMatchesContainsAndResults = entityIndex
            .search(indexScope1, SearchTypes.fromTypes( first.getId().getType() ), noMatchesContainsAnd, 10, 0, false );


        assertEquals( 0, noMatchesContainsAndResults.size() );


        final String noMatchesOr = "(NOT string = 'I ate*') AND (NOT string = 'I drank*')";

        final CandidateResults noMatchesOrResults =
            entityIndex.search(indexScope1, SearchTypes.fromTypes( first.getId().getType() ), noMatchesOr, 10, 0, false );


        assertEquals( 0, noMatchesOrResults.size() );

        final String noMatchesContainsOr = "(NOT string contains 'ate') AND (NOT string contains 'drank')";

        final CandidateResults noMatchesContainsOrResults = entityIndex
            .search(indexScope1, SearchTypes.fromTypes( first.getId().getType() ), noMatchesContainsOr, 10, 0, false );


        assertEquals( 0, noMatchesContainsOrResults.size() );
    }


    @Test
    public void testSizeByEdge(){
        final String type = UUID.randomUUID().toString();

        Id ownerId = new SimpleId( "owner" );


        final Entity first = new Entity( type );

        first.setField( new StringField( "string", "I ate a sammich" ) );
        first.setSize(100);

        EntityUtils.setVersion( first, UUIDGenerator.newTimeUUID() );


        final Entity second = new Entity( type );
        second.setSize(100);

        second.setField( new StringField( "string", "I drank a beer" ) );


        EntityUtils.setVersion( second, UUIDGenerator.newTimeUUID() );


        EntityIndexBatch batch = entityIndex.createBatch();


        //get ordering, so 2 is before 1 when both match
        IndexEdge indexScope1 = new IndexEdgeImpl( ownerId,type , SearchEdge.NodeType.SOURCE, 10 );
        batch.index( indexScope1, first );


        IndexEdge indexScope2 = new IndexEdgeImpl( ownerId, type+"er", SearchEdge.NodeType.SOURCE, 11 );
        batch.index( indexScope2, second);


        indexProducer.put(batch.build()).subscribe();;
        entityIndex.refreshAsync().toBlocking().first();
        long size = entityIndex.getTotalEntitySizeInBytes(new SearchEdgeImpl(ownerId,type, SearchEdge.NodeType.SOURCE));
        assertTrue( size == 100 );

    }

    /**
     * Tests that we're supporting null fields when indexing at Elasticsearch
     */
    @Test
    public void testNullFields() throws IOException {

        Id appId = new SimpleId( "application" );
        final String entityType = "thing";
        IndexEdge indexEdge = new IndexEdgeImpl( appId, "things", SearchEdge.NodeType.SOURCE, 1 );
        final SearchTypes searchTypes = SearchTypes.fromTypes( entityType );
        EntityIndexBatch batch = entityIndex.createBatch();


        UUID uuid = UUID.randomUUID();
        Entity entity1 = new Entity( entityType );
        EntityUtils.setVersion(entity1, UUIDGenerator.newTimeUUID());
        entity1.setField(new UUIDField(IndexingUtils.ENTITY_ID_FIELDNAME, uuid));

        // create a list and add 3 null values to it
        List<Object> listOfNulls = new ArrayList<>(3);
        listOfNulls.add(null);
        listOfNulls.add(null);
        listOfNulls.add(null);


        List<Object> listOfMixedNulls = new ArrayList<>(3);
        listOfMixedNulls.add(null);
        listOfMixedNulls.add("stringvalue");
        listOfMixedNulls.add(null);
        listOfMixedNulls.add(10);

        entity1.setField( new UUIDField("uuid", uuid, true));
        entity1.setField( new ArrayField<>( "arrayofnulls", listOfNulls) );
        entity1.setField( new ArrayField<>( "arrayofmixednulls", listOfMixedNulls) );
        entity1.setField( new NullField("nullfield"));



        batch.index( indexEdge, entity1 );
        indexProducer.put(batch.build()).subscribe();


        entityIndex.refreshAsync().toBlocking().first();


        StopWatch timer = new StopWatch();
        timer.start();
        CandidateResults candidateResults =
            entityIndex.search( indexEdge, searchTypes, "select * where uuid = '"+uuid+"'", 100, 0, false );

        timer.stop();

        assertEquals(1, candidateResults.size());
        logger.debug("Query time {}ms", timer.getTime());

        final CandidateResult candidate1 = candidateResults.get(0);

        //check the id and version
        assertEquals( entity1.getId(), candidate1.getId() );
        assertEquals(entity1.getVersion(), candidate1.getVersion());

    }



}



