package de.otto.edison.registry.client;

import com.ning.http.client.AsyncCompletionHandler;
import com.ning.http.client.AsyncHttpClient;
import com.ning.http.client.Response;
import de.otto.edison.annotations.Beta;
import de.otto.edison.registry.configuration.ServiceRegistryProperties;
import de.otto.edison.status.configuration.ApplicationInfoProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

import static java.util.Arrays.stream;
import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.springframework.util.StringUtils.isEmpty;

/**
 * Simple implementation of a RegistryClient using AsyncHttpClient to register the service.
 * <p>
 *     In order to use this class, a dependency to com.ning:async-http-client:1.9.40 or later must be added to your build.
 * </p>
 *
 * @author Guido Steinacker
 * @since 1.0.0
 */
@Component
@ConditionalOnProperty("edison.serviceregistry.servers")
@ConditionalOnClass(AsyncHttpClient.class)
@EnableConfigurationProperties(ServiceRegistryProperties.class)
@Beta
public class AsyncHttpRegistryClient implements RegistryClient {

    private static final Logger LOG = LoggerFactory.getLogger(AsyncHttpRegistryClient.class);

    @Value("${spring.application.name}")
    private String applicationName;

    @Autowired
    private AsyncHttpClient httpClient;
    @Autowired
    private ServiceRegistryProperties serviceRegistryProperties;
    @Autowired
    private ApplicationInfoProperties applicationInfoProperties;

    @PostConstruct
    public void postConstruct() {
        LOG.info("Scheduling registration at Edison JobTrigger every '{}' minutes.", serviceRegistryProperties.getRefreshAfter());
        newSingleThreadScheduledExecutor().scheduleWithFixedDelay(this::registerService, 0, serviceRegistryProperties.getRefreshAfter(), MINUTES);
    }

    @Override
    public void registerService() {
        stream(serviceRegistryProperties.getServers().split(","))
                .filter(server -> !isEmpty(server))
                .forEach(discoveryServer -> {
                    try {
                        LOG.debug("Updating registration of service at '{}'", discoveryServer);
                        httpClient
                                .preparePut(discoveryServer + "/environments/" + applicationInfoProperties.getEnvironment() + "/" + applicationName)
                                .setHeader("Content-Type", "application/vnd.otto.edison.links+json")
                                .setHeader("Accept", "application/vnd.otto.edison.links+json")
                                .setBody(
                                        "{\n" +
                                                "   \"groups\":[\"" + applicationInfoProperties.getGroup() + "\"],\n" +
                                                "   \"expire\":" + serviceRegistryProperties.getExpireAfter() + ",\n" +
                                                "   \"links\":[{\n" +
                                                "      \"rel\":\"http://github.com/otto-de/edison/link-relations/microservice\",\n" +
                                                "      \"href\" : \"" + serviceRegistryProperties.getService() + "\",\n" +
                                                "      \"title\":\"" + applicationName + "\"\n" +
                                                "   }]  \n" +
                                                "}"
                                )
                                .execute(new AsyncCompletionHandler<Integer>() {
                                    @Override
                                    public Integer onCompleted(final Response response) throws Exception {
                                        if (response.getStatusCode() < 300) {
                                            LOG.info("Successfully updated registration at " + discoveryServer);
                                        } else {
                                            LOG.warn("Failed to update registration at '{}': Status='{}' '{}'", discoveryServer, response.getStatusCode(), response.getStatusText());
                                        }
                                        return response.getStatusCode();
                                    }

                                    @Override
                                    public void onThrowable(final Throwable t) {
                                        LOG.error("Failed to register at '{}'", discoveryServer, t);
                                    }
                                });
                    } catch (final Exception e) {
                        LOG.error("Error updating registration", e);
                    }
                });
    }

}

@@ -343,32 +343,85 @@
 InfoProperties;%0A
+import de.otto.edison.status.domain.ApplicationInfo;%0A
 import org.slf4j
@@ -528,67 +528,8 @@
 ed;%0A
-import org.springframework.beans.factory.annotation.Value;%0A
 impo
@@ -1718,108 +1718,373 @@
     
-@Value(%22$%7Bspring.application.name%7D%22)%0A    private String applicationName;%0A%0A    @Autowired%0A    private
+private final ApplicationInfo applicationInfo;%0A    private final AsyncHttpClient httpClient;%0A    private final ServiceRegistryProperties serviceRegistryProperties;%0A    private final ApplicationInfoProperties applicationInfoProperties;%0A%0A    @Autowired%0A    public AsyncHttpRegistryClient(final ApplicationInfo applicationInfo,%0A                                   final
  Asy
@@ -2110,36 +2110,50 @@
 ient
-;
+,
 %0A    
-@Autowired%0A    private
+                               final
  Ser
@@ -2204,38 +2204,274 @@
 ties
-;
+,
 %0A    
-@Autowired%0A    private A
+                               final ApplicationInfoProperties applicationInfoProperties) %7B%0A        this.applicationInfo = applicationInfo;%0A        this.httpClient = httpClient;%0A        this.serviceRegistryProperties = serviceRegistryProperties;%0A        this.a
 ppli
@@ -2482,32 +2482,34 @@
 onInfoProperties
+ =
  applicationInfo
@@ -2515,24 +2515,30 @@
 oProperties;
+%0A    %7D
 %0A%0A    @PostC
@@ -3379,17 +3379,22 @@
 lication
-N
+Info.n
 ame)%0A   
@@ -4325,17 +4325,22 @@
 lication
-N
+Info.n
 ame + %22%5C

use ApplicationInfo instead of @Value