package com.example.rest.bdd.yatspec.util;

import com.example.rest.bdd.WebApp;
import com.example.rest.bdd.config.WebConfig;
import com.googlecode.yatspec.junit.SpecResultListener;
import com.googlecode.yatspec.junit.SpecRunner;
import com.googlecode.yatspec.junit.WithCustomResultListeners;
import com.googlecode.yatspec.plugin.sequencediagram.ByNamingConventionMessageProducer;
import com.googlecode.yatspec.plugin.sequencediagram.SequenceDiagramGenerator;
import com.googlecode.yatspec.plugin.sequencediagram.SequenceDiagramMessage;
import com.googlecode.yatspec.plugin.sequencediagram.SvgWrapper;
import com.googlecode.yatspec.rendering.html.DontHighlightRenderer;
import com.googlecode.yatspec.rendering.html.HtmlResultRenderer;
import com.googlecode.yatspec.rendering.html.index.HtmlIndexRenderer;
import com.googlecode.yatspec.state.givenwhenthen.ActionUnderTest;
import com.googlecode.yatspec.state.givenwhenthen.CapturedInputAndOutputs;
import com.googlecode.yatspec.state.givenwhenthen.InterestingGivens;
import com.googlecode.yatspec.state.givenwhenthen.TestState;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.web.context.WebApplicationContext;

import static com.googlecode.yatspec.internal.totallylazy.$Sequences.sequence;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;

@RunWith(SpecRunner.class)
public class RestTestCase extends TestState implements WithCustomResultListeners {

    private static WebApplicationContext applicationContext;
    private static MockMvc mockMvc;
    private ResultActions resultActions;
    private SequenceDiagramGenerator sequenceDiagramGenerator;


    @BeforeClass
    public static void startServer() throws Exception {
        if (applicationContext == null) {
            applicationContext = new WebApp().start(WebConfig.class);
        }
    }

    public static <T> T then(T t) {
        return t;
    }

    public static <T> T to(T t) {
        return t;
    }

    @Before
    public void setup() {
        sequenceDiagramGenerator = new SequenceDiagramGenerator();
        mockMvc = webAppContextSetup(applicationContext).dispatchOptions(true).alwaysDo(new CaptureResultHandler(capturedInputAndOutputs)).build();
    }

    @Override
    public Iterable<SpecResultListener> getResultListeners() throws Exception {
        return sequence(
                new HtmlResultRenderer().
                        withCustomHeaderContent(SequenceDiagramGenerator.getHeaderContentForModalWindows()).
                        withCustomRenderer(SvgWrapper.class, new DontHighlightRenderer()),
                new HtmlIndexRenderer()).
                safeCast(SpecResultListener.class);
    }

    @After
    public void generateSequenceDiagram() {
        Iterable<SequenceDiagramMessage> messages = sequence(new ByNamingConventionMessageProducer().messages(capturedInputAndOutputs));
        capturedInputAndOutputs.add("Sequence Diagram", sequenceDiagramGenerator.generateSequenceDiagram(messages));
    }

    protected ResultActions response(ResultMatcher matcher) throws Exception {
        return resultActions.andExpect(matcher);
    }

    protected ActionUnderTest requested(final MockHttpServletRequestBuilder requestBuilder) {
        return new ActionUnderTest() {
            @Override
            public CapturedInputAndOutputs execute(InterestingGivens interestingGivens, CapturedInputAndOutputs capturedInputAndOutputs) throws Exception {
                resultActions = mockMvc.perform(requestBuilder);
                return capturedInputAndOutputs;
            }
        };
    }
}

@@ -1578,16 +1578,104 @@
 quence;%0A
+import static com.googlecode.yatspec.plugin.sequencediagram.SequenceDiagramGenerator.*;%0A
 import s
@@ -2073,17 +2073,16 @@
 rator;%0A%0A
-%0A
     @Bef
@@ -2279,128 +2279,8 @@
  %7D%0A%0A
-    public static %3CT%3E T then(T t) %7B%0A        return t;%0A    %7D%0A%0A    public static %3CT%3E T to(T t) %7B%0A        return t;%0A    %7D%0A%0A
     
@@ -2436,16 +2436,33 @@
 Context)
+%0A                
 .dispatc
@@ -2475,16 +2475,33 @@
 ns(true)
+%0A                
 .alwaysD
@@ -2782,33 +2782,8 @@
 ent(
-SequenceDiagramGenerator.
 getH
@@ -3570,165 +3570,28 @@
 urn 
-new ActionUnderTest() %7B%0A            @Override%0A            public CapturedInputAndOutputs execute(InterestingGivens interestingGivens, CapturedInputAndOutputs
+(interestingGivens1,
  cap
@@ -3614,33 +3614,16 @@
 puts
+1
 ) 
-throws Exception %7B%0A    
+-%3E %7B%0A
     
@@ -3687,28 +3687,24 @@
             
-    
 return captu
@@ -3721,16 +3721,17 @@
 dOutputs
+1
 ;%0A      
@@ -3736,23 +3736,129 @@
     
+%7D;%0A
     %7D%0A
+%0A
     
-    %7D
+public static %3CT%3E T then(T t) %7B%0A        return t;%0A    %7D%0A%0A    public static %3CT%3E T to(T t) %7B%0A        return t
 ;%0A  

Beautify some code