package edu.kit.ipd.crowdcontrol.objectservice.rest.resources;

import edu.kit.ipd.crowdcontrol.objectservice.crowdworking.PlatformManager;
import edu.kit.ipd.crowdcontrol.objectservice.database.operations.*;
import edu.kit.ipd.crowdcontrol.objectservice.proto.Experiment;
import edu.kit.ipd.crowdcontrol.objectservice.rest.exceptions.BadRequestException;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import spark.Request;
import spark.Response;

import java.util.HashMap;
import java.util.Map;

import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

/**
 * @author Niklas Keller
 */
public class ExperimentResourceTest {
    private Request request;
    private Response response;
    private ExperimentResource resource;

    private ExperimentOperations experimentOperations;
    private CalibrationOperations calibrationOperations;
    private TagConstraintsOperations tagConstraintsOperations;
    private AlgorithmOperations algorithmOperations;
    private ExperimentsPlatformOperations experimentsPlatformOperations;
    private PlatformManager platformManager;
    private AnswerRatingOperations answerRatingOperations;

    @Before
    public void setUp() {
        request = mock(Request.class);
        response = mock(Response.class);

        answerRatingOperations = mock(AnswerRatingOperations.class);
        experimentOperations = mock(ExperimentOperations.class);
        calibrationOperations = mock(CalibrationOperations.class);
        tagConstraintsOperations = mock(TagConstraintsOperations.class);
        algorithmOperations = mock(AlgorithmOperations.class);
        experimentsPlatformOperations = mock(ExperimentsPlatformOperations.class);
        platformManager = mock(PlatformManager.class);

        resource = new ExperimentResource(answerRatingOperations, experimentOperations, calibrationOperations, tagConstraintsOperations, algorithmOperations, experimentsPlatformOperations,  platformManager);
    }

    /**
     * @link http://stackoverflow.com/a/6527990/2373138
     */
    @Rule
    public ExpectedException expectedException = ExpectedException.none();

    @Test
    public void rejectsInconsistencyBetweenDescriptionAndPlaceholdersInPut() {
        expectedException.expect(BadRequestException.class);
        expectedException.expectMessage("Description and placeholder keys must match.");

        Experiment experiment = Experiment.newBuilder().setDescription("{{Person}}").build();
        when(request.attribute("input")).thenReturn(experiment);

        resource.put(request, response);
    }

    @Test
    public void succeedsWithoutInconsistencyBetweenDescriptionAndPlaceholdersInPutWithoutPlaceholders() {
        expectedException.expect(RuntimeException.class);
        expectedException.expectMessage("Everything went fine");

        Experiment experiment = Experiment.newBuilder().setDescription("foobar").build();
        when(request.attribute("input")).thenReturn(experiment);

        when(experimentOperations.insertNewExperiment(any())).thenThrow(new RuntimeException("Everything went fine"));

        resource.put(request, response);
    }

    @Test
    public void succeedsWithoutInconsistencyBetweenDescriptionAndPlaceholdersInPutWithPlaceholders() {
        expectedException.expect(RuntimeException.class);
        expectedException.expectMessage("Everything went fine");

        Map<String, String> placeholders = new HashMap<>();
        placeholders.put("foobar", "foo");

        Experiment experiment = Experiment.newBuilder().setDescription("{{foobar}}").putAllPlaceholders(placeholders).build();
        when(request.attribute("input")).thenReturn(experiment);

        when(experimentOperations.insertNewExperiment(any())).thenThrow(new RuntimeException("Everything went fine"));

        resource.put(request, response);
    }
}

@@ -525,23 +525,74 @@
 va.util.
-HashMap
+ArrayList;%0Aimport java.util.HashMap;%0Aimport java.util.List
 ;%0Aimport
@@ -2564,32 +2564,84 @@
 nt.newBuilder().
+addAllRatingOptions(generateDefaultRatingOptions()).
 setDescription(%22
@@ -3064,32 +3064,84 @@
 nt.newBuilder().
+addAllRatingOptions(generateDefaultRatingOptions()).
 setDescription(%22
@@ -3789,16 +3789,68 @@
 ilder().
+addAllRatingOptions(generateDefaultRatingOptions()).
 setDescr
@@ -4090,32 +4090,32 @@
  went fine%22));%0A%0A
-
         resource
@@ -4144,11 +4144,399 @@
 );%0A    %7D
+%0A%0A    private List%3CExperiment.RatingOption%3E generateDefaultRatingOptions() %7B%0A        List%3CExperiment.RatingOption%3E ratingOptions = new ArrayList%3C%3E();%0A%0A        ratingOptions.add(Experiment.RatingOption.newBuilder().setName(%22Good%22).setValue(9).build());%0A        ratingOptions.add(Experiment.RatingOption.newBuilder().setName(%22Bad%22).setValue(0).build());%0A%0A        return ratingOptions;%0A    %7D
 %0A%7D%0A

Add rating options to tests to fix them up