package uk.ac.ebi.quickgo.ontology.service.converter;

import uk.ac.ebi.quickgo.common.converter.FlatFieldBuilder;
import uk.ac.ebi.quickgo.common.converter.FlatFieldLeaf;
import uk.ac.ebi.quickgo.ontology.common.document.OntologyDocument;
import uk.ac.ebi.quickgo.ontology.model.OBOTerm;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.Before;
import org.junit.Test;

import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
import static org.hamcrest.core.IsCollectionContaining.hasItem;
import static uk.ac.ebi.quickgo.ontology.common.document.OntologyDocMocker.createOBODoc;

/**
 * Tests the behaviour of the {@link DefinitionConverter} class.
 */
public class DefinitionConverterTest {
    private DefinitionConverter converter;

    private OntologyDocument doc;

    @Before
    public void setUp() throws Exception {
        converter = new DefinitionConverter();
        doc = createOBODoc("id", "name");
    }

    @Test
    public void convertsDocWithDefinitionTextAndNoTextXrefsIntoADefinitionObjectWithJustTheText() throws Exception {
        String text = "This is the definition of the ontology term";

        doc.definition = text;
        doc.definitionXrefs = Collections.emptyList();

        OBOTerm.Definition def = converter.apply(doc);

        assertThat(def.text, is(text));
        assertThat(def.xrefs, hasSize(0));
    }

    @Test
    public void convertsDocWithNullDefinitionXrefListIntoDefinitionObjectWithEmptyXrefs() throws Exception {
        String text = "This is the definition of the ontology term";

        doc.definition = text;
        doc.definitionXrefs = null;

        OBOTerm.Definition def = converter.apply(doc);

        assertThat(def.text, is(text));
        assertThat(def.xrefs, hasSize(0));
    }

    @Test
    public void convertsDocWithNoDefinitionTextAndWithASingleTextXrefIntoADefinitionObjectWithJustTheXref()
            throws Exception {
        String text = null;

        String xrefId = "id";
        String xrefDb = "db";
        String xrefText = createXrefText(xrefDb, xrefId);

        doc.definition = text;
        doc.definitionXrefs = Collections.singletonList(xrefText);

        OBOTerm.Definition def = converter.apply(doc);

        assertThat(def.text, is(text));

        List<OBOTerm.XRef> retrievedXrefs = def.xrefs;
        assertThat(def.xrefs, hasSize(1));

        OBOTerm.XRef retrievedXref = retrievedXrefs.get(0);
        assertThat(retrievedXref.dbId, is(xrefId));
        assertThat(retrievedXref.dbCode, is(xrefDb));
    }

    @Test
    public void convertsDocWithADefinitionTextAndWithMultipleTextXrefsIntoADefinitionObjectWithADefinitionAndXrefs()
            throws Exception {
        String text = "This is the definition of the ontology term";

        String xrefId1 = "id1";
        String xrefDb1 = "db1";
        String xrefText1 = createXrefText(xrefDb1, xrefId1);

        String xrefId2 = "id2";
        String xrefDb2 = "db2";
        String xrefText2 = createXrefText(xrefDb2, xrefId2);

        doc.definition = text;
        doc.definitionXrefs = Arrays.asList(xrefText1, xrefText2);

        OBOTerm.Definition def = converter.apply(doc);

        assertThat(def.text, is(text));

        List<OBOTerm.XRef> retrievedXrefs = def.xrefs;
        assertThat(retrievedXrefs, hasSize(2));
    }

    private String createXrefText(String db, String id) {
        return FlatFieldBuilder.newFlatField()
                .addField(FlatFieldLeaf.newFlatFieldLeaf(db))
                .addField(FlatFieldLeaf.newFlatFieldLeaf(id))
                .buildString();
    }

    private OBOTerm.XRef createXref(String db, String id) {
        OBOTerm.XRef xref = new OBOTerm.XRef();
        xref.dbCode = db;
        xref.dbId = id;

        return xref;
    }
}

@@ -308,16 +308,45 @@
 Arrays;%0A
+import java.util.Collection;%0A
 import j
@@ -367,16 +367,16 @@
 ctions;%0A
-
 import j
@@ -439,16 +439,72 @@
 .Test;%0A%0A
+import static org.hamcrest.CoreMatchers.containsString;%0A
 import s
@@ -589,16 +589,16 @@
 ers.is;%0A
-
 import s
@@ -642,16 +642,62 @@
 rtThat;%0A
+import static org.hamcrest.Matchers.contains;%0A
 import s
@@ -3625,30 +3625,224 @@
 asSize(2));%0A
+        assertThat(collectionHasObjectWithContents(retrievedXrefs, xrefId1, xrefDb1), is(true));%0A        assertThat(collectionHasObjectWithContents(retrievedXrefs, xrefId2, xrefDb2), is(true));%0A
     %7D%0A
-
 %0A    private
@@ -4114,41 +4114,89 @@
 ate 
-OBOTerm.XRef createXref(
+boolean collectionHasObjectWithContents(Collection%3COBOTerm.XRef%3E xrefs, 
 String 
+i
 d
-b
 , St
@@ -4192,34 +4192,34 @@
 ring id, String 
-i
 d
+b
 ) %7B%0A        OBOT
@@ -4218,118 +4218,167 @@
     
-OBOTerm.XRef xref = new OBOTerm.XRef();%0A        xref.dbCode = db;%0A        xref.dbId = id;%0A%0A        return xref
+return xrefs.stream()%0A                .filter(xref -%3E xref.dbId.equals(id) && xref.dbCode.equals(db))%0A                .findFirst()%0A                .isPresent()
 ;%0A  

Add code to check that elements in collection exist.