package io.jooby.i2572;

import static org.junit.jupiter.api.Assertions.assertEquals;

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

import org.json.JSONObject;

import io.jooby.ExecutionMode;
import io.jooby.Jooby;
import io.jooby.json.JacksonModule;
import io.jooby.junit.ServerTest;
import io.jooby.junit.ServerTestRunner;

public class Issue2572 {

  private static class App2572 extends Jooby {
    Map<String, Object> state = new LinkedHashMap<>();

    {
      install(new JacksonModule());

      get("/2572/state", ctx -> state);

      decorator(next -> ctx -> {
        state.put("caller", Thread.currentThread().getName());
        ctx.onComplete(context -> {
          state.put("onComplete", Thread.currentThread().getName());
        });
        return next.apply(ctx);
      });

      get("/2572/init", ctx -> "Initialized");
    }
  }

  @ServerTest(executionMode = {ExecutionMode.EVENT_LOOP, ExecutionMode.WORKER})
  public void onCompleteShouldRunOnCallerThread(ServerTestRunner runner) {
    runner.use(App2572::new).ready(http -> {
      http.get("/2572/init", rsp -> {
        assertEquals("Initialized", rsp.body().string());
      });

      http.get("/2572/state", rsp -> {
        JSONObject json = new JSONObject(rsp.body().string());
        assertEquals(json.get("caller"), json.get("onComplete"));
      });
    });
  }
}

@@ -97,26 +97,16 @@
 va.util.
-LinkedHash
 Map;%0Aimp
@@ -123,96 +123,111 @@
 til.
-Map;%0A%0Aimport org.json.JSONObject;%0A%0Aimport io.jooby.ExecutionMode
+concurrent.ConcurrentHashMap;%0Aimport java.util.concurrent.CountDownLatch
 ;%0A
+%0A
 import 
-io.jooby.Jooby;
+org.json.JSONObject;%0A
 %0Aimp
@@ -366,53 +366,124 @@
 %0A%0A  
-private static class App2572 extends Jooby
+@ServerTest%0A  public void onCompleteShouldRunOnCallerThread(ServerTestRunner runner) %7B%0A    runner.define(app -%3E
  %7B%0A
+  
     
@@ -518,14 +518,18 @@
 new 
-Linked
+Concurrent
 Hash
@@ -542,24 +542,74 @@
 );%0A%0A    
-%7B
+  CountDownLatch latch = new CountDownLatch(1);
 %0A      
+app.
 install(
@@ -629,32 +629,36 @@
 dule());%0A%0A      
+app.
 get(%22/2572/state
@@ -667,21 +667,70 @@
  ctx -%3E 
-state
+%7B%0A        latch.await();%0A        return state;%0A      %7D
 );%0A%0A    
@@ -731,16 +731,20 @@
 %0A%0A      
+app.
 decorato
@@ -922,32 +922,61 @@
 d().getName());%0A
+          latch.countDown();%0A
         %7D);%0A    
@@ -1020,16 +1020,20 @@
 %0A%0A      
+app.
 get(%22/25
@@ -1074,196 +1074,8 @@
    %7D
-%0A  %7D%0A%0A  @ServerTest(executionMode = %7BExecutionMode.EVENT_LOOP, ExecutionMode.WORKER%7D)%0A  public void onCompleteShouldRunOnCallerThread(ServerTestRunner runner) %7B%0A    runner.use(App2572::new
 ).re
@@ -1118,32 +1118,84 @@
 init%22, rsp -%3E %7B%0A
+        System.out.println(Thread.currentThread());%0A
         assertEq
@@ -1298,59 +1298,192 @@
     
-JSONObject json = new JSONObject(rsp.body().string(
+System.out.println(Thread.currentThread());%0A        JSONObject json = new JSONObject(rsp.body().string());%0A        System.out.println(json.get(%22caller%22) + %22 = %22 + json.get(%22onComplete%22
 ));%0A

fix random failure caused by raise condition