package io.vertxbeans;

import io.vertx.core.AsyncResultHandler;
import io.vertx.core.VertxOptions;
import io.vertx.core.metrics.MetricsOptions;
import io.vertx.core.spi.cluster.ClusterManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;

import static java.util.concurrent.TimeUnit.MINUTES;

/**
 * Created by Rob Worsnop on 9/5/15.
 */
public class VertxBeansBase {
    @Autowired(required = false)
    private ClusterManager clusterManager;

    @Autowired(required = false)
    private MetricsOptions metricsOptions;

    @Autowired
    private Environment env;

    @Bean
    protected VertxOptions vertxOptions() {
        VertxOptions options = new VertxOptions();

        setParameter(env.getProperty("vertx.warning-exception-time", Long.class), options::setWarningExceptionTime);
        setParameter(env.getProperty("vertx.event-loop-pool-size", Integer.class), options::setEventLoopPoolSize);
        setParameter(env.getProperty("vertx.max-event-loop-execution-time", Long.class), options::setMaxEventLoopExecuteTime);
        setParameter(env.getProperty("vertx.worker-pool-size", Integer.class), options::setWorkerPoolSize);
        setParameter(env.getProperty("vertx.max-worker-execution-time", Long.class), options::setMaxWorkerExecuteTime);
        setParameter(env.getProperty("vertx.blocked-thread-check-interval", Long.class), options::setBlockedThreadCheckInterval);
        setParameter(env.getProperty("vertx.internal-blocking-pool-size", Integer.class), options::setInternalBlockingPoolSize);
        options.setHAEnabled(env.getProperty("vertx.ha-enabled",Boolean.class, false));
        setParameter(env.getProperty("vertx.ha-group", ""), options::setHAGroup);
        setParameter(env.getProperty("vertx.quorum-size", Integer.class), options::setQuorumSize);
        options.setClustered(env.getProperty("vertx.clustered", Boolean.class, false));
        options.setClusterHost(env.getProperty("vertx.cluster-host", "localhost"));
        setParameter(env.getProperty("vertx.cluster-port", Integer.class), options::setClusterPort);
        setParameter(env.getProperty("vertx.cluster-ping-interval", Long.class), options::setClusterPingInterval);
        setParameter(env.getProperty("vertx.cluster-ping-reply-interval", Long.class), options::setClusterPingReplyInterval);
        setParameter(clusterManager, options::setClusterManager);
        setParameter(metricsOptions, options::setMetricsOptions);
        
        return options;
    }

    protected <T> T clusteredVertx(Consumer<AsyncResultHandler<T>> consumer) throws InterruptedException, ExecutionException, TimeoutException {
        CompletableFuture<T> future = new CompletableFuture<>();
        clusteredVertx(consumer, ar -> {
            if (ar.succeeded()){
                future.complete(ar.result());
            } else{
                future.completeExceptionally(ar.cause());
            }
        });
        return future.get(2, MINUTES);
    }

    private <T> void clusteredVertx(Consumer<AsyncResultHandler<T>> consumer, AsyncResultHandler<T> handler){
        consumer.accept(handler);
    }

    private <T> void setParameter(T param, Consumer<T> setter){
        if (param != null){
            setter.accept(param);
        }
    }

}

@@ -85,32 +85,113 @@
 e.VertxOptions;%0A
+import io.vertx.core.logging.Logger;%0Aimport io.vertx.core.logging.LoggerFactory;%0A
 import io.vertx.
@@ -433,16 +433,172 @@
 nment;%0A%0A
+import java.net.Inet6Address;%0Aimport java.net.InetAddress;%0Aimport java.net.NetworkInterface;%0Aimport java.net.SocketException;%0Aimport java.util.Enumeration;%0A
 import j
@@ -896,16 +896,103 @@
 sBase %7B%0A
+%0A    private static final Logger log = LoggerFactory.getLogger(VertxBeansBase.class);%0A%0A
     @Aut
@@ -2198,16 +2198,17 @@
 nabled%22,
+ 
 Boolean.
@@ -2565,19 +2565,27 @@
 t%22, 
-%22localhost%22
+getDefaultAddress()
 ));%0A
@@ -3058,24 +3058,16 @@
 tions);%0A
-        
 %0A       
@@ -3372,16 +3372,17 @@
 eeded())
+ 
 %7B%0A      
@@ -3439,16 +3439,17 @@
   %7D else
+ 
 %7B%0A      
@@ -3680,16 +3680,17 @@
 handler)
+ 
 %7B%0A      
@@ -3786,16 +3786,17 @@
  setter)
+ 
 %7B%0A      
@@ -3815,16 +3815,17 @@
 != null)
+ 
 %7B%0A      
@@ -3869,10 +3869,1028 @@
 %0A    %7D%0A%0A
+    private String getDefaultAddress() %7B%0A        Enumeration%3CNetworkInterface%3E nets;%0A        try %7B%0A            nets = NetworkInterface.getNetworkInterfaces();%0A        %7D catch (SocketException e) %7B%0A            log.warn(%22Unable to determine network interfaces. Using %5C%22localhost%5C%22 as host address.%22, e);%0A            return %22localhost%22;%0A        %7D%0A        NetworkInterface netinf;%0A        while (nets.hasMoreElements()) %7B%0A            netinf = nets.nextElement();%0A            Enumeration%3CInetAddress%3E addresses = netinf.getInetAddresses();%0A            while (addresses.hasMoreElements()) %7B%0A                InetAddress address = addresses.nextElement();%0A                if (!address.isAnyLocalAddress() && !address.isMulticastAddress()%0A                        && !(address instanceof Inet6Address)) %7B%0A                    return address.getHostAddress();%0A                %7D%0A            %7D%0A        %7D%0A        log.info(%22Couldn't determine the network host. Using %5C%22localhost%5C%22 as host address%22);%0A        return %22localhost%22;%0A    %7D%0A
 %7D%0A

Set the host automatically when cluster-host isn't defined explicitly