package org.jboss.resteasy.client.jaxrs.engines;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

import jakarta.ws.rs.client.InvocationCallback;

import org.jboss.resteasy.client.jaxrs.ClientHttpEngine;
import org.jboss.resteasy.client.jaxrs.internal.ClientInvocation;
import org.jboss.resteasy.client.jaxrs.internal.ClientResponse;

/**
 * Interface for an async HttpClientEngine
 *
 * @author Markus Kull
 */
public interface AsyncClientHttpEngine extends ClientHttpEngine {

    /**
     * Interface for extracting a result out of a ClientResponse
     *
     * @param <T> Result-Type
     */
    interface ResultExtractor<T> {
        /**
         * Extracts a result out of a Response
         *
         * @param response Response
         * @return result
         */
        T extractResult(ClientResponse response);
    }

    /**
     * Submits an asynchronous request.
     *
     * @param <T>       type
     * @param request   Request
     * @param buffered  buffer the response?
     * @param callback  Optional callback receiving the result, which is run inside the io-thread. may be null.
     * @param extractor ResultExtractor for extracting a result out of a ClientResponse. Is run inside the io-thread
     * @return Future with the result or Exception
     */
    <T> Future<T> submit(ClientInvocation request, boolean buffered, InvocationCallback<T> callback,
            ResultExtractor<T> extractor);

    /**
     * Submits an asynchronous request.
     *
     * @param <T>       type
     * @param request   Request
     * @param buffered  buffer the response?
     * @param extractor ResultExtractor for extracting a result out of a ClientResponse. Is run inside the io-thread
     * @return {@link CompletableFuture} with the result or Exception
     */
    default <T> CompletableFuture<T> submit(ClientInvocation request, boolean buffered, ResultExtractor<T> extractor) {
        return submit(request, buffered, extractor, null);
    }

    /**
     * Submits an asynchronous request.
     *
     * @param <T>             type
     * @param request         Request
     * @param buffered        buffer the response?
     * @param extractor       ResultExtractor for extracting a result out of a ClientResponse. Is run inside the io-thread
     * @param executorService the executor to use for asynchronous execution
     * @return {@link CompletableFuture} with the result or Exception
     */
    <T> CompletableFuture<T> submit(ClientInvocation request, boolean buffered, ResultExtractor<T> extractor,
            ExecutorService executorService);

}
