package oasis.http;

import static org.assertj.core.api.Assertions.*;

import java.nio.charset.StandardCharsets;

import javax.inject.Inject;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.jukito.JukitoModule;
import org.jukito.JukitoRunner;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import com.google.api.client.repackaged.com.google.common.base.Strings;
import com.squareup.okhttp.mockwebserver.Dispatcher;
import com.squareup.okhttp.mockwebserver.MockResponse;
import com.squareup.okhttp.mockwebserver.RecordedRequest;
import com.squareup.okhttp.mockwebserver.rule.MockWebServerRule;

import oasis.web.webhooks.WebhookSignatureFilter;

@RunWith(JukitoRunner.class)
public class OkHttpClientEngineTest {

  private static final String SECRET = "This is a secret";
  private static final byte[] PAYLOAD = "This is the request payload".getBytes(StandardCharsets.UTF_8);
  private static final String SIGNATURE = "sha1=3daba1f18d85905076a8ed72caf13565ece571fb";

  public static class Module extends JukitoModule {
    @Override
    protected void configureTest() {
      install(new HttpClientModule());
    }
  }

  @Rule public MockWebServerRule mockServer = new MockWebServerRule();
  @Before public void setUp() {
    mockServer.get().setDispatcher(new Dispatcher() {
      @Override
      public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
        assertThat(request.getBody().readByteArray()).isEqualTo(PAYLOAD);
        return new MockResponse()
            .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN)
            .setHeader("X-Whatever", "some header")
            .setBody(Strings.nullToEmpty(request.getHeader(WebhookSignatureFilter.HEADER)));
      }
    });
  }

  @Inject Client client;

  @Test public void simpleRequest() {
    Response response = client.target(mockServer.getUrl("/simple").toString()).request()
        .post(Entity.json(PAYLOAD));

    assertThat(response.getStatusInfo()).isEqualTo(Response.Status.OK);
    assertThat(response.getMediaType()).isEqualTo(MediaType.TEXT_PLAIN_TYPE);
    assertThat(response.getHeaderString("X-Whatever")).isEqualTo("some header");
  }

  @Test public void requestHeader() {
    Response response = client.target(mockServer.getUrl("/requestHeader").toString()).request()
        .header(WebhookSignatureFilter.HEADER, SIGNATURE)
        .post(Entity.json(PAYLOAD));

    assertThat(response.getStatusInfo()).isEqualTo(Response.Status.OK);
    String signature = response.readEntity(String.class);
    assertThat(signature).isEqualTo(SIGNATURE);
  }

  @Test public void simpleWriterInterceptors() {
    Response response = client.target(mockServer.getUrl("/writerInterceptor").toString())
        .register(new WebhookSignatureFilter(SECRET))
        .request()
        .post(Entity.json(PAYLOAD));

    assertThat(response.getStatusInfo()).isEqualTo(Response.Status.OK);
    String signature = response.readEntity(String.class);
    assertThat(signature)
        .startsWith("sha1=") // the prefix is case-sensitive
        .isEqualToIgnoringCase(SIGNATURE);
  }
}

@@ -468,94 +468,54 @@
 t.ru
-nner.RunWith;%0A%0Aimport com.google.api.client.repackaged.com.google.common.base.Strings;
+les.Timeout;%0Aimport org.junit.runner.RunWith;%0A
 %0Aimp
@@ -1270,16 +1270,160 @@
  %7D%0A  %7D%0A%0A
+  // In case an error is thrown in the MockWebServer, so clients don't block infinitely.%0A  @Rule public Timeout timeout = Timeout.seconds(10);%0A%0A
   @Rule 
@@ -1685,26 +1685,23 @@
         
-assertThat
+switch 
 (request
@@ -1708,60 +1708,53 @@
 .get
-Body().readByteArray()).isEqualTo(PAYLOAD);%0A
+Path()) %7B%0A          case %22/simple%22:%0A 
         
 retu
@@ -1749,16 +1749,19 @@
         
+   
 return n
@@ -1778,16 +1778,96 @@
 ponse()%0A
+                .setResponseCode(Response.Status.NOT_FOUND.getStatusCode())%0A    
         
@@ -1933,32 +1933,36 @@
 IN)%0A            
+   
+ 
 .setHeader(%22X-Wh
@@ -1993,24 +1993,28 @@
             
+    
 .setBody(Str
@@ -2014,77 +2014,462 @@
 ody(
-Strings.nullToEmpty(request.getHeader(WebhookSignatureFilter.HEADER))
+%22Not found%22);%0A          case %22/writerInterceptor%22:%0A            assertThat(request.getBody().readByteArray()).isEqualTo(PAYLOAD);%0A            // fall-through%0A          case %22/requestHeader%22:%0A            return new MockResponse()%0A                .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN)%0A                .setBody(request.getHeader(WebhookSignatureFilter.HEADER));%0A        %7D%0A        throw new AssertionError(%22Unexpected request: %22 + request
 );%0A 
@@ -2644,43 +2644,13 @@
 st()
-%0A        .post(Entity.json(PAYLOAD)
+.get(
 );%0A%0A
@@ -2712,26 +2712,33 @@
 onse.Status.
-OK
+NOT_FOUND
 );%0A    asser
@@ -2887,16 +2887,90 @@
 ader%22);%0A
+    assertThat(response.readEntity(String.class)).isEqualTo(%22Not found%22);%0A
   %7D%0A%0A  @
@@ -3171,33 +3171,12 @@
    .
-post(Entity.json(PAYLOAD)
+get(
 );%0A%0A

Enhance OkHttpClientEngineTest