package uk.ac.ebi.atlas.experimentimport.admin;

import com.google.common.base.Optional;
import com.google.gson.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import uk.ac.ebi.atlas.controllers.ResourceNotFoundException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.regex.Pattern;

public class ExperimentAdminController {

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

    private final ExperimentOps experimentOps;
    private final ExperimentAdminHelpPage helpPage = new ExperimentAdminHelpPage();
    private final Gson gson= new GsonBuilder().setPrettyPrinting().create();

    public ExperimentAdminController(ExperimentOps experimentOps) {
        this.experimentOps = experimentOps;
    }

    @RequestMapping(
            value = "",
            method = RequestMethod.GET,
            produces = "application/json;charset=UTF-8")
    @ResponseBody
    public String listAllExperiments() {
        return doOp("all", "list");
    }

    @RequestMapping(
            value = "/{accessions}",
            method = RequestMethod.GET,
            produces = "application/json;charset=UTF-8")
    @ResponseBody
    public String listExperiments(@PathVariable("accessions") String accessions) {
        if(accessions.equalsIgnoreCase("help")){
            return helpPage.getMessage();
        } else {
            return doOp(accessions, "list");
        }
    }

    @RequestMapping(
            value = "/{accessions}/{op}",
            method = RequestMethod.GET,
            produces = "application/json;charset=UTF-8")
    @ResponseBody
    public String doOp(@PathVariable("accessions") String accessionParameter, @PathVariable("op") String opParameter) {
        try {
            Optional<Collection<String>> accessions = accessionParameter.length() == 0 || accessionParameter.toLowerCase().equals("all")
                    ? Optional.<Collection<String>>absent()
                    : Optional.of(readAccessions(accessionParameter));

            return gson.toJson(experimentOps.perform(accessions, Op.opsForParameter(opParameter)));
        } catch (IllegalArgumentException e) {
            return gson.toJson(usageMessage(opParameter));
        } catch (Exception e) {
            return gson.toJson(errorMessage(accessionParameter, e));
        }
    }

    private JsonElement errorMessage(String accessionParameter, Exception e){
        JsonArray result = new JsonArray();
        JsonObject messageObject = new JsonObject();
        messageObject.addProperty("accession", accessionParameter);
        messageObject.addProperty("error", e.getMessage()!=null? e.getMessage() : e.toString());
        result.add(messageObject);
        return result;
    }

    private JsonElement usageMessage(String opParameter){
        JsonObject messageObject = new JsonObject();
        messageObject.addProperty("error","Could not understand: " + opParameter );
        messageObject.addProperty("help","see gxa/admin/experiments/help for more info");
        return messageObject;
    }

    private Collection<String> readAccessions(String accessionParameter) {
        if (accessionParameter.contains("*")) {
            List<String> result = new ArrayList<>();
            Pattern pattern = Pattern.compile(accessionParameter.replaceAll("\\*", ".*"));
            for (String experimentAccession : experimentOps.findAllExperiments()) {
                if (pattern.matcher(experimentAccession).matches()) {
                    result.add(experimentAccession);
                }
            }
            return result;
        } else {
            return Arrays.asList(accessionParameter.split(","));
        }
    }

    @ExceptionHandler(ResourceNotFoundException.class)
    @ResponseStatus(value = HttpStatus.NOT_FOUND)
    @ResponseBody
    public String handleResourceNotFoundException(Exception e) throws IOException {
        LOGGER.error(e.getMessage(), e);
        return e.getClass().getSimpleName() + ": " + e.getMessage();
    }

}
@@ -38,24 +38,64 @@
 ort.admin;%0A%0A
+import com.google.common.base.Function;%0A
 import com.g
@@ -1992,16 +1992,22 @@
         
+final 
 Optional
@@ -2251,24 +2251,25 @@
 rameter));%0A%0A
+%0A
             
@@ -2291,60 +2291,360 @@
 son(
-experimentOps.perform(accessions, Op.opsForParameter
+%0A                    maybeOps(opParameter)%0A                    .transform(new Function%3CList%3COp%3E, JsonElement%3E() %7B%0A                        @Override%0A                        public JsonElement apply(List%3COp%3E ops) %7B%0A                            return experimentOps.perform(accessions, ops);%0A                        %7D%0A                    %7D).or(usageMessage
 (opP
@@ -2653,16 +2653,29 @@
 ameter))
+%0A            
 );%0A     
@@ -2690,23 +2690,8 @@
 ch (
-IllegalArgument
 Exce
@@ -2732,29 +2732,29 @@
 .toJson(
-usage
+error
 Message(
 opParame
@@ -2737,34 +2737,41 @@
 on(errorMessage(
-op
+accession
 Parameter));%0A   
@@ -2759,24 +2759,27 @@
 ionParameter
+, e
 ));%0A        
@@ -2783,97 +2783,236 @@
    %7D
- catch (Exception e) %7B%0A            return gson.toJson(errorMessage(accessionParameter, e)
+%0A    %7D%0A%0A    private Optional%3CList%3COp%3E%3E maybeOps(String opParameter)%7B%0A        try%7B%0A            return Optional.of(Op.opsForParameter(opParameter));%0A        %7D catch (IllegalArgumentException e)%7B%0A            return Optional.absent(
 );%0A 

Handle an IllegalArgumentException with an Optional because something else is throwing the same exception in ves-hx-77 and I don't see what it is