package uk.ac.ebi.atlas.controllers.page;

import uk.ac.ebi.atlas.model.experiment.baseline.BaselineExperiment;
import com.google.common.collect.SortedSetMultimap;
import com.google.common.collect.TreeMultimap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import uk.ac.ebi.atlas.trader.ExpressionAtlasExperimentTrader;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;

@Controller
@Scope("request")
public class BaselineExperimentsController {

    private static final Logger LOGGER = LoggerFactory.getLogger(BaselineExperimentsController.class);

    private ExpressionAtlasExperimentTrader experimentTrader;

    private SortedSetMultimap<String, String> experimentAccessionsBySpecies;
    private Map<String, String> experimentLinks = new HashMap<>();
    private Map<String, String> experimentDisplayNames = new HashMap<>();

    @Inject
    public BaselineExperimentsController(ExpressionAtlasExperimentTrader experimentTrader) {
        this.experimentTrader = experimentTrader;
    }

    @RequestMapping("/baseline/experiments")
    public String getBaselineExperimentsPage(Model model) {

        loadExperimentAccessionsBySpecies();

        model.addAttribute("experimentAccessionsBySpecies", experimentAccessionsBySpecies);
        model.addAttribute("experimentLinks", experimentLinks);
        model.addAttribute("experimentDisplayNames", experimentDisplayNames);

        model.addAttribute("mainTitle", "Baseline expression experiments ");

        return "foundation-baseline-experiments";
    }

    @PostConstruct
    private void loadExperimentAccessionsBySpecies() {

        for (String experimentAccession : experimentTrader.getAllBaselineExperimentAccessions()) {
            String displayName = null;
            try {
                displayName = experimentTrader.getPublicExperiment(experimentAccession).getDisplayName();
            } catch (RuntimeException e) {
                // we don't want the entire application to crash just because one condensedSdrf file may be offline because a curator is modifying it
                LOGGER.error(e.getMessage(), e);
                displayName = experimentAccession;
            }

            int numberOfAssays = ((BaselineExperiment) experimentTrader.getPublicExperiment(experimentAccession)).getAnalysedRowsAccessions().size();

            experimentDisplayNames.put(experimentAccession, displayName + " (" + numberOfAssays + " assays)");
        }

        Comparator<String> keyComparator = (o1, o2) -> {
            // Services review: Alvis' edict for Homo sapiens experiments to always come up on top of baseline landing page
            if (o1.equals("Homo sapiens") && !o2.equals("Homo sapiens"))
                return -1;
            else if (o2.equals("Homo sapiens") && !o1.equals("Homo sapiens"))
                return 1;
            else
                return o1.compareTo(o2);
        };
        // experiments should be sorted by their display name, not accession
        Comparator<String> valueComparator = (o1, o2) -> {
            // Services review: Alvis' edict for proteomics experiments to always come up at the bottom of
            // the list of experiments within each species
            if (o1.contains("-PROT-") && !o2.contains("-PROT-"))
                return 1;
            else if (o2.contains("-PROT-") && !o1.contains("-PROT-"))
                return -1;
            else
                return experimentDisplayNames.get(o1).compareTo(experimentDisplayNames.get(o2));
        };
        experimentAccessionsBySpecies = TreeMultimap.create(keyComparator, valueComparator);

        for (String experimentAccession : experimentTrader.getAllBaselineExperimentAccessions()) {

            try {
                BaselineExperiment experiment = (BaselineExperiment) experimentTrader.getPublicExperiment(experimentAccession);
                experimentAccessionsBySpecies.put(experiment.getSpecies().getName(), experimentAccession);
                experimentLinks.put(experimentAccession + experiment.getSpecies().getName(), "");
            } catch (RuntimeException e) {
                // we don't want the entire application to crash just because one condensedSdrf file may be offline because a curator is modifying it
                LOGGER.error(e.getMessage(), e);
            }

        }

    }

}
@@ -40,77 +40,8 @@
 e;%0A%0A
-import uk.ac.ebi.atlas.model.experiment.baseline.BaselineExperiment;%0A
 impo
@@ -84,24 +84,24 @@
 etMultimap;%0A
+
 import com.g
@@ -196,61 +196,8 @@
 ry;%0A
-import org.springframework.context.annotation.Scope;%0A
 impo
@@ -342,16 +342,85 @@
 apping;%0A
+import uk.ac.ebi.atlas.model.experiment.baseline.BaselineExperiment;%0A
 import u
@@ -479,47 +479,8 @@
 r;%0A%0A
-import javax.annotation.PostConstruct;%0A
 impo
@@ -597,26 +597,8 @@
 ler%0A
-@Scope(%22request%22)%0A
 publ
@@ -810,227 +810,8 @@
 r;%0A%0A
-    private SortedSetMultimap%3CString, String%3E experimentAccessionsBySpecies;%0A    private Map%3CString, String%3E experimentLinks = new HashMap%3C%3E();%0A    private Map%3CString, String%3E experimentDisplayNames = new HashMap%3C%3E();%0A%0A
     
@@ -1086,489 +1086,69 @@
     
-loadExperimentAccessionsBySpecies();%0A%0A        model.addAttribute(%22experimentAccessionsBySpecies%22, experimentAccessionsBySpecies);%0A        model.addAttribute(%22experimentLinks%22, experimentLinks);%0A        model.addAttribute(%22experimentDisplayNames%22, experimentDisplayNames);%0A%0A        model.addAttribute(%22mainTitle%22, %22Baseline expression experiments %22);%0A%0A        return %22foundation-baseline-experiments%22;%0A    %7D%0A%0A    @PostConstruct%0A    private void loadExperimentAccessionsBySpecies() %7B
+Map%3CString, String%3E experimentDisplayNames = new HashMap%3C%3E();
 %0A%0A  
@@ -1278,15 +1278,8 @@
 Name
- = null
 ;%0A  
@@ -3053,24 +3053,58 @@
   %7D;%0A       
+ SortedSetMultimap%3CString, String%3E
  experimentA
@@ -3174,24 +3174,88 @@
 mparator);%0A%0A
+        Map%3CString, String%3E experimentLinks = new HashMap%3C%3E();%0A%0A
         for 
@@ -3957,20 +3957,383 @@
 %0A        %7D%0A%0A
+        model.addAttribute(%22experimentAccessionsBySpecies%22, experimentAccessionsBySpecies);%0A        model.addAttribute(%22experimentLinks%22, experimentLinks);%0A        model.addAttribute(%22experimentDisplayNames%22, experimentDisplayNames);%0A%0A        model.addAttribute(%22mainTitle%22, %22Baseline expression experiments %22);%0A%0A        return %22foundation-baseline-experiments%22;%0A
     %7D%0A%0A%7D

Refactor : remove an unnecessary request scope and a @PostConstruct method that I think was happening twice. Simple is good.