package org.jboss.resteasy.reactive.server.filters;

import io.smallrye.mutiny.Uni;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import javax.ws.rs.core.Response;
import org.jboss.resteasy.reactive.RestResponse;
import org.jboss.resteasy.reactive.server.ServerRequestFilter;
import org.jboss.resteasy.reactive.server.ServerResponseFilter;
import org.jboss.resteasy.reactive.server.spi.ResteasyReactiveContainerRequestContext;

/**
 * This class is used by the filters that are generated as a result of the use of {@link ServerRequestFilter} or
 * {@link ServerResponseFilter} on methods
 * that don't return {@code void}.
 * See {@code io.quarkus.resteasy.reactive.server.deployment.CustomFilterGenerator}
 */
@SuppressWarnings("unused")
public final class FilterUtil {

    private FilterUtil() {
    }

    public static void handleOptional(Optional<Response> optional,
            ResteasyReactiveContainerRequestContext context) {
        if ((optional != null) && optional.isPresent()) {
            context.abortWith(optional.get());
        }
    }

    public static void handleOptionalRestResponse(Optional<RestResponse> optional,
            ResteasyReactiveContainerRequestContext context) {
        if ((optional != null) && optional.isPresent()) {
            context.abortWith(optional.get().toResponse());
        }
    }

    public static void handleResponse(Response response,
            ResteasyReactiveContainerRequestContext context) {
        if (response != null) {
            context.abortWith(response);
        }
    }

    public static void handleRestResponse(RestResponse response,
            ResteasyReactiveContainerRequestContext context) {
        if (response != null) {
            context.abortWith(response.toResponse());
        }
    }

    public static void handleUniVoid(Uni<Object> uni, ResteasyReactiveContainerRequestContext context) {
        if (uni == null) {
            return;
        }
        context.suspend();
        uni.subscribe().with(new Consumer<Object>() {
            @Override
            public void accept(Object unused) {
                context.resume();
            }
        }, new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) {
                context.resume(throwable);
            }
        });
    }

    public static void handleUniResponse(Uni<Response> uni, ResteasyReactiveContainerRequestContext context) {
        if (uni == null) {
            return;
        }
        context.suspend();
        uni.subscribe().with(new Consumer<Response>() {
            @Override
            public void accept(Response response) {
                if (response != null) {
                    context.abortWith(response);
                } else {
                    context.resume();
                }
            }
        }, new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) {
                context.resume(throwable);
            }
        });
    }

    public static void handleUniRestResponse(Uni<? extends RestResponse<?>> uni,
            ResteasyReactiveContainerRequestContext context) {
        if (uni == null) {
            return;
        }
        handleUniResponse(uni.map(new Function<RestResponse<?>, Response>() {
            @Override
            public Response apply(RestResponse<?> t) {
                return t != null ? t.toResponse() : null;
            }
        }), context);
    }
}

@@ -1167,32 +1167,35 @@
 nal%3CRestResponse
+%3C?%3E
 %3E optional,%0A    
@@ -1644,32 +1644,35 @@
 nse(RestResponse
+%3C?%3E
  response,%0A     
@@ -2063,22 +2063,16 @@
 onsumer%3C
-Object
 %3E() %7B%0A  
@@ -2129,22 +2129,17 @@
 (Object 
-unused
+o
 ) %7B%0A    
@@ -2193,33 +2193,30 @@
      %7D, new 
-Con
+Re
 sume
-r%3C
 Throwable%3E()
@@ -2216,156 +2216,25 @@
 able
-%3E() %7B%0A            @Override%0A            public void accept(Throwable throwable) %7B%0A                context.resume(throwable);%0A            %7D%0A        %7D
+Consumer(context)
 );%0A 
@@ -2476,24 +2476,16 @@
 onsumer%3C
-Response
 %3E() %7B%0A  
@@ -2755,25 +2755,22 @@
  %7D, new 
-Con
+Re
 sume
-r%3C
 Throwabl
@@ -2774,156 +2774,25 @@
 able
-%3E() %7B%0A            @Override%0A            public void accept(Throwable throwable) %7B%0A                context.resume(throwable);%0A            %7D%0A        %7D
+Consumer(context)
 );%0A 
@@ -3252,11 +3252,426 @@
 );%0A    %7D
+%0A%0A    private static class ResumeThrowableConsumer implements Consumer%3CThrowable%3E %7B%0A        private final ResteasyReactiveContainerRequestContext context;%0A%0A        public ResumeThrowableConsumer(ResteasyReactiveContainerRequestContext context) %7B%0A            this.context = context;%0A        %7D%0A%0A        @Override%0A        public void accept(Throwable throwable) %7B%0A            context.resume(throwable);%0A        %7D%0A    %7D
 %0A%7D%0A

Apply minor polish to FilterUtil