package uk.ac.ebi.quickgo.geneproduct.common;

import uk.ac.ebi.quickgo.common.solr.TemporarySolrDataStore;
import uk.ac.ebi.quickgo.geneproduct.common.document.GeneProductDocument;
import uk.ac.ebi.quickgo.geneproduct.common.document.GeneProductFields;

import java.io.IOException;
import java.util.Collections;
import java.util.List;
import org.apache.solr.client.solrj.SolrServerException;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationContextLoader;
import org.springframework.data.solr.core.SolrTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static uk.ac.ebi.quickgo.geneproduct.common.common.GeneProductDocMocker.createDocWithId;

/**
 * Tests the behaviour of the {@link GeneProductRepository}
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = GeneProductRepoConfig.class, loader = SpringApplicationContextLoader.class)
public class GeneProductRepositoryIT {
    @ClassRule
    public static final TemporarySolrDataStore solrDataStore = new TemporarySolrDataStore();

    @Autowired
    private GeneProductRepository geneProductRepository;

    @Autowired
    private SolrTemplate geneProductTemplate;

    @Before
    public void before() {
        geneProductRepository.deleteAll();
    }

    @Test
    public void addGeneProductToRepository() throws Exception {
        String id = "geneProduct1";

        GeneProductDocument doc = createDocWithId(id);

        GeneProductDocument savedDoc = geneProductRepository.save(doc);

        assertThat(savedDoc, is(doc));
    }

    @Test
    public void add3GeneProductTosRepository() throws Exception {
        String id1 = "geneProduct1";
        String id2 = "geneProduct2";
        String id3 = "geneProduct3";

        GeneProductDocument doc1 = createDocWithId(id1);
        GeneProductDocument doc2 = createDocWithId(id2);
        GeneProductDocument doc3 = createDocWithId(id3);

        geneProductRepository.save(doc1);
        geneProductRepository.save(doc2);
        geneProductRepository.save(doc3);

        assertThat(geneProductRepository.findAll(), containsInAnyOrder(doc1, doc2, doc3));
    }

    @Test
    public void removeGeneProductFromRepository() throws IOException, SolrServerException {
        String id = "geneProduct1";

        GeneProductDocument doc = createDocWithId(id);

        geneProductRepository.save(doc);

        deleteFromRepositoryByIds(doc);

        List<GeneProductDocument> retrievedDoc = geneProductRepository.findById(Collections.singletonList(id));

        assertThat(retrievedDoc.isEmpty(), is(true));
    }

    @Test
    public void lookupGeneProductById() {
        String id = "geneProduct1";

        GeneProductDocument doc = createDocWithId(id);

        geneProductRepository.save(doc);

        List<GeneProductDocument> retrievedDoc = geneProductRepository.findById(Collections.singletonList(id));

        assertThat(retrievedDoc.isEmpty(), is(false));
        assertThat(retrievedDoc.get(0), is(doc));

    }

    /**
     * Deleting from a repository is a special case when the schema.xml defines a non-"string"
     * analyzer on the field used to identify the documents to delete. We use a lower-casing analyser
     * for IDs, which means the geneProductTemplate.deleteById fails.
     * <p>
     * To get the desired behaviour, delete by accessing the solr server instance directly, so that
     * the request goes through a query, which is subject to the same analyser used for indexing.
     *
     * @param docs the documents to delete
     * @throws SolrServerException
     * @throws IOException
     */
    private void deleteFromRepositoryByIds(GeneProductDocument... docs) throws SolrServerException, IOException {
        for (GeneProductDocument doc : docs) {
            geneProductTemplate.getSolrClient().deleteByQuery(GeneProductFields.Searchable.ID + ":" + doc.id);
        }
        geneProductTemplate.getSolrClient().commit();
    }
}

@@ -272,24 +272,81 @@
 OException;%0A
+import java.util.ArrayList;%0Aimport java.util.Collection;%0A
 import java.
@@ -2498,89 +2498,374 @@
     
-assertThat(geneProductRepository.findAll(), containsInAnyOrder(doc1, doc2, doc3))
+Collection%3CString%3E extractedIds = extractIds(geneProductRepository.findAll());%0A%0A        assertThat(extractedIds, containsInAnyOrder(id1, id2, id3));%0A    %7D%0A%0A    private Collection%3CString%3E extractIds(Iterable%3CGeneProductDocument%3E gpDocuments) %7B%0A        List%3CString%3E ids = new ArrayList%3C%3E();%0A%0A        gpDocuments.forEach(gpDoc -%3E ids.add(gpDoc.id));%0A%0A        return ids
 ;%0A  
@@ -3714,24 +3714,26 @@
 c.get(0)
+.id
 , is(
+i
 d
-oc
 ));%0A%0A   

Fix broken test cases.