package org.zalando.riptide.spring;

import com.codahale.metrics.MetricRegistry;
import lombok.AllArgsConstructor;
import org.springframework.boot.actuate.metrics.GaugeService;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Scheduled;
import org.zalando.riptide.metrics.MetricsPlugin;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.DEFAULT_TASK_SCHEDULER_BEAN_NAME;

@Configuration
@AutoConfigureAfter(name = {
        "org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration",
        "org.zalando.logbook.spring.LogbookAutoConfiguration",
        "org.zalando.tracer.spring.TracerAutoConfiguration",
        "org.zalando.tracer.spring.TracerSchedulingAutoConfiguration",
})
public class RiptideAutoConfiguration {

    @Bean
    public static RiptidePostProcessor restClientPostProcessor() {
        return new RiptidePostProcessor(DefaultRiptideRegistrar::new);
    }

    @Configuration
    @ConditionalOnClass(MetricsPlugin.class)
    @ConditionalOnMissingBean(MetricsPlugin.class)
    @ConditionalOnBean(MetricRegistry.class)
    static class MetricsConfiguration {

        @Bean
        @SuppressWarnings("SpringJavaAutowiringInspection")
        public MetricsPlugin metricsPlugin(final MetricRegistry registry) {
            final MetricsGaugeService gaugeService = new MetricsGaugeService(registry);
            final ZMONMetricsNameGenerator nameGenerator = new ZMONMetricsNameGenerator();
            return new MetricsPlugin(gaugeService, nameGenerator);
        }

        @AllArgsConstructor
        private static class MetricsGaugeService implements GaugeService {

            private final MetricRegistry registry;

            @Override
            public void submit(final String metricName, final double value) {
                registry.timer(metricName).update((long) value, MILLISECONDS);
            }

        }

    }

    @Configuration
    @ConditionalOnClass(Scheduled.class)
    @AutoConfigureAfter(name = {
            "org.zalando.tracer.spring.TracerAutoConfiguration",
            "org.zalando.tracer.spring.TracerSchedulingAutoConfiguration"
    })
    @AutoConfigureBefore(name = "org.springframework.scheduling.annotation.SchedulingConfiguration")
    static class SchedulingAutoConfiguration {

        @Bean(name = DEFAULT_TASK_SCHEDULER_BEAN_NAME, destroyMethod = "shutdown")
        @ConditionalOnMissingBean(name = DEFAULT_TASK_SCHEDULER_BEAN_NAME)
        public ScheduledExecutorService taskScheduler() {
            final int corePoolSize = Runtime.getRuntime().availableProcessors();
            return Executors.newScheduledThreadPool(corePoolSize);
        }

    }

}

@@ -1361,18 +1361,151 @@
 ration%22,
-%0A%7D
+  // only needed for tracer %3C 0.12.0%0A%7D)%0A@AutoConfigureBefore(name = %22org.springframework.scheduling.annotation.SchedulingConfiguration%22
 )%0Apublic
@@ -2734,288 +2734,8 @@
 ss)%0A
-    @AutoConfigureAfter(name = %7B%0A            %22org.zalando.tracer.spring.TracerAutoConfiguration%22,%0A            %22org.zalando.tracer.spring.TracerSchedulingAutoConfiguration%22%0A    %7D)%0A    @AutoConfigureBefore(name = %22org.springframework.scheduling.annotation.SchedulingConfiguration%22)%0A
     

Move configuration directives