package net.unit8.bouncr.hook;

import com.fasterxml.jackson.databind.ObjectMapper;
import net.jodah.failsafe.Failsafe;
import net.jodah.failsafe.RetryPolicy;
import okhttp3.*;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;

public class WebHook<T> implements Hook<T> {
    private static final OkHttpClient client = new OkHttpClient();
    private static final ObjectMapper mapper = new ObjectMapper();
    private static final MediaType JSON = MediaType.parse("application/json");
    private static ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);

    private RetryPolicy idempotent = new RetryPolicy()
            .withBackoff(3, 10, TimeUnit.SECONDS)
            .retryOn(SocketTimeoutException.class)
            .retryIf(res -> Stream.of(res)
                    .map(Response.class::cast)
                    .map(Response::code)
                    .filter(code -> code >= 500)
                    .findAny()
                    .isPresent());

    private RetryPolicy notIdempotent = new RetryPolicy()
            .withBackoff(3, 10, TimeUnit.SECONDS)
            .retryIf(res -> Stream.of(res)
                    .map(Response.class::cast)
                    .map(Response::code)
                    .filter(code -> code >= 500)
                    .findAny()
                    .isPresent());

    private final String method;
    private final String url;

    public WebHook(String url, String method) {
        this.url = url;
        this.method = method;
    }

    @Override
    public void run(T object) {
        RetryPolicy retryPolicy = method.equalsIgnoreCase("get") ? idempotent : notIdempotent;
        Failsafe.with(retryPolicy)
                .with(executor)
                .onSuccess(response -> {

                })
                .get(() -> {
                    RequestBody body = RequestBody.create(JSON, mapper.writeValueAsString(object));
                    Request request = new Request.Builder()
                            .url(url)
                            .header("content-type", "application/json")
                            .method(method, body)
                            .build();
                    return client.newCall(request).execute();
                });
    }
}

@@ -175,36 +175,8 @@
 *;%0A%0A
-import java.io.IOException;%0A
 impo
@@ -211,16 +211,38 @@
 eption;%0A
+import java.util.Map;%0A
 import j
@@ -1048,38 +1048,40 @@
                .
-filter
+anyMatch
 (code -%3E code %3E=
@@ -1089,72 +1089,8 @@
 500)
-%0A                    .findAny()%0A                    .isPresent()
 );%0A%0A
@@ -1353,14 +1353,16 @@
    .
-filter
+anyMatch
 (cod
@@ -1382,72 +1382,8 @@
 500)
-%0A                    .findAny()%0A                    .isPresent()
 );%0A%0A
@@ -1444,16 +1444,64 @@
 ing url;
+%0A    private Map%3CString, String%3E headers = null;
 %0A%0A    pu
@@ -1603,16 +1603,186 @@
 %0A    %7D%0A%0A
+    public WebHook(String url, String method, Map%3CString, String%3E headers) %7B%0A        this.url = url;%0A        this.method = method;%0A        this.headers = headers;%0A    %7D%0A%0A
     @Ove
@@ -2202,16 +2202,67 @@
 uest
- request
+.Builder requestBuilder;%0A                    requestBuilder
  = n
@@ -2441,16 +2441,17 @@
 d, body)
+;
 %0A       
@@ -2467,25 +2467,120 @@
     
-        .build();
+if (headers != null) %7B%0A                        headers.forEach(requestBuilder::addHeader);%0A                    %7D
 %0A   
@@ -2625,16 +2625,31 @@
 (request
+Builder.build()
 ).execut

Change WebHook can setting headers from other class.