package org.restler.http;

import org.restler.util.Util;
import org.springframework.http.*;
import org.springframework.http.converter.GenericHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.web.client.AsyncRestTemplate;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

public class RestOperationsExecutor implements Executor {

    private final RestTemplate restTemplate;

    public RestOperationsExecutor(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
        restTemplate.getMessageConverters().add(new BodySavingMessageConverter());
    }

    public <T> ResponseEntity<T> execute(Request<T> executableRequest) {
        RequestEntity<?> requestEntity = executableRequest.toRequestEntity();

        AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate();
        asyncRestTemplate.getMessageConverters().add(new BodySavingMessageConverter());

        ListenableFuture<ResponseEntity<T>> future = asyncRestTemplate.exchange(executableRequest.toRequestEntity().getUrl(), executableRequest.toRequestEntity().getMethod(),
                requestEntity, executableRequest.getReturnType());

        return restTemplate.exchange(requestEntity, executableRequest.getReturnType());
    }

    private class BodySavingMessageConverter implements GenericHttpMessageConverter<Object> {
        @Override
        public boolean canRead(Type type, Class<?> contextClass, MediaType mediaType) {
            return true;
        }

        @Override
        public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
            return throwException(inputMessage);
        }

        @Override
        public boolean canRead(Class<?> clazz, MediaType mediaType) {
            return true;
        }

        @Override
        public boolean canWrite(Class<?> clazz, MediaType mediaType) {
            return true;
        }

        @Override
        public List<MediaType> getSupportedMediaTypes() {
           return new ArrayList<>();
        }

        @Override
        public Object read(Class<?> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
            return throwException(inputMessage);
        }

        private Object throwException(HttpInputMessage inputMessage) throws IOException {
            String responseBody = Util.toString(inputMessage.getBody());
            inputMessage.getBody().close();
            throw new HttpExecutionException(responseBody);
        }

        @Override
        public void write(Object o, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {

        }
    }
}

@@ -310,126 +310,8 @@
 on;%0A
-import org.springframework.util.concurrent.ListenableFuture;%0Aimport org.springframework.web.client.AsyncRestTemplate;%0A
 impo
@@ -358,16 +358,16 @@
 mplate;%0A
+
 %0Aimport 
@@ -925,412 +925,8 @@
 ();%0A
-%0A        AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate();%0A        asyncRestTemplate.getMessageConverters().add(new BodySavingMessageConverter());%0A%0A        ListenableFuture%3CResponseEntity%3CT%3E%3E future = asyncRestTemplate.exchange(executableRequest.toRequestEntity().getUrl(), executableRequest.toRequestEntity().getMethod(),%0A                requestEntity, executableRequest.getReturnType());%0A%0A
     
@@ -1797,24 +1797,25 @@
 iaTypes() %7B%0A
+ 
            r

Remove using AsyncRestTemplate in SimpleHttpRequesExecutor