package uk.ac.ebi.atlas.experimentpage;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.TreeMultimap;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import uk.ac.ebi.atlas.experimentpage.json.JsonExperimentController;
import uk.ac.ebi.atlas.trader.ExperimentTrader;
import uk.ac.ebi.atlas.tsne.TSnePlotCollator;
import uk.ac.ebi.atlas.tsne.TSnePoint;

import javax.inject.Inject;
import java.io.IOException;
import java.util.stream.Collectors;

@RestController
public class JsonSingleCellExperimentController extends JsonExperimentController {

    private Gson gson = new GsonBuilder().registerTypeAdapter(TSnePoint.class, TSnePoint.typeAdapter(new Gson())).create();
    private TSnePlotCollator tSnePlotCollator;

    @Inject
    public JsonSingleCellExperimentController(ExperimentTrader experimentTrader, TSnePlotCollator tSnePlotCollator) {
        super(experimentTrader);
        this.tSnePlotCollator = tSnePlotCollator;
    }

    @RequestMapping(
            value = "/json/experiments/{experimentAccession}/tsneplot",
            method = RequestMethod.GET,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String tSnePlotCoordinates(@PathVariable String experimentAccession,
                                      @RequestParam(defaultValue = "") String accessKey) throws IOException {
        return tSnePlotClusters(experimentAccession, 2, accessKey);
    }

    @RequestMapping(value = "/json/experiments/{experimentAccession}/tsneplot/clusters/{k}",
            method = RequestMethod.GET,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String tSnePlotClusters(
            @PathVariable String experimentAccession,
            @PathVariable int k,
            @RequestParam(defaultValue = "") String accessKey) throws IOException {

        if (!"E-RANDOM".equalsIgnoreCase(experimentAccession)) {
            experimentTrader.getExperiment(experimentAccession, accessKey);
        }

        TreeMultimap<Integer, TSnePoint> clusterPoints =
                tSnePlotCollator.getTSnePlotWithClusters(experimentAccession, k);

        return gson.toJson(
                clusterPoints.keySet().stream()
                        .map(key -> ImmutableMap.of("name", key, "data", clusterPoints.get(key)))
                        .collect(Collectors.toList()));
    }

    @RequestMapping(value = "/json/experiments/{experimentAccession}/tsneplot/expression/{geneId}",
            method = RequestMethod.GET,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String tSnePlotExpression(
            @PathVariable String experimentAccession,
            @PathVariable String geneId,
            @RequestParam(defaultValue = "") String accessKey) throws IOException {
        // Return hard-coded t-SNE plot data: coordinates
        experimentTrader.getExperiment(experimentAccession, accessKey);

        return gson.toJson(
                ImmutableMap.of("data", tSnePlotCollator.getTSnePlotWithExpression(experimentAccession, geneId)));
    }

}

@@ -34,16 +34,64 @@
 tpage;%0A%0A
+import com.google.common.collect.ImmutableList;%0A
 import c
@@ -1472,16 +1472,25 @@
 tsneplot
+/clusters
 %22,%0A     
@@ -1616,18 +1616,22 @@
 Plot
-Coordina
+DefaultClus
 te
+r
 s(@P
@@ -2686,19 +2686,37 @@
 %22name%22, 
+Integer.toString(
 key
+)
 , %22data%22
@@ -2797,32 +2797,486 @@
 ist()));%0A    %7D%0A%0A
+    @RequestMapping(value = %22/json/experiments/%7BexperimentAccession%7D/tsneplot/expression%22,%0A            method = RequestMethod.GET,%0A            produces = MediaType.APPLICATION_JSON_UTF8_VALUE)%0A    public String tSnePlotDefaultExpression(%0A            @PathVariable String experimentAccession,%0A            @RequestParam(defaultValue = %22%22) String accessKey) throws IOException %7B%0A        return tSnePlotExpression(experimentAccession, %22%22, accessKey);%0A    %7D%0A%0A
     @RequestMapp
@@ -3805,24 +3805,106 @@
 ccessKey);%0A%0A
+        // Wrapped in a list to have a one-element array (required by Highcharts)%0A
         retu
@@ -3935,16 +3935,33 @@
         
+ImmutableList.of(
 Immutabl
@@ -4049,16 +4049,17 @@
 eneId)))
+)
 ;%0A    %7D%0A

Add end points without parameters to return sensible data If no gene is specified for expression then return 0 expression and default clusters is 2