package io.freefair.spring.okhttp;

import okhttp3.OkHttpClient;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.condition.NoneNestedConditions;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.boot.web.client.RestTemplateCustomizer;
import org.springframework.boot.web.client.RestTemplateRequestCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import java.util.Collection;
import java.util.List;
import java.util.function.BiFunction;
import java.util.stream.Collectors;

/**
 * @author Lars Grefer
 * @see RestTemplateAutoConfiguration
 */
@AutoConfiguration(before = RestTemplateAutoConfiguration.class, after = HttpMessageConvertersAutoConfiguration.class)
@ConditionalOnClass({RestTemplateCustomizer.class, RestTemplate.class})
@Conditional(OkHttpRestTemplateAutoConfiguration.NotReactiveWebApplicationCondition.class)
public class OkHttpRestTemplateAutoConfiguration {

    @Bean
    @Lazy
    @ConditionalOnMissingBean
    public RestTemplateBuilder restTemplateBuilder(ObjectProvider<HttpMessageConverters> messageConverters,
                                                   ObjectProvider<RestTemplateCustomizer> restTemplateCustomizers,
                                                   ObjectProvider<RestTemplateRequestCustomizer<?>> restTemplateRequestCustomizers,
                                                   OkHttpClient okHttpClient) {
        RestTemplateBuilder builder = new RestTemplateBuilder();
        HttpMessageConverters converters = messageConverters.getIfUnique();
        if (converters != null) {
            builder = builder.messageConverters(converters.getConverters());
        }
        builder = addCustomizers(builder, restTemplateCustomizers, RestTemplateBuilder::customizers);
        builder = addCustomizers(builder, restTemplateRequestCustomizers, RestTemplateBuilder::requestCustomizers);

        builder = builder.requestFactory(() -> new OkHttp3ClientHttpRequestFactory(okHttpClient));

        return builder;
    }

    private <T> RestTemplateBuilder addCustomizers(RestTemplateBuilder builder, ObjectProvider<T> objectProvider,
                                                   BiFunction<RestTemplateBuilder, Collection<T>, RestTemplateBuilder> method) {
        List<T> customizers = objectProvider.orderedStream().collect(Collectors.toList());
        if (!customizers.isEmpty()) {
            return method.apply(builder, customizers);
        }
        return builder;
    }

    static class NotReactiveWebApplicationCondition extends NoneNestedConditions {

        NotReactiveWebApplicationCondition() {
            super(ConfigurationPhase.PARSE_CONFIGURATION);
        }

        @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
        private static class ReactiveWebApplication {

        }

    }

}

@@ -62,65 +62,8 @@
 nt;%0A
-import org.springframework.beans.factory.ObjectProvider;%0A
 impo
@@ -448,82 +448,8 @@
 ns;%0A
-import org.springframework.boot.autoconfigure.http.HttpMessageConverters;%0A
 impo
@@ -615,32 +615,120 @@
 oConfiguration;%0A
+import org.springframework.boot.autoconfigure.web.client.RestTemplateBuilderConfigurer;%0A
 import org.sprin
@@ -846,82 +846,8 @@
 er;%0A
-import org.springframework.boot.web.client.RestTemplateRequestCustomizer;%0A
 impo
@@ -1134,135 +1134,8 @@
 e;%0A%0A
-import java.util.Collection;%0Aimport java.util.List;%0Aimport java.util.function.BiFunction;%0Aimport java.util.stream.Collectors;%0A%0A
 /**%0A
@@ -1638,310 +1638,67 @@
 der(
-ObjectProvider%3CHttpMessageConverters%3E messageConverters,%0A                                                   ObjectProvider%3CRestTemplateCustomizer%3E restTemplateCustomizers,%0A                                                   ObjectProvider%3CRestTemplateRequestCustomizer%3C?%3E%3E restTemplateRequestCustomiz
+RestTemplateBuilderConfigurer restTemplateBuilderConfigur
 er
-s
 ,%0A  
@@ -1844,424 +1844,8 @@
 ();%0A
-        HttpMessageConverters converters = messageConverters.getIfUnique();%0A        if (converters != null) %7B%0A            builder = builder.messageConverters(converters.getConverters());%0A        %7D%0A        builder = addCustomizers(builder, restTemplateCustomizers, RestTemplateBuilder::customizers);%0A        builder = addCustomizers(builder, restTemplateRequestCustomizers, RestTemplateBuilder::requestCustomizers);%0A%0A
     
@@ -1939,17 +1939,16 @@
 ient));%0A
-%0A
         
@@ -1958,483 +1958,56 @@
 urn 
-builder;%0A    %7D%0A%0A    private %3CT%3E RestTemplateBuilder addCustomizers(RestTemplateBuilder builder, ObjectProvider%3CT%3E objectProvider,%0A                                                   BiFunction%3CRestTemplateBuilder, Collection%3CT%3E, RestTemplateBuilder%3E method) %7B%0A        List%3CT%3E customizers = objectProvider.orderedStream().collect(Collectors.toList());%0A        if (!customizers.isEmpty()) %7B%0A            return method.apply(builder, customizers);%0A        %7D%0A        return builder
+restTemplateBuilderConfigurer.configure(builder)
 ;%0A  

Improve RestTemplateAutoConfiguration