package org.educama;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.restdocs.JUnitRestDocumentation;
import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler;
import org.springframework.restdocs.payload.FieldDescriptor;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import java.util.LinkedHashMap;
import java.util.Map;

import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
import static org.springframework.restdocs.operation.preprocess.Preprocessors.*;
import static org.springframework.restdocs.payload.PayloadDocumentation.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

/**
 * This class uses Spring Rest Docs to generate example requests which are embedded into asciidoc/rest-api.adoc.
 * The result is transformend to HTML and served at /docs/rest-api.html
 *
 * Documentation: http://docs.spring.io/spring-restdocs/docs/current/reference/html5
 */
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = EducamaApplication.class, webEnvironment= SpringBootTest.WebEnvironment.DEFINED_PORT)
public class RestApiDocumentation {
	
	@Rule
	public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("target/generated-snippets");

	@Autowired
	private ObjectMapper objectMapper;

	@Autowired
	private WebApplicationContext context;

	private MockMvc mockMvc;

	private RestDocumentationResultHandler documentationHandler;

	private FieldDescriptor[] fieldDescriptorShipment;

	@Before
	public void setUp() {
		this.documentationHandler = document("{methodName}",
				preprocessRequest(prettyPrint()),
				preprocessResponse(prettyPrint()));

		this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
				.apply(documentationConfiguration(this.restDocumentation).uris().withPort(8081))
				.alwaysDo(this.documentationHandler)
				.build();

		fieldDescriptorShipment = new FieldDescriptor[] {
				fieldWithPath("id").description("The unique database identifier"),
				fieldWithPath("trackingId").description("The unique business key of the shipment"),
				fieldWithPath("customer").description("The name of the customer"),
				fieldWithPath("senderAddress").description("The address of the sender"),
				fieldWithPath("receiverAddress").description("The address of the final receiver") };
	}

	@Test
	public void createShipment() throws Exception {
		Map<String,String> shipment = new LinkedHashMap<>();
		shipment.put("customer", "NovaTec Consulting GmbH");
		shipment.put("senderAddress", "Dieselstr. 18/1, 70771 Leinfelden-Echterdingen, Germany");
		shipment.put("receiverAddress", "Santa Claus Main Post Office, FI-96930 Arctic Circle, Finland");
		this.mockMvc.perform(post("/educama/v1/shipments").contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsBytes(shipment)))
				.andExpect(status().isCreated())
				.andDo(this.documentationHandler.document(
						requestFields(
								fieldWithPath("customer").description("The name of the customer"),
								fieldWithPath("senderAddress").description("The address of the sender"),
								fieldWithPath("receiverAddress").description("The address of the final receiver")
						),
						responseFields(fieldDescriptorShipment)
				));

	}

	@Test
	public void listShipment() throws Exception {
		this.mockMvc.perform(get("/educama/v1/shipments"))
			.andExpect(status().isOk())
			.andDo(this.documentationHandler.document(
					responseFields(
							fieldWithPath("shipments[]").description("An array of shipment objects")).andWithPrefix("shipments[].", fieldDescriptorShipment)));

	}
}

@@ -19,61 +19,8 @@
 a;%0A%0A
-import com.fasterxml.jackson.annotation.JsonInclude;%0A
 impo
@@ -2406,16 +2406,23 @@
 Request(
+%0A%09%09%09%09%09%09
 prettyPr
@@ -2426,16 +2426,45 @@
 yPrint()
+,%0A%09%09%09%09%09%09removeHeaders(%22Host%22)
 ),%0A%09%09%09%09p
@@ -2630,30 +2630,8 @@
 ion)
-.uris().withPort(8081)
 )%0A%09%09
@@ -4052,17 +4052,16 @@
 %09%09%09%09));%0A
-%0A
 %09%7D%0A%0A%09@Te
@@ -4400,14 +4400,13 @@
 ent)));%0A
-%0A
 %09%7D%0A%7D%0A

Remove host and port from REST API documentation because they are misleading, i.e. those were used to execute the tests.