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

import uk.ac.ebi.quickgo.common.converter.FlatFieldBuilder;
import uk.ac.ebi.quickgo.model.ontology.go.GOTerm;
import uk.ac.ebi.quickgo.ontology.common.OntologyDocument;

import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

import static org.springframework.util.StringUtils.isEmpty;
import static uk.ac.ebi.quickgo.common.converter.FlatFieldBuilder.newFlatField;
import static uk.ac.ebi.quickgo.common.converter.FlatFieldLeaf.newFlatFieldLeaf;

/**
 * Converts a {@link GOTerm} instance into an {@link OntologyDocument} instance.
 *
 * Created 14/12/15
 * @author Edd
 */
public class GOTermToODocConverter implements Function<GOTerm, OntologyDocument> {

    private final static GenericTermToODocConverter GENERIC_TERM_TO_DOC_CONVERTER = new GenericTermToODocConverter();

    @Override public OntologyDocument apply(GOTerm termOptional) {
        OntologyDocument ontologyDocument = GENERIC_TERM_TO_DOC_CONVERTER.apply(termOptional);

            GOTerm term = termOptional;
            OntologyDocument doc = ontologyDocument;

            doc.annotationGuidelines = extractAnnGuidelines(term);
            doc.aspect = term.getAspect() == null ?
                    null : term.getAspect().text;
            doc.taxonConstraints = extractTaxonConstraints(term);
            doc.usage = term.getUsage() == null ?
                    null : term.getUsage().getText();
            doc.blacklist = extractBlacklist(term);
            doc.goDiscussions = extractGoDiscussions(term);
            doc.proteinComplexes = extractProteinComplexes(term);

            return doc;
    }

    private List<String> extractChildren(GOTerm goTerm) {
        if (!isEmpty(goTerm.getChildren())) {
            return goTerm.getChildren().stream()
                    .map(
                            t -> t.getChild().getId())
                    .collect(Collectors.toList());
        } else {
            return null;
        }
    }

    /*
     * format: description|url
     */
    private List<String> extractAnnGuidelines(GOTerm goTerm) {
        if (!isEmpty(goTerm.getGuidelines())) {
            return goTerm.getGuidelines().stream()
                    .map(
                            t -> newFlatField()
                                    .addField(newFlatFieldLeaf(t.getTitle()))
                                    .addField(newFlatFieldLeaf(t.getUrl()))
                                    .buildString())
                    .collect(Collectors.toList());
        } else {
            return null;
        }
    }

    /*
     * format: ancestorId|ancestorName|relationship|taxId|taxIdType|taxName|pubMedId1&pubMedId2
     */
    private List<String> extractTaxonConstraints(GOTerm goTerm) {
        if (!isEmpty(goTerm.getTaxonConstraints())) {
            return goTerm.getTaxonConstraints().stream()
                    .map(t -> {
                        FlatFieldBuilder pubmedsAsFlatField = newFlatField();
                        t.getSourcesIds().stream().forEach(
                                s -> pubmedsAsFlatField.addField(newFlatFieldLeaf(s))
                        );

                        return newFlatField()
                                .addField(newFlatFieldLeaf(t.getGoId()))
                                .addField(newFlatFieldLeaf(t.getName()))
                                .addField(newFlatFieldLeaf(t.relationship()))
                                .addField(newFlatFieldLeaf(t.getTaxId()))
                                .addField(newFlatFieldLeaf(t.taxIdType()))
                                .addField(newFlatFieldLeaf(t.getTaxonName()))
                                .addField(pubmedsAsFlatField)
                                .buildString();
                    })
                    .collect(Collectors.toList());
        } else {
            return null;
        }
    }

    /*
     * format: goId|category|entityType|entityId|taxonId|ancestorGoId|reason|methodId
     */
    private List<String> extractBlacklist(GOTerm goTerm) {
        if (!isEmpty(goTerm.getBlacklist())) {
            return goTerm.getBlacklist().stream()
                    .map(
                            t -> newFlatField()
                                    .addField(newFlatFieldLeaf(t.getGoId()))
                                    .addField(newFlatFieldLeaf(t.getCategory()))
                                    .addField(newFlatFieldLeaf(t.getEntityType()))
                                    .addField(newFlatFieldLeaf(t.getProteinAc()))
                                    .addField(newFlatFieldLeaf(Integer.toString(t.getTaxonId())))
                                    .addField(newFlatFieldLeaf(t.getEntityName()))
                                    .addField(newFlatFieldLeaf(t.getAncestorGOID()))
                                    .addField(newFlatFieldLeaf(t.getReason()))
                                    .addField(newFlatFieldLeaf(t.getMethodId()))
                                    .buildString())
                    .collect(Collectors.toList());
        } else {
            return null;
        }
    }

    private List<String> extractGoDiscussions(GOTerm goTerm) {
        if (!isEmpty(goTerm.getPlannedChanges())) {
            return goTerm.getPlannedChanges().stream()
                    .map(change -> newFlatField()
                            .addField(newFlatFieldLeaf(change.getTitle()))
                            .addField(newFlatFieldLeaf(change.getUrl()))
                            .buildString())
                    .collect(Collectors.toList());
        } else {
            return null;
        }
    }

    /*
     * format: database|database_identifier|symbol|name
     */
    private List<String> extractProteinComplexes(GOTerm goTerm) {
        if (!isEmpty(goTerm.getProteinComplexes())) {
            return goTerm.getProteinComplexes().stream()
                    .map(pc -> newFlatField()
                            .addField(newFlatFieldLeaf(pc.db))
                            .addField(newFlatFieldLeaf(pc.id))
                            .addField(newFlatFieldLeaf(pc.symbol))
                            .addField(newFlatFieldLeaf(pc.name))
                            .buildString())
                    .collect(Collectors.toList());
        } else {
            return null;
        }
    }
}

@@ -244,35 +244,8 @@
 st;%0A
-import java.util.Optional;%0A
 impo
@@ -276,16 +276,16 @@
 nction;%0A
+
 import j
@@ -920,24 +920,16 @@
 erm term
-Optional
 ) %7B%0A    
@@ -949,32 +949,19 @@
 ocument 
-ontologyDocument
+doc
  = GENER
@@ -999,118 +999,11 @@
 term
-Optional
 );%0A
-%0A
-            GOTerm term = termOptional;%0A            OntologyDocument doc = ontologyDocument;%0A%0A    
     
@@ -1065,28 +1065,24 @@
 m);%0A        
-    
 doc.aspect =
@@ -1117,36 +1117,32 @@
                 
-  
-  
 null : term.getA
@@ -1155,20 +1155,16 @@
 ).text;%0A
-    
         
@@ -1221,28 +1221,24 @@
 m);%0A        
-  
-  
 doc.usage = 
@@ -1271,36 +1271,32 @@
                 
-    
 null : term.getU
@@ -1317,28 +1317,24 @@
 ();%0A        
-  
-  
 doc.blacklis
@@ -1353,36 +1353,32 @@
 lacklist(term);%0A
-    
         doc.goDi
@@ -1421,28 +1421,24 @@
 m);%0A        
-  
-  
 doc.proteinC
@@ -1479,21 +1479,16 @@
 (term);%0A
-%0A    
         
@@ -1510,352 +1510,8 @@
  %7D%0A%0A
-    private List%3CString%3E extractChildren(GOTerm goTerm) %7B%0A        if (!isEmpty(goTerm.getChildren())) %7B%0A            return goTerm.getChildren().stream()%0A                    .map(%0A                            t -%3E t.getChild().getId())%0A                    .collect(Collectors.toList());%0A        %7D else %7B%0A            return null;%0A        %7D%0A    %7D%0A%0A
     
@@ -2498,24 +2498,24 @@
 latField();%0A
+
             
@@ -2548,17 +2548,8 @@
 s().
-stream().
 forE

Remove references to optional. Remove redundant assignation. Replace stream().forEach() with .forEach()