package org.folio.okapi.common;

import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpClientRequest;
import io.vertx.core.http.HttpServer;
import io.vertx.ext.unit.Async;
import io.vertx.ext.unit.TestContext;
import io.vertx.ext.unit.junit.VertxUnitRunner;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(VertxUnitRunner.class)
public class PauseResumeTest {

  private Vertx vertx;
  private HttpServer server;
  private static final int PORT = 9230;

  private void myStreamHandle1(RoutingContext ctx) {
    ctx.response().end("OK1");
  }

  private void myStreamHandle2(RoutingContext ctx) {
    ctx.request().pause();
    HttpClient cli = vertx.createHttpClient();
    HttpClientRequest req = cli.get(PORT, "localhost", "/test1", res -> {
      ctx.request().endHandler(x -> {
        ctx.response().end("OK2");
      });
      ctx.request().resume();
    });
    req.exceptionHandler(x -> {
      ctx.response().setStatusCode(500);
      ctx.response().end(x.getLocalizedMessage());
    });
    req.end();
  }

  @Before
  public void setUp(TestContext context) {
    vertx = Vertx.vertx();

    Router router = Router.router(vertx);
    router.get("/test1").handler(this::myStreamHandle1);
    router.get("/test2").handler(this::myStreamHandle2);

    server = vertx.createHttpServer()
      .requestHandler(router::accept)
      .listen(PORT, context.asyncAssertSuccess());
  }

  @After
  public void tearDown(TestContext context) {
    vertx.close(context.asyncAssertSuccess());
  }

  @Test
  public void test1(TestContext context) {
    Async async = context.async();

    HttpClient cli = vertx.createHttpClient();
    HttpClientRequest req = cli.get(PORT, "localhost", "/test1", res -> {
      Buffer b = Buffer.buffer();
      res.handler(b::appendBuffer);
      res.endHandler(res2 -> {
        context.assertEquals("OK1", b.toString());
        context.assertEquals(200, res.statusCode());
        async.complete();
      });
    });
    req.end();
  }

  @Test
  public void test2(TestContext context) {
    Async async = context.async();

    HttpClient cli = vertx.createHttpClient();
    HttpClientRequest req = cli.get(PORT, "localhost", "/test2", res -> {
      Buffer b = Buffer.buffer();
      res.handler(b::appendBuffer);
      res.endHandler(res2 -> {
        context.assertEquals("OK2", b.toString());
        context.assertEquals(200, res.statusCode());
        async.complete();
      });
    });
    req.end();
  }
}

@@ -904,34 +904,35 @@
 quest req = cli.
-ge
+pos
 t(PORT, %22localho
@@ -951,24 +951,134 @@
 %22, res -%3E %7B%0A
+      if (ctx.request().isEnded()) %7B%0A        ctx.response().end(%22OK2%22); // Vert.x 3.6 series%0A      %7D else %7B%0A  
       ctx.re
@@ -1099,24 +1099,26 @@
 dler(x -%3E %7B%0A
+  
         ctx.
@@ -1142,28 +1142,38 @@
 K2%22);%0A      
+  
 %7D);%0A
+      %7D%0A
       ctx.re
@@ -1476,34 +1476,35 @@
 tx);%0A    router.
-ge
+pos
 t(%22/test1%22).hand
@@ -1542,18 +1542,19 @@
  router.
-ge
+pos
 t(%22/test
@@ -1987,34 +1987,35 @@
 quest req = cli.
-ge
+pos
 t(PORT, %22localho
@@ -2473,18 +2473,502 @@
 q = cli.
-ge
+post(PORT, %22localhost%22, %22/test2%22, res -%3E %7B%0A      Buffer b = Buffer.buffer();%0A      res.handler(b::appendBuffer);%0A      res.endHandler(res2 -%3E %7B%0A        context.assertEquals(%22OK2%22, b.toString());%0A        context.assertEquals(200, res.statusCode());%0A        async.complete();%0A      %7D);%0A    %7D);%0A    req.end(%22foo%22);%0A  %7D%0A%0A  @Test%0A  public void test3(TestContext context) %7B%0A    Async async = context.async();%0A%0A    HttpClient cli = vertx.createHttpClient();%0A    HttpClientRequest req = cli.pos
 t(PORT, 

Handle Vert.x 3.6.x already ends empty HTTP body (#741)