package it.w0rd.api;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import it.w0rd.DataTest;
import it.w0rd.api.requests.ShortenerRequest;
import it.w0rd.persistence.db.DictionaryManager;
import it.w0rd.persistence.redis.RedisManager;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

public class UserApiTest extends DataTest {

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    @Autowired
    private WebApplicationContext wac;

    @Autowired
    protected DictionaryManager dictionaryManager;

    @Autowired
    protected RedisManager redisManager;


    @Value("${app.host}")
    private String host;

    @Value("${app.protocol}")
    private String protocol;

    private MockMvc mockMvc;

    @Before
    public void initMockMvc() throws IOException {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
    }

    @Test
    public void shouldReturnGeneralStats() throws Exception {
        MvcResult mvcResult = mockMvc.perform(get("/api/stats").contentType(MediaType.APPLICATION_JSON_VALUE))
                .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
                .andExpect(status().isOk())
                .andReturn();

        ShortenerStats shortenerStats = OBJECT_MAPPER.readValue(mvcResult.getResponse().getContentAsString(), new TypeReference<ShortenerStats>() {
        });
        assertThat(shortenerStats.getRemainingCount(), equalTo(21L));
        assertThat(shortenerStats.getShortenedCount(), equalTo(0L));
    }

    @Test
    public void shouldAddShortenedURLWhenPostedTo() throws Exception {
        assertThat(dictionaryManager.size(), equalTo(21L));

        ShortenerRequest request = new ShortenerRequest("https://run.pivotal.io/");

        byte[] requestJson = OBJECT_MAPPER.writeValueAsBytes(request);

        MvcResult postResponse = mockMvc.perform(post("/api/shorten")
                .content(requestJson).contentType(MediaType.APPLICATION_JSON_VALUE))
                .andExpect(status().is2xxSuccessful())
                .andExpect(content().contentType("application/json"))
                .andReturn();

        String responseAsString = postResponse.getResponse().getContentAsString();
        ShortenerResponse response = OBJECT_MAPPER.readValue(responseAsString, new TypeReference<ShortenerResponse>() {
        });
        assertThat(response.getOriginal().toString(), equalTo(request.getUrl()));
    }

    @Test
    @Ignore
    public void shouldGetErrorMessageWhenSubmittingAnInvalidURL() throws Exception {
        ShortenerRequest request = new ShortenerRequest("htp://invalid.url");

        byte[] requestJson = OBJECT_MAPPER.writeValueAsBytes(request);

        MvcResult postResponse = mockMvc.perform(post("/api/shorten").content(requestJson).contentType(MediaType.APPLICATION_JSON_VALUE))
                .andExpect(status().is(400))
                .andExpect(content().contentType("application/json"))
                .andReturn();

        ShortenerException exception = OBJECT_MAPPER.readValue(postResponse.getResponse().getContentAsString(), new TypeReference<ShortenerException>() {
        });
        assertThat(exception.getMessage(), equalTo("Could not parse your URL: unknown protocol: htp"));
    }

    public byte[] ojectToBytes(Object o) throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutput out;
        out = new ObjectOutputStream(bos);
        out.writeObject(o);
        return bos.toByteArray();
    }

}

@@ -893,16 +893,55 @@
 tStream;
+%0Aimport java.net.MalformedURLException;
 %0A%0Aimport
@@ -1563,245 +1563,12 @@
 ac;%0A
-%0A
     
-@Autowired%0A    protected DictionaryManager dictionaryManager;%0A%0A    @Autowired%0A    protected RedisManager redisManager;%0A%0A%0A    @Value(%22$%7Bapp.host%7D%22)%0A    private String host;%0A%0A    @Value(%22$%7Bapp.protocol%7D%22)%0A    private String protocol;%0A
 %0A   
@@ -2235,32 +2235,33 @@
 ) %7B%0A        %7D);%0A
+%0A
         assertTh
@@ -2483,214 +2483,108 @@
     
-assertThat(dictionaryManager.size(), equalTo(21L));%0A%0A        ShortenerRequest request = new ShortenerRequest(%22https://run.pivotal.io/%22);%0A%0A        byte%5B%5D requestJson = OBJECT_MAPPER.writeValueAsBytes(request
+byte%5B%5D requestJson = OBJECT_MAPPER.writeValueAsBytes(new ShortenerRequest(%22https://run.pivotal.io/%22)
 );%0A%0A
@@ -3101,32 +3101,33 @@
 ) %7B%0A        %7D);%0A
+%0A
         assertTh
@@ -3176,56 +3176,124 @@
 lTo(
-request.getUrl()));%0A    %7D%0A%0A    @Test%0A    @Ignore
+new ShortenerRequest(%22https://run.pivotal.io/%22).getUrl()));%0A    %7D%0A%0A    @Test(expected = MalformedURLException.class)
 %0A   
@@ -3536,33 +3536,8 @@
     
- MvcResult postResponse =
  moc
@@ -3786,279 +3786,8 @@
 n();
-%0A%0A        ShortenerException exception = OBJECT_MAPPER.readValue(postResponse.getResponse().getContentAsString(), new TypeReference%3CShortenerException%3E() %7B%0A        %7D);%0A        assertThat(exception.getMessage(), equalTo(%22Could not parse your URL: unknown protocol: htp%22));
 %0A   
@@ -3809,16 +3809,17 @@
 byte%5B%5D o
+b
 jectToBy

Tidy up UserApiTest